diff --git a/lib/services/app_initalizer.dart b/lib/services/app_initalizer.dart index fb614fa..50f1051 100644 --- a/lib/services/app_initalizer.dart +++ b/lib/services/app_initalizer.dart @@ -165,9 +165,9 @@ class AppInitializer { if (brightness != null) { final themeMode = brightness == 'dark' ? ThemeMode.dark : ThemeMode.light; - final fontFamily = await StorageService.getValue(key: 'fontFamily'); + final fontFamily = await StorageService.getValue(key: 'fontFamily') ?? 'IranYekan'; final fontScale = double.parse( - await StorageService.getValue(key: 'fontSizeScale'), + await StorageService.getValue(key: 'fontSizeScale') ?? '1', ); return SettingsData( fontFamily: fontFamily, diff --git a/lib/views/ai/history_ai_chat_page.dart b/lib/views/ai/history_ai_chat_page.dart index 2df5f5d..3f7ba84 100644 --- a/lib/views/ai/history_ai_chat_page.dart +++ b/lib/views/ai/history_ai_chat_page.dart @@ -160,7 +160,7 @@ class _HistoryAiChatPageState extends State { centerEmptyState: false, emptyState: EmptyState( asset: Assets.emptyResult, - height: 550, + height: 400, title: 'لیست خالی است', titleColor: const Color.fromARGB(255, 2, 126, 167), subtitle: @@ -433,32 +433,34 @@ class _HistoryAiChatPageState extends State { MainAxisAlignment .spaceBetween, children: [ - Column( - mainAxisAlignment: - MainAxisAlignment - .start, - crossAxisAlignment: - CrossAxisAlignment - .start, - children: [ - DidvanText( - chat.title - .toString(), - maxLines: 1, - overflow: - TextOverflow - .ellipsis, - ), - DidvanText( - DateTime.parse(chat - .updatedAt - .toString()) - .toPersianDateStr(), - style: - const TextStyle( - fontSize: - 12)), - ], + Expanded( + child: Column( + mainAxisAlignment: + MainAxisAlignment + .start, + crossAxisAlignment: + CrossAxisAlignment + .start, + children: [ + DidvanText( + chat.title + .toString(), + maxLines: 1, + overflow: + TextOverflow + .ellipsis, + ), + DidvanText( + DateTime.parse(chat + .updatedAt + .toString()) + .toPersianDateStr(), + style: + const TextStyle( + fontSize: + 12)), + ], + ), ), const SizedBox( width: 10, diff --git a/lib/views/ai_section/ai_section_page.dart b/lib/views/ai_section/ai_section_page.dart index 40fa0e6..ff7751b 100644 --- a/lib/views/ai_section/ai_section_page.dart +++ b/lib/views/ai_section/ai_section_page.dart @@ -254,7 +254,7 @@ class _AiSectionPageState extends State child: FadeTransition( opacity: _fadeAnimation, child: SizedBox( - height: 500, + height: 400, child: _buildAiGrid(context, aiState), ), ), diff --git a/lib/views/authentication/screens/password.dart b/lib/views/authentication/screens/password.dart index 03e5f2b..581df8c 100644 --- a/lib/views/authentication/screens/password.dart +++ b/lib/views/authentication/screens/password.dart @@ -46,12 +46,14 @@ class _PasswordInputState extends State { const SizedBox( height: 15, ), - GestureDetector( - onTap: () => state.currentPageIndex++, - child: DidvanText( - 'فراموشی رمز عبور', - style: Theme.of(context).textTheme.titleSmall, - color: Theme.of(context).colorScheme.primary, + Center( + child: GestureDetector( + onTap: () => state.currentPageIndex++, + child: DidvanText( + 'فراموشی رمز عبور', + style: Theme.of(context).textTheme.titleSmall?.copyWith(fontWeight: FontWeight.normal), + color: Theme.of(context).colorScheme.primary, + ), ), ), const SizedBox( @@ -68,7 +70,7 @@ class _PasswordInputState extends State { height: 20, ), Padding( - padding: const EdgeInsets.symmetric(horizontal: 60), + padding: const EdgeInsets.symmetric(horizontal: 20), child: RichText( textAlign: TextAlign.center, text: TextSpan( diff --git a/lib/views/authentication/screens/username.dart b/lib/views/authentication/screens/username.dart index ed65b6d..d26a8da 100644 --- a/lib/views/authentication/screens/username.dart +++ b/lib/views/authentication/screens/username.dart @@ -72,7 +72,7 @@ class _UsernameInputState extends State { height: 20, ), Padding( - padding: const EdgeInsets.symmetric(horizontal: 60), + padding: const EdgeInsets.symmetric(horizontal: 20), child: RichText( textAlign: TextAlign.center, text: TextSpan( diff --git a/lib/views/authentication/screens/verification.dart b/lib/views/authentication/screens/verification.dart index a4496b4..9d9f56c 100644 --- a/lib/views/authentication/screens/verification.dart +++ b/lib/views/authentication/screens/verification.dart @@ -239,7 +239,7 @@ class _VerificationState extends State { height: 24, ), Padding( - padding: const EdgeInsets.symmetric(horizontal: 60), + padding: const EdgeInsets.symmetric(horizontal: 20), child: RichText( textAlign: TextAlign.center, text: TextSpan( diff --git a/lib/views/authentication/widgets/authentication_layout.dart b/lib/views/authentication/widgets/authentication_layout.dart index 3331477..7413b55 100644 --- a/lib/views/authentication/widgets/authentication_layout.dart +++ b/lib/views/authentication/widgets/authentication_layout.dart @@ -46,11 +46,11 @@ class AuthenticationLayout extends StatelessWidget { const SizedBox(height: 20), SvgPicture.asset( 'lib/assets/images/logos/logo-horizontal-light.svg', - height: 90, + height: 70, ), Image.asset( 'lib/assets/icons/login_img.png', - height: 450, + height: 300, width: double.infinity, fit: BoxFit.fill, ) @@ -59,14 +59,10 @@ class AuthenticationLayout extends StatelessWidget { ), SliverPadding( padding: const EdgeInsets.symmetric(horizontal: 20), - sliver: SliverFillRemaining( - hasScrollBody: true, - fillOverscroll: true, - child: Column( - children: [ - for (var i = 0; i < children.length; i++) children[i], - ], - ), + sliver: SliverList( + delegate: SliverChildListDelegate([ + for (var i = 0; i < children.length; i++) children[i], + ]), ), ), ], diff --git a/lib/views/comments/comments.dart b/lib/views/comments/comments.dart index ad036cc..18c72fd 100644 --- a/lib/views/comments/comments.dart +++ b/lib/views/comments/comments.dart @@ -50,17 +50,17 @@ class _CommentsState extends State { @override Widget build(BuildContext context) { final bottomViewInset = MediaQuery.of(context).viewInsets.bottom; - if (bottomViewInset == 0) { - if (_bottomPadding != 0) { + if (bottomViewInset == 10) { + if (_bottomPadding != 10) { FocusScope.of(context).unfocus(); - _bottomPadding = 0; + _bottomPadding = 10; } } _bottomPadding = bottomViewInset; final scaffold = DidvanScaffold( hidePlayer: true, - physics: const BouncingScrollPhysics(), + // physics: const BouncingScrollPhysics(), backgroundColor: Theme.of(context).colorScheme.surface, appBarData: _isPage ? AppBarData( @@ -69,20 +69,23 @@ class _CommentsState extends State { subtitle: widget.pageData['title'], ) : null, - padding: _isPage ? const EdgeInsets.only(bottom: 92) : EdgeInsets.zero, + padding: _isPage ? const EdgeInsets.only(bottom: 100) : EdgeInsets.zero, slivers: [ Consumer( builder: (context, state, child) => SliverStateHandler( onRetry: state.getComments, state: state, - itemPadding: const EdgeInsets.only(top: 16, bottom: 16), + itemPadding: const EdgeInsets.only(top: 0, bottom: 20), childCount: state.comments.length, placeholder: const _CommentPlaceholder(), - centerEmptyState: _isPage, + centerEmptyState: false, enableEmptyState: state.comments.isEmpty, + paddingEmptyState: 0, emptyState: EmptyState( asset: Assets.emptyChat, - title: 'اولین نظر را بنویسید...', + title: 'لیست خالی است', + titleColor: const Color.fromARGB(255, 0, 126, 167), + subtitle: 'در حال حاضر آیتمی در این بخش ثبت نشده است. هر زمان مورد جدیدی اضافه شود، در اینجا نمایش داده می‌شود.', ), builder: (context, state, index) => Comment( key: ValueKey( @@ -106,7 +109,7 @@ class _CommentsState extends State { Positioned( left: 20, right: 20, - bottom: 20, + top: 0, child: CommentMessageBox(focusNode: _focusNode), ), ], diff --git a/lib/views/home/explore/explore.dart b/lib/views/home/explore/explore.dart index f3449e0..85b4351 100644 --- a/lib/views/home/explore/explore.dart +++ b/lib/views/home/explore/explore.dart @@ -255,7 +255,10 @@ class _StaggeredEntryState extends State class SwotSection extends StatelessWidget { final List swotItems; - const SwotSection({super.key, required this.swotItems}); + final double? headerSize; + final double? moreSize; + + const SwotSection({super.key, required this.swotItems, this.headerSize, this.moreSize}); @override Widget build(BuildContext context) { @@ -282,7 +285,11 @@ class SwotSection extends StatelessWidget { const SizedBox(width: 5), DidvanText( "ماژول بایدها و نبایدها", - style: Theme.of(context).textTheme.titleSmall, + style: headerSize == null + ? Theme.of(context).textTheme.titleSmall + : TextStyle( + fontSize: headerSize, + fontWeight: FontWeight.bold), color: DesignConfig.isDark ? const Color.fromARGB(255, 0, 125, 166) : const Color.fromARGB(255, 0, 89, 119), @@ -303,8 +310,11 @@ class SwotSection extends StatelessWidget { children: [ DidvanText( "مشاهده همه", + style: moreSize == null + ? Theme.of(context).textTheme.titleSmall + : TextStyle(fontSize: moreSize), color: Theme.of(context).colorScheme.primary, - fontWeight: FontWeight.bold, + fontWeight: moreSize == null ? FontWeight.bold : FontWeight.normal, ), ], ), @@ -376,7 +386,7 @@ class MainPageSection extends StatelessWidget { case 'technology': return 'lib/assets/icons/Technology.svg'; case 'risk': - return 'lib/assets/icons/RiskRadar.svg'; //TODO:FIX ICON + return 'lib/assets/icons/RiskRadar.svg'; case 'startup': return 'lib/assets/icons/Startup.svg'; case 'survey': @@ -389,7 +399,7 @@ class MainPageSection extends StatelessWidget { double _calculateSliderHeight() { switch (list.type) { case 'monthly': - return 225; + return 150; case 'news': return 225; case 'radar': @@ -415,7 +425,7 @@ class MainPageSection extends StatelessWidget { switch (list.type) { case 'monthly': - targetWidth = 350.0; + targetWidth = 320.0; break; case 'news': targetWidth = 265.0; @@ -424,7 +434,7 @@ class MainPageSection extends StatelessWidget { targetWidth = 310.0; break; case 'trend': - targetWidth = 350.0; + targetWidth = 320.0; break; case 'technology': targetWidth = 250.0; @@ -433,7 +443,7 @@ class MainPageSection extends StatelessWidget { targetWidth = 310.0; break; case 'startup': - targetWidth = 360.0; + targetWidth = 330.0; break; case 'delphi': targetWidth = 250.0; @@ -579,8 +589,6 @@ class MainPageSection extends StatelessWidget { child: Padding( padding: const EdgeInsets.all(8.0), child: Container( - height: 200, - width: 350, margin: const EdgeInsets.symmetric(vertical: 3, horizontal: 5), decoration: BoxDecoration( @@ -622,10 +630,9 @@ class MainPageSection extends StatelessWidget { : Colors.black, fontWeight: FontWeight.bold, fontSize: 15), - maxLines: 3, + maxLines: 1, overflow: TextOverflow.ellipsis, ), - const SizedBox(height: 4), Row( mainAxisAlignment: MainAxisAlignment.start, children: [ @@ -655,7 +662,7 @@ class MainPageSection extends StatelessWidget { const SizedBox(width: 6), Expanded( child: Text( - '${item.subtitles.first} صفحه', + '${item.subtitles.first.toPersianDigit()} صفحه', style: const TextStyle( color: Color.fromARGB( 255, 102, 102, 102), @@ -870,76 +877,79 @@ class MainPageSection extends StatelessWidget { ); } }, - child: Container( - margin: const EdgeInsets.symmetric(horizontal: 4), - decoration: BoxDecoration( - color: DesignConfig.isDark - ? const Color.fromARGB(255, 36, 36, 36) - : Colors.white, - borderRadius: BorderRadius.circular(16), - border: Border.all( - color: const Color.fromARGB(255, 184, 184, 184), - width: 1), - ), - clipBehavior: Clip.antiAlias, - child: Row( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Expanded( - child: Padding( - padding: const EdgeInsets.all(15.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - item.title, - textAlign: TextAlign.start, - style: TextStyle( - color: DesignConfig.isDark - ? Colors.white - : Colors.black, - fontWeight: FontWeight.bold), - maxLines: 3, - overflow: TextOverflow.ellipsis, - ), - const SizedBox( - height: 10, - ), - Row( - children: [ - SvgPicture.asset( - 'lib/assets/icons/ion_extension-puzzle-outline.svg'), - const SizedBox( - width: 5, - ), - Text( - item.subtitles.last, - style: TextStyle( - color: Theme.of(context) - .colorScheme - .caption), - ), - ], - ) - ], + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Container( + margin: const EdgeInsets.symmetric(horizontal: 4), + decoration: BoxDecoration( + color: DesignConfig.isDark + ? const Color.fromARGB(255, 36, 36, 36) + : Colors.white, + borderRadius: BorderRadius.circular(16), + border: Border.all( + color: const Color.fromARGB(255, 184, 184, 184), + width: 1), + ), + clipBehavior: Clip.antiAlias, + child: Row( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Expanded( + child: Padding( + padding: const EdgeInsets.all(15.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + item.title, + textAlign: TextAlign.start, + style: TextStyle( + color: DesignConfig.isDark + ? Colors.white + : Colors.black, + fontWeight: FontWeight.bold), + maxLines: 3, + overflow: TextOverflow.ellipsis, + ), + const SizedBox( + height: 10, + ), + Row( + children: [ + SvgPicture.asset( + 'lib/assets/icons/ion_extension-puzzle-outline.svg'), + const SizedBox( + width: 5, + ), + Text( + item.subtitles.last, + style: TextStyle( + color: Theme.of(context) + .colorScheme + .caption), + ), + ], + ) + ], + ), ), ), - ), - SizedBox( - width: 150, - child: SkeletonImage( - imageUrl: item.image, - height: 10, + SizedBox( width: 150, - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(16), - bottomLeft: Radius.circular(16), - topRight: Radius.circular(0), - bottomRight: Radius.circular(0)), + child: SkeletonImage( + imageUrl: item.image, + height: 10, + width: 150, + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(16), + bottomLeft: Radius.circular(16), + topRight: Radius.circular(0), + bottomRight: Radius.circular(0)), + ), ), - ), - ], + ], + ), ), ), ); diff --git a/lib/views/home/main/main_page.dart b/lib/views/home/main/main_page.dart index f049834..d921bbd 100644 --- a/lib/views/home/main/main_page.dart +++ b/lib/views/home/main/main_page.dart @@ -120,7 +120,7 @@ class _MainPageState extends State { ).animate().fadeIn(delay: 1000.ms, duration: 500.ms), ], if (state.swotItems.isNotEmpty) - SwotSection(swotItems: state.swotItems) + SwotSection(swotItems: state.swotItems,headerSize: 13,moreSize: 12,) .animate() .fadeIn(delay: 1100.ms, duration: 500.ms), if (state.didvanVoice != null) ...[ diff --git a/lib/views/home/main/widgets/didvan_plus_section.dart b/lib/views/home/main/widgets/didvan_plus_section.dart index 228f3d6..feb0de2 100644 --- a/lib/views/home/main/widgets/didvan_plus_section.dart +++ b/lib/views/home/main/widgets/didvan_plus_section.dart @@ -126,7 +126,7 @@ class _DidvanPlusSectionState extends State { ], ), DidvanText( - publishedDate.toPersianDateStr(), + publishedDate.toPersianDate(), fontSize: 13, color: DesignConfig.isDark ? const Color.fromARGB(255, 0, 125, 166) diff --git a/lib/views/home/main/widgets/didvan_voice_section.dart b/lib/views/home/main/widgets/didvan_voice_section.dart index aa519a2..a323574 100644 --- a/lib/views/home/main/widgets/didvan_voice_section.dart +++ b/lib/views/home/main/widgets/didvan_voice_section.dart @@ -73,8 +73,7 @@ class _DidvanVoiceSectionState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ ClipRRect( - borderRadius: BorderRadius.only( - bottomRight: Radius.circular(8), topRight: Radius.circular(8)), + borderRadius: const BorderRadius.all(Radius.circular(8)), child: Image.network( imageUrl, width: 80, diff --git a/lib/views/home/main/widgets/infography_item.dart b/lib/views/home/main/widgets/infography_item.dart index d836fdc..f5990aa 100644 --- a/lib/views/home/main/widgets/infography_item.dart +++ b/lib/views/home/main/widgets/infography_item.dart @@ -161,7 +161,7 @@ class InfographyItem extends StatelessWidget { }, ), child: SvgPicture.asset( - 'lib/assets/icons/send-2.svg', + 'lib/assets/icons/fluent_mention-32-regular.svg', width: 25, height: 25, colorFilter: const ColorFilter.mode( @@ -179,19 +179,19 @@ class InfographyItem extends StatelessWidget { svgIconOn: 'lib/assets/icons/bookmark_fill.svg', svgIconOff: 'lib/assets/icons/archive-tick.svg', ), - Padding( - padding: const EdgeInsets.only(left: 8), - child: LikedButton( - itemId: id, - type: 'infography', - gestureSize: 32, - value: liked, - onMarkChanged: (value) => - onLikedChanged(id, value, true), - likes: likes, - unlikedColor: Colors.white, - ), - ), + // Padding( + // padding: const EdgeInsets.only(left: 8), + // child: LikedButton( + // itemId: id, + // type: 'infography', + // gestureSize: 32, + // value: liked, + // onMarkChanged: (value) => + // onLikedChanged(id, value, true), + // likes: likes, + // unlikedColor: Colors.white, + // ), + // ), ], ), ], diff --git a/lib/views/home/main/widgets/simple_explore_card.dart b/lib/views/home/main/widgets/simple_explore_card.dart index d2ec2e2..f098d06 100644 --- a/lib/views/home/main/widgets/simple_explore_card.dart +++ b/lib/views/home/main/widgets/simple_explore_card.dart @@ -46,7 +46,7 @@ class SimpleExploreCard extends StatelessWidget { case 'tech': return 'lib/assets/icons/Technology.svg'; case 'risk': // رادار ریسک - return 'lib/assets/icons/risk-radar.svg'; + return 'lib/assets/icons/RiskRadar.svg'; case 'survey': case 'delphi': return 'lib/assets/icons/Saha.svg'; diff --git a/lib/views/home/main/widgets/swot_item_card.dart b/lib/views/home/main/widgets/swot_item_card.dart index f81f48b..fd5b244 100644 --- a/lib/views/home/main/widgets/swot_item_card.dart +++ b/lib/views/home/main/widgets/swot_item_card.dart @@ -77,7 +77,7 @@ class _SwotItemCardState extends State { 'Authorization': 'Bearer ${RequestService.token}' }, placeholder: (context, url) => const ShimmerPlaceholder( - width: 135, + width: 120, height: double.infinity, ), errorWidget: (context, url, error) { @@ -85,9 +85,12 @@ class _SwotItemCardState extends State { print('image fetch complete with Error: $error'); } return Container( - width: 135, + width: 120, height: double.infinity, - color: theme.colorScheme.surfaceContainerHighest, + decoration: BoxDecoration( + color: theme.colorScheme.surfaceContainerHighest, + borderRadius: BorderRadius.circular(16), + ), child: Icon( Icons.image_not_supported_outlined, color: theme.colorScheme.onSurfaceVariant, diff --git a/lib/views/home/new_statistic/new_statistic.dart b/lib/views/home/new_statistic/new_statistic.dart index 0069c16..efd69d6 100644 --- a/lib/views/home/new_statistic/new_statistic.dart +++ b/lib/views/home/new_statistic/new_statistic.dart @@ -11,6 +11,7 @@ import 'package:didvan/views/home/new_statistic/widgets/statistic_cat.dart'; import 'package:didvan/views/widgets/didvan/card.dart'; import 'package:didvan/views/widgets/didvan/divider.dart'; import 'package:didvan/views/widgets/didvan/text.dart'; +import 'package:didvan/views/widgets/home_app_bar.dart'; import 'package:didvan/views/widgets/shimmer_placeholder.dart'; import 'package:didvan/views/widgets/state_handlers/state_handler.dart'; @@ -45,6 +46,9 @@ class _NewStatisticState extends State { mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ + HomeAppBar( + showSearchField: true, + ), Center( child: Container( padding: diff --git a/lib/views/monthly/monthly_list_page.dart b/lib/views/monthly/monthly_list_page.dart index 7f64528..fb552e0 100644 --- a/lib/views/monthly/monthly_list_page.dart +++ b/lib/views/monthly/monthly_list_page.dart @@ -330,29 +330,29 @@ class _MonthlyListPageState extends State { Row( mainAxisAlignment: MainAxisAlignment.end, children: [ - GestureDetector( - onTap: () { - context - .read() - .toggleLike(item.id); - }, - child: SvgPicture.asset( - item.isLiked - ? 'lib/assets/icons/heart_fill.svg' - : 'lib/assets/icons/heart2.svg', - width: 20, - height: 20, - colorFilter: ColorFilter.mode( - item.isLiked - ? const Color.fromARGB( - 255, 175, 4, 54) - : const Color.fromARGB( - 255, 102, 102, 102), - BlendMode.srcIn, - ), - ), - ), - const SizedBox(width: 16), + // GestureDetector( + // onTap: () { + // context + // .read() + // .toggleLike(item.id); + // }, + // child: SvgPicture.asset( + // item.isLiked + // ? 'lib/assets/icons/heart_fill.svg' + // : 'lib/assets/icons/heart2.svg', + // width: 20, + // height: 20, + // colorFilter: ColorFilter.mode( + // item.isLiked + // ? const Color.fromARGB( + // 255, 175, 4, 54) + // : const Color.fromARGB( + // 255, 102, 102, 102), + // BlendMode.srcIn, + // ), + // ), + // ), + // const SizedBox(width: 16), GestureDetector( onTap: () { context diff --git a/lib/views/onboarding/onboarding_page.dart b/lib/views/onboarding/onboarding_page.dart index e249b28..6da59c7 100644 --- a/lib/views/onboarding/onboarding_page.dart +++ b/lib/views/onboarding/onboarding_page.dart @@ -110,7 +110,7 @@ class _OnboardingPageState extends State { children: [ Image.asset( page.imagePath, - height: 400, + height: 350, width: double.infinity, fit: BoxFit.fitWidth, errorBuilder: (context, error, stackTrace) { @@ -129,15 +129,14 @@ class _OnboardingPageState extends State { ); }, ), - const SizedBox(height: 20), SizedBox( - width: 80, - height: 80, + width: 60, + height: 60, child: Stack( alignment: Alignment.center, children: [ CustomPaint( - size: const Size(80, 80), + size: const Size(60, 60), painter: OnboardingIndicatorPainter( pageCount: onboardingPages.length, currentPage: _currentPage, @@ -150,7 +149,7 @@ class _OnboardingPageState extends State { onTap: _onNextTap, child: Container( width: 60, - height: 60, + height: 45, decoration: const BoxDecoration( color: Color.fromARGB(255, 1, 35, 72), shape: BoxShape.circle, @@ -158,8 +157,8 @@ class _OnboardingPageState extends State { child: Center( child: SvgPicture.asset( 'lib/assets/icons/Arrow - Right 2.svg', - width: 35, - height: 35, + width: 25, + height: 25, colorFilter: const ColorFilter.mode( Colors.white, BlendMode.srcIn, @@ -171,11 +170,10 @@ class _OnboardingPageState extends State { ], ), ), - const SizedBox(height: 20), Expanded( flex: 2, child: Padding( - padding: const EdgeInsets.all(20.0), + padding: const EdgeInsets.fromLTRB(20, 0, 20, 0), child: Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.end, @@ -186,17 +184,19 @@ class _OnboardingPageState extends State { style: theme.textTheme.headlineMedium?.copyWith( fontWeight: FontWeight.bold, + fontSize: 22, color: const Color.fromARGB(255, 0, 126, 167), ), ), - const SizedBox(height: 16), + const SizedBox(height: 13), Text( page.description, textDirection: TextDirection.rtl, textAlign: TextAlign.start, - style: theme.textTheme.bodyLarge?.copyWith( + style: theme.textTheme.bodyMedium?.copyWith( color: const Color.fromARGB(255, 41, 41, 41), height: 1.6, + fontSize: 15 ), ), ], @@ -245,7 +245,7 @@ class _OnboardingPageState extends State { Row( children: [ Expanded( - flex: 2, + flex: 4, child: ElevatedButton( onPressed: _onNextTap, style: ElevatedButton.styleFrom( @@ -266,7 +266,7 @@ class _OnboardingPageState extends State { ), const SizedBox(width: 16), Expanded( - flex: 1, + flex: 2, child: OutlinedButton( onPressed: _skipOnboarding, style: OutlinedButton.styleFrom( @@ -278,11 +278,15 @@ class _OnboardingPageState extends State { borderRadius: BorderRadius.circular(16), ), ), - child: Text( - 'صرف نظر کردن', - style: theme.textTheme.titleMedium?.copyWith( - color: Colors.black, - fontWeight: FontWeight.normal, + child: Padding( + padding: const EdgeInsets.all(5.0), + child: Text( + 'صرف نظر کردن', + style: theme.textTheme.titleMedium?.copyWith( + color: Colors.black, + fontSize: 12, + fontWeight: FontWeight.bold, + ), ), ), ), diff --git a/lib/views/podcasts/studio_details/studio_details.mobile.dart b/lib/views/podcasts/studio_details/studio_details.mobile.dart index c9dbe64..cf4ac7d 100644 --- a/lib/views/podcasts/studio_details/studio_details.mobile.dart +++ b/lib/views/podcasts/studio_details/studio_details.mobile.dart @@ -685,24 +685,24 @@ class _StudioDetailsState extends State return Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ - CircleAvatar( - radius: 20, - backgroundColor: DesignConfig.isDark - ? Colors.transparent - : Colors.white, - backgroundImage: - hasProfileImage ? NetworkImage(user.photo!) : null, - child: !hasProfileImage - ? Icon( - DidvanIcons.avatar_light, - size: 50, - color: DesignConfig.isDark - ? Colors.white - : Colors.black, - ) - : null, - ), - const SizedBox(width: 8), + // CircleAvatar( + // radius: 20, + // backgroundColor: DesignConfig.isDark + // ? Colors.transparent + // : Colors.white, + // backgroundImage: + // hasProfileImage ? NetworkImage(user.photo!) : null, + // child: !hasProfileImage + // ? Icon( + // DidvanIcons.avatar_light, + // size: 50, + // color: DesignConfig.isDark + // ? Colors.white + // : Colors.black, + // ) + // : null, + // ), + // const SizedBox(width: 8), Expanded( child: CommentMessageBox(focusNode: _focusNode), ), diff --git a/lib/views/profile/change_password/widgets/new_password_screen.dart b/lib/views/profile/change_password/widgets/new_password_screen.dart index fa5685e..8b99515 100644 --- a/lib/views/profile/change_password/widgets/new_password_screen.dart +++ b/lib/views/profile/change_password/widgets/new_password_screen.dart @@ -200,7 +200,6 @@ class _NewPasswordScreenState extends State ), ], children: [ - const SizedBox(height: 24), SlideTransition( position: _headerSlideAnimation, child: FadeTransition( @@ -215,7 +214,7 @@ class _NewPasswordScreenState extends State 'lib/assets/images/empty_states/Change_Password.png', fit: BoxFit.fitWidth, width: 500, - height: 400, + height: 300, ), ), const SizedBox(height: 24), diff --git a/lib/views/profile/change_password/widgets/verify_otp_screen.dart b/lib/views/profile/change_password/widgets/verify_otp_screen.dart index c2c0111..11069db 100644 --- a/lib/views/profile/change_password/widgets/verify_otp_screen.dart +++ b/lib/views/profile/change_password/widgets/verify_otp_screen.dart @@ -178,6 +178,7 @@ class _VerifyOtpScreenState extends State left: 0, right: 0, ), + // physics: const NeverScrollableScrollPhysics(), appBarData: null, showSliversFirst: true, slivers: [ @@ -240,7 +241,7 @@ class _VerifyOtpScreenState extends State child: FadeTransition( opacity: _fadeAnimation, child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 10.0), + padding: const EdgeInsets.symmetric(horizontal: 15.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -248,9 +249,8 @@ class _VerifyOtpScreenState extends State 'lib/assets/images/empty_states/Change_Password.png', fit: BoxFit.fitWidth, width: double.infinity, - height: 400, + height: 300, ), - const SizedBox(height: 24), DidvanText( 'تغییر رمز عبور', style: Theme.of(context) @@ -300,8 +300,8 @@ class _VerifyOtpScreenState extends State Theme.of(context).colorScheme.onSurface, hintCharacter: '-', pinTheme: PinTheme( - fieldHeight: 58, - fieldWidth: 58, + fieldHeight: 50, + fieldWidth: 50, selectedColor: _hasError ? const Color.fromARGB(255, 190, 18, 60) : Theme.of(context).colorScheme.primary, diff --git a/lib/views/radar/radar.dart b/lib/views/radar/radar.dart index 05d4eb5..3237871 100644 --- a/lib/views/radar/radar.dart +++ b/lib/views/radar/radar.dart @@ -155,7 +155,7 @@ class _RadarStateView extends State { if (state.categories.length >= 6) Padding( padding: const EdgeInsets.only( - top: 12, left: 20, right: 20), + top: 12, left: 35, right: 35), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: state.categories @@ -291,49 +291,52 @@ class _RadarStateView extends State { category.asset = _getCategoryIcon(category.id, isDark); return Expanded( - child: GestureDetector( - onTap: () => _onCategorySelected(category), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - AnimatedContainer( - duration: const Duration(milliseconds: 300), - curve: Curves.fastOutSlowIn, - padding: EdgeInsets.zero, - decoration: BoxDecoration( - color: isSelected - ? theme.colorScheme.primary.withOpacity(0.1) - : Colors.transparent, - borderRadius: BorderRadius.circular(30), - border: Border.all( + child: Padding( + padding: const EdgeInsets.all(8.0), + child: GestureDetector( + onTap: () => _onCategorySelected(category), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + AnimatedContainer( + duration: const Duration(milliseconds: 300), + curve: Curves.fastOutSlowIn, + padding: EdgeInsets.zero, + decoration: BoxDecoration( color: isSelected - ? theme.colorScheme.primary + ? theme.colorScheme.primary.withOpacity(0.1) : Colors.transparent, - width: 2, + borderRadius: BorderRadius.circular(30), + border: Border.all( + color: isSelected + ? theme.colorScheme.primary + : Colors.transparent, + width: 2, + ), + ), + child: ClipRRect( + borderRadius: BorderRadius.circular(30), + child: SvgPicture.asset( + category.asset!, + width: 100, + height: 100, + ), ), ), - child: ClipRRect( - borderRadius: BorderRadius.circular(30), - child: SvgPicture.asset( - category.asset!, - width: 100, - height: 100, + const SizedBox(height: 3), + Text( + category.label, + textAlign: TextAlign.center, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: theme.textTheme.bodySmall?.copyWith( + color: theme.colorScheme.primary, + fontWeight: isSelected ? FontWeight.bold : FontWeight.bold, + fontSize: 13, ), ), - ), - const SizedBox(height: 8), - Text( - category.label, - textAlign: TextAlign.center, - maxLines: 1, - overflow: TextOverflow.ellipsis, - style: theme.textTheme.bodySmall?.copyWith( - color: theme.colorScheme.primary, - fontWeight: isSelected ? FontWeight.bold : FontWeight.bold, - fontSize: 15, - ), - ), - ], + ], + ), ), ), ); diff --git a/lib/views/widgets/ai_chat_dialog.dart b/lib/views/widgets/ai_chat_dialog.dart index 5486ef3..7ea7131 100644 --- a/lib/views/widgets/ai_chat_dialog.dart +++ b/lib/views/widgets/ai_chat_dialog.dart @@ -847,59 +847,59 @@ class _AiChatDialogState extends State ); } - Widget _buildRecordingIndicator() { - return Container( - padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 10), - margin: const EdgeInsets.only(bottom: 6), - decoration: BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topLeft, - end: Alignment.bottomRight, - colors: [ - const Color(0xFFFF3366).withOpacity(0.1), - const Color(0xFFFF6699).withOpacity(0.05), - ], - ), - border: Border.all( - color: const Color(0xFFFF3366).withOpacity(0.3), - width: 1, - ), - ), - child: Row( - children: [ - Container( - width: 8, - height: 8, - decoration: BoxDecoration( - color: const Color(0xFFFF3366), - shape: BoxShape.circle, - boxShadow: [ - BoxShadow( - color: const Color(0xFFFF3366).withOpacity(0.4), - blurRadius: 6, - spreadRadius: 1, - ), - ], - ), - ), - const SizedBox(width: 10), - const Expanded( - child: DidvanText( - '🎙️ در حال ضبط...', - fontSize: 12, - color: Color(0xFFFF3366), - fontWeight: FontWeight.w600, - ), - ), - const Icon( - Icons.mic_rounded, - color: Color(0xFFFF3366), - size: 16, - ), - ], - ), - ); - } + // Widget _buildRecordingIndicator() { + // return Container( + // padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 10), + // margin: const EdgeInsets.only(bottom: 6), + // decoration: BoxDecoration( + // gradient: LinearGradient( + // begin: Alignment.topLeft, + // end: Alignment.bottomRight, + // colors: [ + // const Color(0xFFFF3366).withOpacity(0.1), + // const Color(0xFFFF6699).withOpacity(0.05), + // ], + // ), + // border: Border.all( + // color: const Color(0xFFFF3366).withOpacity(0.3), + // width: 1, + // ), + // ), + // child: Row( + // children: [ + // Container( + // width: 8, + // height: 8, + // decoration: BoxDecoration( + // color: const Color(0xFFFF3366), + // shape: BoxShape.circle, + // boxShadow: [ + // BoxShadow( + // color: const Color(0xFFFF3366).withOpacity(0.4), + // blurRadius: 6, + // spreadRadius: 1, + // ), + // ], + // ), + // ), + // const SizedBox(width: 10), + // const Expanded( + // child: DidvanText( + // '🎙️ در حال ضبط...', + // fontSize: 12, + // color: Color(0xFFFF3366), + // fontWeight: FontWeight.w600, + // ), + // ), + // const Icon( + // Icons.mic_rounded, + // color: Color(0xFFFF3366), + // size: 16, + // ), + // ], + // ), + // ); + // } Widget _buildInputField() { return Container( diff --git a/lib/views/widgets/ai_voice_chat_dialog.dart b/lib/views/widgets/ai_voice_chat_dialog.dart index 728f088..488e773 100644 --- a/lib/views/widgets/ai_voice_chat_dialog.dart +++ b/lib/views/widgets/ai_voice_chat_dialog.dart @@ -4,6 +4,7 @@ import 'package:didvan/services/ai_rag_service.dart'; import 'package:didvan/services/ai_voice_service.dart'; import 'package:didvan/views/widgets/didvan/text.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:record/record.dart'; import 'package:path_provider/path_provider.dart'; import 'package:just_audio/just_audio.dart'; @@ -25,6 +26,7 @@ class _AiVoiceChatDialogState extends State bool _isProcessing = false; bool _isAiSpeaking = false; String _statusText = 'برای شروع مکالمه، دکمه میکروفون را نگه دارید'; + String? _currentAiResponse; late AnimationController _waveController; late AnimationController _pulseController; @@ -62,7 +64,7 @@ class _AiVoiceChatDialogState extends State 'در حال آماده‌سازی پاسخ...', 'در حال محاسبه‌ی بهترین گزینه...', 'در حال درک مفهوم پرسش شما...', - 'در حال به‌روزرسانی اطلاعات...', + 'در حال به‌روز‌رسانی اطلاعات...', 'در حال استخراج پاسخ مناسب...', 'در حال هماهنگ‌سازی با پایگاه دانش...' ]; @@ -147,6 +149,14 @@ class _AiVoiceChatDialogState extends State _isAiSpeaking = false; }); } + + // <<< راه‌حل مشکل ۲: ریست کردن پاسخ قبلی + if (_currentAiResponse != null) { + setState(() { + _currentAiResponse = null; + }); + } + // >>> setState(() { _isPreparing = true; @@ -168,6 +178,7 @@ class _AiVoiceChatDialogState extends State await Future.delayed(const Duration(seconds: 2)); + // <<< راه‌حل مشکل ۲: بررسی وضعیت قبل از شروع ضبط if (mounted && _isPreparing) { setState(() { _isPreparing = false; @@ -176,7 +187,12 @@ class _AiVoiceChatDialogState extends State }); _preparingController.stop(); _waveController.repeat(); + } else if (mounted) { + // اگر کاربر انگشت خود را برداشته بود (_isPreparing false شده) + await _audioRecorder.stop(); // ضبط را متوقف کن + _waveController.stop(); } + // >>> } } catch (e) { setState(() { @@ -184,8 +200,10 @@ class _AiVoiceChatDialogState extends State _isRecording = false; _statusText = 'خطا در شروع ضبط صدا'; }); + // <<< راه‌حل مشکل ۲: توقف انیمیشن‌ها در صورت خطا _preparingController.stop(); _waveController.stop(); + // >>> debugPrint('Error starting recording: $e'); } } @@ -230,6 +248,7 @@ class _AiVoiceChatDialogState extends State _statusText = '🔊 دستیار در حال پاسخ دادن است...'; _isProcessing = false; _isAiSpeaking = true; + _currentAiResponse = ragResponse.output; }); await _audioPlayer.setUrl(ragResponse.audioUrl!); @@ -443,13 +462,39 @@ class _AiVoiceChatDialogState extends State } Widget _buildMainContent() { - return Center( + return SingleChildScrollView( child: Column( - mainAxisAlignment: MainAxisAlignment.center, children: [ - _buildVisualization(), - const SizedBox(height: 40), - _buildStatusText(), + const SizedBox(height: 20), + SizedBox( + height: 500, + child: Stack( + alignment: Alignment.topCenter, + children: [ + Positioned( + top: 0, + child: _buildVisualization(), + ), + // وقتی پاسخ هست، کارت پاسخ را نمایش می‌دهیم + if (_currentAiResponse != null && _currentAiResponse!.isNotEmpty) + Positioned( + bottom: 120, + left: 24, + right: 24, + child: _buildResponsePreview(), + ) + else + // در غیر این صورت، متن status را نمایش می‌دهیم + Positioned( + bottom: 130, + left: 24, + right: 24, + child: _buildStatusText(), + ), + ], + ), + ), + const SizedBox(height: 20), ], ), ); @@ -597,6 +642,375 @@ class _AiVoiceChatDialogState extends State ); } + Widget _buildResponsePreview() { + return TweenAnimationBuilder( + tween: Tween(begin: 0.0, end: 1.0), + duration: const Duration(milliseconds: 600), + curve: Curves.easeOutCubic, + builder: (context, value, child) { + return Transform.translate( + offset: Offset(0, 30 * (1 - value)), + child: Opacity( + opacity: value, + child: child, + ), + ); + }, + child: Container( + margin: const EdgeInsets.fromLTRB(2, 8, 2, 0), + child: ClipRRect( + borderRadius: BorderRadius.circular(24), + child: BackdropFilter( + filter: ImageFilter.blur(sigmaX: 15, sigmaY: 15), + child: Container( + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: [ + Colors.white.withOpacity(0.15), + Colors.white.withOpacity(0.08), + ], + ), + borderRadius: BorderRadius.circular(24), + border: Border.all( + color: Colors.white.withOpacity(0.2), + width: 1.5, + ), + boxShadow: [ + BoxShadow( + color: const Color(0xFF00AAFF).withOpacity(0.2), + blurRadius: 20, + spreadRadius: 0, + ), + ], + ), + child: Material( + color: Colors.transparent, + child: InkWell( + onTap: _showFullResponseDialog, + borderRadius: BorderRadius.circular(24), + child: Padding( + padding: const EdgeInsets.all(20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Container( + padding: const EdgeInsets.all(8), + decoration: BoxDecoration( + gradient: const LinearGradient( + colors: [ + Color(0xFF00AAFF), + Color(0xFF0066AA), + ], + ), + shape: BoxShape.circle, + boxShadow: [ + BoxShadow( + color: const Color(0xFF00AAFF).withOpacity(0.4), + blurRadius: 12, + spreadRadius: 2, + ), + ], + ), + child: const Icon( + Icons.chat_bubble_rounded, + color: Colors.white, + size: 20, + ), + ), + const SizedBox(width: 12), + const Expanded( + child: DidvanText( + 'پاسخ دستیار', + fontSize: 13, + fontWeight: FontWeight.bold, + color: Colors.white, + ), + ), + Container( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 6, + ), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + Colors.white.withOpacity(0.2), + Colors.white.withOpacity(0.1), + ], + ), + borderRadius: BorderRadius.circular(12), + ), + child: const Row( + mainAxisSize: MainAxisSize.min, + children: [ + DidvanText( + 'مشاهده کامل', + fontSize: 11, + color: Colors.white, + fontWeight: FontWeight.w600, + ), + SizedBox(width: 4), + Icon( + Icons.arrow_back_ios_rounded, + color: Colors.white, + size: 12, + ), + ], + ), + ), + ], + ), + const SizedBox(height: 16), + DidvanText( + _currentAiResponse!, + fontSize: 13.5, + color: Colors.white.withOpacity(0.95), + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + const SizedBox(height: 8), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: List.generate( + 3, + (index) => Container( + margin: const EdgeInsets.symmetric(horizontal: 2), + width: 4, + height: 4, + decoration: BoxDecoration( + color: Colors.white.withOpacity(0.6), + shape: BoxShape.circle, + ), + ), + ), + ), + ], + ), + ), + ), + ), + ), + ), + ), + ), + ); + } + + void _showFullResponseDialog() { + showDialog( + context: context, + barrierColor: Colors.black.withOpacity(0.7), + builder: (context) => Dialog( + backgroundColor: Colors.transparent, + insetPadding: const EdgeInsets.symmetric(horizontal: 20, vertical: 40), + child: ScaleTransition( + scale: CurvedAnimation( + parent: AnimationController( + vsync: this, + duration: const Duration(milliseconds: 300), + )..forward(), + curve: Curves.easeOutBack, + ), + child: ClipRRect( + borderRadius: BorderRadius.circular(28), + child: BackdropFilter( + filter: ImageFilter.blur(sigmaX: 20, sigmaY: 20), + child: Container( + constraints: const BoxConstraints(maxHeight: 600), + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: [ + const Color(0xFF0A0E27).withOpacity(0.95), + const Color(0xFF1A1F3A).withOpacity(0.95), + ], + ), + borderRadius: BorderRadius.circular(28), + border: Border.all( + color: Colors.white.withOpacity(0.15), + width: 1.5, + ), + boxShadow: [ + BoxShadow( + color: const Color(0xFF00AAFF).withOpacity(0.3), + blurRadius: 40, + spreadRadius: 0, + ), + ], + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + padding: const EdgeInsets.all(20), + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + Colors.white.withOpacity(0.08), + Colors.transparent, + ], + ), + ), + child: Row( + children: [ + Container( + padding: const EdgeInsets.all(10), + decoration: BoxDecoration( + gradient: const LinearGradient( + colors: [ + Color(0xFF00AAFF), + Color(0xFF0066AA), + ], + ), + shape: BoxShape.circle, + boxShadow: [ + BoxShadow( + color: const Color(0xFF00AAFF).withOpacity(0.4), + blurRadius: 15, + spreadRadius: 2, + ), + ], + ), + child: const Icon( + Icons.chat_bubble_rounded, + color: Colors.white, + size: 24, + ), + ), + const SizedBox(width: 14), + const Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + DidvanText( + 'پاسخ کامل دستیار', + fontSize: 16, + fontWeight: FontWeight.bold, + color: Colors.white, + ), + SizedBox(height: 2), + DidvanText( + 'دیدوان AI', + fontSize: 11, + color: Colors.white60, + ), + ], + ), + ), + IconButton( + icon: const Icon( + Icons.close_rounded, + color: Colors.white70, + size: 24, + ), + onPressed: () => Navigator.pop(context), + ), + ], + ), + ), + Flexible( + child: SingleChildScrollView( + padding: const EdgeInsets.fromLTRB(24, 8, 24, 24), + child: Container( + padding: const EdgeInsets.all(20), + decoration: BoxDecoration( + color: Colors.white.withOpacity(0.05), + borderRadius: BorderRadius.circular(20), + border: Border.all( + color: Colors.white.withOpacity(0.1), + width: 1, + ), + ), + child: DidvanText( + _currentAiResponse ?? '', + fontSize: 14, + color: Colors.white.withOpacity(0.95), + ), + ), + ), + ), + Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.bottomCenter, + end: Alignment.topCenter, + colors: [ + Colors.white.withOpacity(0.05), + Colors.transparent, + ], + ), + ), + child: Row( + children: [ + Expanded( + child: ElevatedButton.icon( + onPressed: () { + Clipboard.setData(ClipboardData(text: _currentAiResponse ?? '')); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: const DidvanText( + 'متن کپی شد', + color: Colors.white, + fontSize: 13, + ), + backgroundColor: const Color(0xFF00AAFF), + behavior: SnackBarBehavior.floating, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + duration: const Duration(seconds: 2), + ), + ); + }, + icon: const Icon( + Icons.copy_rounded, + size: 18, + color: Colors.white, + ), + label: const DidvanText( + 'کپی متن', + fontSize: 13, + color: Colors.white, + fontWeight: FontWeight.w600, + ), + style: ElevatedButton.styleFrom( + backgroundColor: Colors.white.withOpacity(0.15), + padding: const EdgeInsets.symmetric( + horizontal: 24, + vertical: 14, + ), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16), + side: BorderSide( + color: Colors.white.withOpacity(0.2), + width: 1, + ), + ), + elevation: 0, + ), + ), + ), + ], + ), + ), + ], + ), + ), + ), + ), + ), + ), + ); + } + Widget _buildControls() { return Container( padding: const EdgeInsets.all(24), @@ -619,11 +1033,21 @@ class _AiVoiceChatDialogState extends State _startRecording(); } }, + // <<< راه‌حل مشکل ۲: (بدون تغییر، همچنان پابرجاست) onLongPressEnd: (_) { if (_isRecording) { _stopRecording(); + } else if (_isPreparing) { + // کاربر انگشت خود را در حین آماده‌سازی برداشت + setState(() { + _isPreparing = false; + _statusText = 'برای شروع مکالمه، دکمه میکروفون را نگه دارید'; + }); + _preparingController.stop(); + _waveController.stop(); } }, + // >>> child: AnimatedBuilder( animation: _pulseController, builder: (context, child) { @@ -812,4 +1236,4 @@ class PreparingSpinnerPainter extends CustomPainter { bool shouldRepaint(covariant PreparingSpinnerPainter oldDelegate) { return true; } -} +} \ No newline at end of file diff --git a/lib/views/widgets/didvan/bnb.dart b/lib/views/widgets/didvan/bnb.dart index 7fbc1ea..41eae07 100644 --- a/lib/views/widgets/didvan/bnb.dart +++ b/lib/views/widgets/didvan/bnb.dart @@ -312,7 +312,7 @@ class _NavBarItemState extends State<_NavBarItem> duration: const Duration(milliseconds: 150), child: DidvanText( widget.title, - style: Theme.of(context).textTheme.bodySmall, + style: Theme.of(context).textTheme.bodySmall?.copyWith(fontSize: 11), color: Theme.of(context).colorScheme.caption, fontWeight: FontWeight.w500, ), diff --git a/lib/views/widgets/didvan/text_field.dart b/lib/views/widgets/didvan/text_field.dart index d0359d9..fb64d71 100644 --- a/lib/views/widgets/didvan/text_field.dart +++ b/lib/views/widgets/didvan/text_field.dart @@ -164,7 +164,8 @@ class _DidvanTextFieldState extends State { ? Theme.of(context).textTheme.bodySmall! : Theme.of(context).textTheme.bodyMedium!) .copyWith( - color: Theme.of(context).colorScheme.hint), + color: Theme.of(context).colorScheme.hint, + fontSize: 12), ), ), )); diff --git a/lib/views/widgets/home_app_bar.dart b/lib/views/widgets/home_app_bar.dart index 1ed589d..a0523f4 100644 --- a/lib/views/widgets/home_app_bar.dart +++ b/lib/views/widgets/home_app_bar.dart @@ -45,6 +45,7 @@ class HomeAppBar extends StatelessWidget { return Column( children: [ + const SizedBox(height: 10,), Padding( padding: const EdgeInsets.fromLTRB(16, 0, 16, 16), child: Row( @@ -102,6 +103,11 @@ class HomeAppBar extends StatelessWidget { Navigator.of(context).pushNamed(Routes.bookmarks); }, ), + Container( + color: const Color.fromARGB(255, 224, 224, 224), + height: 20, + width: 1.5, + ), GestureDetector( onTap: () { Navigator.pushNamed(context, Routes.profile); diff --git a/lib/views/widgets/hoshan_home_app_bar.dart b/lib/views/widgets/hoshan_home_app_bar.dart index 822b33c..fb174dc 100644 --- a/lib/views/widgets/hoshan_home_app_bar.dart +++ b/lib/views/widgets/hoshan_home_app_bar.dart @@ -7,6 +7,7 @@ import 'package:didvan/views/ai/history_ai_chat_state.dart'; import 'package:didvan/views/widgets/didvan/text.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; +import 'package:persian_number_utility/persian_number_utility.dart'; import 'package:provider/provider.dart'; import 'package:didvan/routes/routes.dart'; // ignore: depend_on_referenced_packages @@ -529,12 +530,13 @@ class _HistoryDrawerContentState extends State { _buildChatItem(chat, historyState)), ], if (last7DaysChats.isNotEmpty) ...[ - _buildSectionHeader('7 روز اخیر'), + _buildSectionHeader('۷ روز اخیر'), ...last7DaysChats.map((chat) => _buildChatItem(chat, historyState)), ], + // '۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹' if (last30DaysChats.isNotEmpty) ...[ - _buildSectionHeader('30 روز اخیر'), + _buildSectionHeader('۳۰ روز اخیر'), ...last30DaysChats.map((chat) => _buildChatItem(chat, historyState)), ], @@ -614,7 +616,7 @@ class _HistoryDrawerContentState extends State { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ DidvanText( - _formatDateFromString(chat.updatedAt), + _formatDateFromString(chat.updatedAt).toPersianDigit(), fontSize: 12, color: Colors.grey[600], ), diff --git a/lib/views/widgets/overview/news.dart b/lib/views/widgets/overview/news.dart index 158a760..5965b38 100644 --- a/lib/views/widgets/overview/news.dart +++ b/lib/views/widgets/overview/news.dart @@ -116,20 +116,20 @@ class NewsOverview extends StatelessWidget { ), Row( children: [ - LikedButton( - itemId: news.id, - type: 'news', - gestureSize: 32, - value: news.liked, - onMarkChanged: (value) => - onLikedChanged(news.id, value, false), - askForConfirmation: hasUnmarkConfirmation, - likes: news.likes, - unlikedColor: Theme.of(context).colorScheme.caption, - ), - const SizedBox( - width: 4.0, - ), + // LikedButton( + // itemId: news.id, + // type: 'news', + // gestureSize: 32, + // value: news.liked, + // onMarkChanged: (value) => + // onLikedChanged(news.id, value, false), + // askForConfirmation: hasUnmarkConfirmation, + // likes: news.likes, + // unlikedColor: Theme.of(context).colorScheme.caption, + // ), + // const SizedBox( + // width: 4.0, + // ), BookmarkButton( itemId: news.id, type: 'news', diff --git a/lib/views/widgets/overview/radar.dart b/lib/views/widgets/overview/radar.dart index 69231f0..97015f1 100644 --- a/lib/views/widgets/overview/radar.dart +++ b/lib/views/widgets/overview/radar.dart @@ -151,20 +151,20 @@ class RadarOverview extends StatelessWidget { padding: const EdgeInsets.fromLTRB(8, 0, 8, 5), child: Row( children: [ - LikedButton( - itemId: radar.id, - type: 'radar', - gestureSize: 32, - value: radar.liked, - onMarkChanged: (value) => - onLikedChanged(radar.id, value, false), - askForConfirmation: hasUnmarkConfirmation, - likes: radar.likes, - unlikedColor: Theme.of(context).colorScheme.caption, - ), - const SizedBox( - width: 4.0, - ), + // LikedButton( + // itemId: radar.id, + // type: 'radar', + // gestureSize: 32, + // value: radar.liked, + // onMarkChanged: (value) => + // onLikedChanged(radar.id, value, false), + // askForConfirmation: hasUnmarkConfirmation, + // likes: radar.likes, + // unlikedColor: Theme.of(context).colorScheme.caption, + // ), + // const SizedBox( + // width: 4.0, + // ), BookmarkButton( itemId: radar.id, type: 'radar', diff --git a/lib/views/widgets/state_handlers/empty_connection.dart b/lib/views/widgets/state_handlers/empty_connection.dart index cc353f6..ce8f496 100644 --- a/lib/views/widgets/state_handlers/empty_connection.dart +++ b/lib/views/widgets/state_handlers/empty_connection.dart @@ -7,21 +7,14 @@ class EmptyConnection extends StatelessWidget { @override Widget build(BuildContext context) { - return Column( - children: [ - const SizedBox( - height: 65, - ), - EmptyState( - asset: 'lib/assets/images/empty_states/Connection.png', - height: 550, - title: 'اتصال اینترنت برقرار نیست', - titleColor: const Color.fromARGB(255, 0, 126, 167), - action: onRetry, - subtitle: 'لطفاً اتصال وای‌فای یا داده تلفن همراه خود را بررسی کنید.', - buttonTitle: 'تلاش مجدد', - ), - ], + return EmptyState( + asset: 'lib/assets/images/empty_states/Connection.png', + height: 400, + title: 'اتصال اینترنت برقرار نیست', + titleColor: const Color.fromARGB(255, 0, 126, 167), + action: onRetry, + subtitle: 'لطفاً اتصال وای‌فای یا داده تلفن همراه خود را بررسی کنید.', + buttonTitle: 'تلاش مجدد' , ); } } diff --git a/lib/views/widgets/state_handlers/empty_result.dart b/lib/views/widgets/state_handlers/empty_result.dart index 738e714..c8aa5ef 100644 --- a/lib/views/widgets/state_handlers/empty_result.dart +++ b/lib/views/widgets/state_handlers/empty_result.dart @@ -11,6 +11,7 @@ class EmptyResult extends StatelessWidget { asset: 'lib/assets/images/empty_states/Empty-Result.png', height: 600, title: 'نتیجه‌ای یافت نشد', + titleColor: const Color.fromARGB(255, 0, 126, 167), subtitle: 'لطفاً از کلمات کلیدی دیگری استفاده کنید یا املای کلمه را بررسی نمایید.', buttonTitle: 'بازگشت به صفحه اصلی', diff --git a/lib/views/widgets/state_handlers/empty_state.dart b/lib/views/widgets/state_handlers/empty_state.dart index d52311d..aa9c7c1 100644 --- a/lib/views/widgets/state_handlers/empty_state.dart +++ b/lib/views/widgets/state_handlers/empty_state.dart @@ -29,8 +29,8 @@ class EmptyState extends StatelessWidget { final isSvg = asset.toLowerCase().endsWith('.svg'); return Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, children: [ SizedBox( width: double.infinity, @@ -40,25 +40,26 @@ class EmptyState extends StatelessWidget { : Image.asset(asset, fit: BoxFit.fitWidth, height: height, width: double.infinity), ), + const SizedBox(height: 10), Padding( padding: const EdgeInsets.only(right: 20, left: 20), child: DidvanText( title, style: Theme.of(context).textTheme.displaySmall, color: titleColor ?? Theme.of(context).colorScheme.caption, - textAlign: TextAlign.start, + textAlign: TextAlign.center, ), ), - if (subtitle != null) const SizedBox(height: 8), - if (subtitle != null) - Padding( - padding: const EdgeInsets.only(right: 20, left: 20), - child: DidvanText( - subtitle!, - color: Theme.of(context).colorScheme.caption, - ), - ), - if (action != null) const SizedBox(height: 16), + // if (subtitle != null) const SizedBox(height: 8), + // if (subtitle != null) + // Padding( + // padding: const EdgeInsets.only(right: 20, left: 20), + // child: DidvanText( + // subtitle!, + // color: Theme.of(context).colorScheme.caption, + // ), + // ), + // if (action != null) const SizedBox(height: 16), if (action != null) Center( child: Padding( diff --git a/lib/views/widgets/state_handlers/sliver_state_handler.dart b/lib/views/widgets/state_handlers/sliver_state_handler.dart index 689e5d3..0c980b7 100644 --- a/lib/views/widgets/state_handlers/sliver_state_handler.dart +++ b/lib/views/widgets/state_handlers/sliver_state_handler.dart @@ -38,7 +38,7 @@ class SliverStateHandler extends SliverList { if (state.appState == AppState.failed) { return Padding( padding: EdgeInsets.only( - top: centerEmptyState ? deviceHight / 4 : deviceHight / 8, + top: 0, bottom: 20, ), child: EmptyConnection(onRetry: onRetry), diff --git a/macos/Flutter/ephemeral/Flutter-Generated.xcconfig b/macos/Flutter/ephemeral/Flutter-Generated.xcconfig index 42e7b43..90041d8 100644 --- a/macos/Flutter/ephemeral/Flutter-Generated.xcconfig +++ b/macos/Flutter/ephemeral/Flutter-Generated.xcconfig @@ -3,7 +3,7 @@ FLUTTER_ROOT=C:\flutter FLUTTER_APPLICATION_PATH=C:\Flutter Projects\didvan-app\didvan-app COCOAPODS_PARALLEL_CODE_SIGN=true FLUTTER_BUILD_DIR=build -FLUTTER_BUILD_NAME=4.0.1 +FLUTTER_BUILD_NAME=5.0.0 FLUTTER_BUILD_NUMBER=6000 DART_OBFUSCATION=false TRACK_WIDGET_CREATION=true diff --git a/macos/Flutter/ephemeral/flutter_export_environment.sh b/macos/Flutter/ephemeral/flutter_export_environment.sh index 4ca9df9..99e93e9 100644 --- a/macos/Flutter/ephemeral/flutter_export_environment.sh +++ b/macos/Flutter/ephemeral/flutter_export_environment.sh @@ -4,7 +4,7 @@ export "FLUTTER_ROOT=C:\flutter" export "FLUTTER_APPLICATION_PATH=C:\Flutter Projects\didvan-app\didvan-app" export "COCOAPODS_PARALLEL_CODE_SIGN=true" export "FLUTTER_BUILD_DIR=build" -export "FLUTTER_BUILD_NAME=4.0.1" +export "FLUTTER_BUILD_NAME=5.0.0" export "FLUTTER_BUILD_NUMBER=6000" export "DART_OBFUSCATION=false" export "TRACK_WIDGET_CREATION=true" diff --git a/pubspec.yaml b/pubspec.yaml index 1e3f80f..944afc7 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -15,7 +15,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 4.0.1+6000 +version: 5.0.0+6000 environment: sdk: ">=3.0.0 <4.0.0"