Browse Source
Merge pull request 'feature/intro' (#27) from feature/intro into develop
Merge pull request 'feature/intro' (#27) from feature/intro into develop
Reviewed-on: https://git.nwhco.ir/amirreza.chegini/hade_hoda_flutter/pulls/27pull/28/head
45 changed files with 876 additions and 157 deletions
-
BINassets/fonts/Baloo2-Bold.ttf
-
BINassets/fonts/Baloo2-ExtraBold.ttf
-
BINassets/fonts/Baloo2-Medium.ttf
-
BINassets/fonts/Baloo2-SemiBold.ttf
-
0assets/fonts/DinoKids-Regular.ttf
-
BINassets/fonts/Marhey-Light.ttf
-
BINassets/fonts/Marhey-Medium.ttf
-
BINassets/fonts/Marhey-Regular.ttf
-
BINassets/images/intro_1.jpg
-
BINassets/images/intro_2.jpg
-
BINassets/images/intro_3.jpg
-
BINassets/images/intro_4.jpg
-
BINassets/images/intro_5.jpg
-
10lib/common_ui/resources/my_assets.dart
-
137lib/common_ui/resources/my_text_style.dart
-
18lib/common_ui/theme/my_theme.dart
-
2lib/core/middlewares/my_middlewares.dart
-
23lib/core/routers/my_routes.dart
-
14lib/core/utils/my_device.dart
-
7lib/core/utils/screen_size.dart
-
18lib/core/utils/set_platform_size.dart
-
16lib/core/widgets/about_us_dialog/about_us_dialog.dart
-
6lib/core/widgets/about_us_dialog/styles/background.dart
-
67lib/core/widgets/animations/slide_up_fade.dart
-
8lib/core/widgets/hadith_dialog/hadith_dialog.dart
-
48lib/features/intro/presentation/bloc/intro_bloc.dart
-
2lib/features/intro/presentation/bloc/intro_event.dart
-
14lib/features/intro/presentation/bloc/intro_state.dart
-
97lib/features/intro/presentation/ui/intro_page.dart
-
54lib/features/intro/presentation/ui/screens/intro_1_screen.dart
-
37lib/features/intro/presentation/ui/screens/intro_2_screen.dart
-
37lib/features/intro/presentation/ui/screens/intro_3_screen.dart
-
36lib/features/intro/presentation/ui/screens/intro_4_screen.dart
-
34lib/features/intro/presentation/ui/screens/intro_5_screen.dart
-
91lib/features/intro/presentation/ui/widgets/bubble_chat_widget.dart
-
44lib/features/splash/presentation/bloc/splash_bloc.dart
-
3lib/features/splash/presentation/bloc/splash_event.dart
-
15lib/features/splash/presentation/bloc/splash_state.dart
-
82lib/features/splash/presentation/ui/splash_page.dart
-
6lib/init_bindings.dart
-
9lib/l10n/app_en.arb
-
42lib/l10n/app_localizations.dart
-
24lib/l10n/app_localizations_en.dart
-
1lib/main.dart
-
31pubspec.yaml
|
After Width: 819 | Height: 1229 | Size: 147 KiB |
|
After Width: 819 | Height: 1229 | Size: 139 KiB |
|
After Width: 819 | Height: 1229 | Size: 134 KiB |
|
After Width: 819 | Height: 1229 | Size: 141 KiB |
|
After Width: 819 | Height: 1229 | Size: 179 KiB |
@ -1,24 +1,10 @@ |
|||
import 'package:flutter/material.dart'; |
|||
import 'package:hadi_hoda_flutter/common_ui/resources/my_colors.dart'; |
|||
|
|||
enum ColorsName { primaryColor, backgroundDialog } |
|||
|
|||
class MyTheme { |
|||
static const MyTheme _i = MyTheme._internal(); |
|||
const MyTheme._internal(); |
|||
factory MyTheme() => _i; |
|||
|
|||
static final ThemeData light = ThemeData(brightness: Brightness.dark); |
|||
|
|||
static final ThemeData dark = ThemeData(brightness: Brightness.light); |
|||
|
|||
static Map<ColorsName, Color> get lightColors => { |
|||
ColorsName.primaryColor: MyColors.white, |
|||
ColorsName.backgroundDialog: MyColors.purple, |
|||
}; |
|||
|
|||
static Map<ColorsName, Color> get darkColors => { |
|||
ColorsName.primaryColor: MyColors.black, |
|||
ColorsName.backgroundDialog: MyColors.purple, |
|||
}; |
|||
static final ThemeData light = ThemeData(brightness: Brightness.light); |
|||
static final ThemeData dark = ThemeData(brightness: Brightness.dark); |
|||
} |
|||
@ -1,6 +1,13 @@ |
|||
import 'package:flutter/material.dart'; |
|||
import 'package:hadi_hoda_flutter/core/utils/context_provider.dart'; |
|||
|
|||
extension ScreenSize on BuildContext { |
|||
double get widthScreen => MediaQuery.sizeOf(this).width; |
|||
double get heightScreen => MediaQuery.sizeOf(this).height; |
|||
} |
|||
|
|||
|
|||
extension AdaptiveSize on double { |
|||
double get w => ContextProvider.context.widthScreen * this; |
|||
double get h => ContextProvider.context.heightScreen * this; |
|||
} |
|||
@ -0,0 +1,67 @@ |
|||
import 'package:flutter/material.dart'; |
|||
|
|||
class SlideUpFade extends StatefulWidget { |
|||
const SlideUpFade({ |
|||
super.key, |
|||
required this.child, |
|||
this.delay = Duration.zero, |
|||
}); |
|||
|
|||
final Widget child; |
|||
final Duration delay; |
|||
|
|||
@override |
|||
State<SlideUpFade> createState() => _SlideUpFadeState(); |
|||
} |
|||
|
|||
class _SlideUpFadeState extends State<SlideUpFade> |
|||
with SingleTickerProviderStateMixin { |
|||
late AnimationController _controller; |
|||
late Animation<double> _fadeAnim; |
|||
late Animation<Offset> _slideAnim; |
|||
|
|||
@override |
|||
void initState() { |
|||
super.initState(); |
|||
_controller = AnimationController( |
|||
vsync: this, |
|||
duration: Duration(milliseconds: 500), |
|||
reverseDuration: Duration(milliseconds: 500), |
|||
); |
|||
|
|||
_fadeAnim = Tween<double>( |
|||
begin: 0, |
|||
end: 1, |
|||
).animate(CurvedAnimation(parent: _controller, curve: Curves.easeIn)); |
|||
|
|||
_slideAnim = Tween<Offset>( |
|||
begin: Offset(0, 0.1), |
|||
end: Offset.zero, |
|||
).animate(CurvedAnimation(parent: _controller, curve: Curves.easeIn)); |
|||
startAnim(); |
|||
} |
|||
|
|||
Future<void> startAnim() async { |
|||
await Future.delayed(widget.delay, () { |
|||
_controller.forward(); |
|||
}); |
|||
} |
|||
|
|||
@override |
|||
void dispose() { |
|||
_controller.dispose(); |
|||
super.dispose(); |
|||
} |
|||
|
|||
@override |
|||
Widget build(BuildContext context) { |
|||
return AnimatedBuilder( |
|||
animation: _controller, |
|||
child: widget.child, |
|||
builder: (context, child) => FadeTransition( |
|||
opacity: _fadeAnim, |
|||
child: SlideTransition(position: _slideAnim, child: child), |
|||
), |
|||
); |
|||
} |
|||
} |
|||
@ -1,44 +1,48 @@ |
|||
import 'dart:async'; |
|||
|
|||
import 'package:bloc/bloc.dart'; |
|||
import 'package:flutter/cupertino.dart'; |
|||
import 'package:go_router/go_router.dart'; |
|||
import 'package:hadi_hoda_flutter/common_ui/resources/my_assets.dart'; |
|||
import 'package:hadi_hoda_flutter/core/routers/my_routes.dart'; |
|||
import 'package:hadi_hoda_flutter/core/utils/context_provider.dart'; |
|||
import 'package:hadi_hoda_flutter/features/intro/presentation/bloc/intro_event.dart'; |
|||
import 'package:hadi_hoda_flutter/features/intro/presentation/bloc/intro_state.dart'; |
|||
import 'package:hadi_hoda_flutter/features/intro/presentation/ui/screens/intro_1_screen.dart'; |
|||
import 'package:hadi_hoda_flutter/features/intro/presentation/ui/screens/intro_2_screen.dart'; |
|||
import 'package:hadi_hoda_flutter/features/intro/presentation/ui/screens/intro_3_screen.dart'; |
|||
import 'package:hadi_hoda_flutter/features/intro/presentation/ui/screens/intro_4_screen.dart'; |
|||
import 'package:hadi_hoda_flutter/features/intro/presentation/ui/screens/intro_5_screen.dart'; |
|||
|
|||
class IntroBloc extends Bloc<IntroEvent, IntroState> { |
|||
/// ------------constructor------------ |
|||
IntroBloc() : super(const IntroState()); |
|||
IntroBloc() : super(const IntroState()){ |
|||
on<ChangeIntroEvent>(_changeIntroEvent); |
|||
} |
|||
|
|||
/// ------------UseCases------------ |
|||
|
|||
/// ------------Variables------------ |
|||
final List<Widget> intros = [ |
|||
Intro1Screen(key: Key('0')), |
|||
Intro2Screen(key: Key('1')), |
|||
Intro3Screen(key: Key('2')), |
|||
Intro4Screen(key: Key('3')), |
|||
Intro5Screen(key: Key('4')), |
|||
]; |
|||
|
|||
/// ------------Controllers------------ |
|||
|
|||
/// ------------Functions------------ |
|||
Future<void> _precacheAllImages(BuildContext context) async { |
|||
await Future.wait( |
|||
MyAssets.images.map( |
|||
(assetPath) => precacheImage(AssetImage(assetPath), context), |
|||
), |
|||
); |
|||
void goToLevelPage(){ |
|||
ContextProvider.context.go(Routes.levelPage); |
|||
} |
|||
|
|||
Future<void> goToHomePage(BuildContext context) async { |
|||
if (context.mounted) { |
|||
await _precacheAllImages(context); |
|||
/// ------------Api Calls------------ |
|||
FutureOr<void> _changeIntroEvent(ChangeIntroEvent event, Emitter emit) async { |
|||
if (state.currentIntro < intros.length - 1) { |
|||
emit(state.copyWith(currentIntro: state.currentIntro + 1)); |
|||
} else { |
|||
goToLevelPage(); |
|||
} |
|||
|
|||
await Future.delayed( |
|||
Duration(seconds: 2), |
|||
() { |
|||
if (context.mounted) { |
|||
context.goNamed(Routes.homePage); |
|||
} |
|||
}, |
|||
); |
|||
} |
|||
|
|||
/// ------------Api Calls------------ |
|||
} |
|||
@ -1,3 +1,5 @@ |
|||
sealed class IntroEvent { |
|||
const IntroEvent(); |
|||
} |
|||
|
|||
class ChangeIntroEvent extends IntroEvent {} |
|||
@ -1,15 +1,21 @@ |
|||
import 'package:hadi_hoda_flutter/core/status/base_status.dart'; |
|||
|
|||
class IntroState { |
|||
final BaseStatus getFilesStatus; |
|||
final BaseStatus getIntroStatus; |
|||
final int currentIntro; |
|||
|
|||
const IntroState({this.getFilesStatus = const BaseInit()}); |
|||
const IntroState({ |
|||
this.getIntroStatus = const BaseInit(), |
|||
this.currentIntro = 0, |
|||
}); |
|||
|
|||
IntroState copyWith({ |
|||
BaseStatus? getFilesStatus, |
|||
BaseStatus? getIntroStatus, |
|||
int? currentIntro, |
|||
}) { |
|||
return IntroState( |
|||
getFilesStatus: getFilesStatus ?? this.getFilesStatus, |
|||
getIntroStatus: getIntroStatus ?? this.getIntroStatus, |
|||
currentIntro: currentIntro ?? this.currentIntro, |
|||
); |
|||
} |
|||
} |
|||
@ -1,82 +1,63 @@ |
|||
import 'package:flutter/material.dart'; |
|||
import 'package:flutter_bloc/flutter_bloc.dart'; |
|||
import 'package:hadi_hoda_flutter/common_ui/resources/my_assets.dart'; |
|||
import 'package:hadi_hoda_flutter/common_ui/resources/my_colors.dart'; |
|||
import 'package:hadi_hoda_flutter/common_ui/resources/my_spaces.dart'; |
|||
import 'package:hadi_hoda_flutter/core/utils/screen_size.dart'; |
|||
import 'package:hadi_hoda_flutter/core/widgets/animations/rotation_anim.dart'; |
|||
import 'package:hadi_hoda_flutter/core/widgets/images/my_image.dart'; |
|||
import 'package:hadi_hoda_flutter/common_ui/resources/my_text_style.dart'; |
|||
import 'package:hadi_hoda_flutter/core/utils/my_localization.dart'; |
|||
import 'package:hadi_hoda_flutter/features/intro/presentation/bloc/intro_bloc.dart'; |
|||
import 'package:hadi_hoda_flutter/features/intro/presentation/bloc/intro_event.dart'; |
|||
import 'package:hadi_hoda_flutter/features/intro/presentation/bloc/intro_state.dart'; |
|||
|
|||
class IntroPage extends StatefulWidget { |
|||
class IntroPage extends StatelessWidget { |
|||
const IntroPage({super.key}); |
|||
|
|||
@override |
|||
State<IntroPage> createState() => _IntroPageState(); |
|||
} |
|||
|
|||
class _IntroPageState extends State<IntroPage> { |
|||
@override |
|||
void initState() { |
|||
super.initState(); |
|||
WidgetsBinding.instance.addPostFrameCallback((_) { |
|||
context.read<IntroBloc>().goToHomePage(context); |
|||
}); |
|||
} |
|||
|
|||
|
|||
@override |
|||
Widget build(BuildContext context) { |
|||
return Scaffold( |
|||
body: Container( |
|||
height: context.heightScreen, |
|||
width: context.widthScreen, |
|||
decoration: BoxDecoration( |
|||
gradient: LinearGradient( |
|||
begin: Alignment.topCenter, |
|||
end: Alignment.bottomCenter, |
|||
colors: [ |
|||
Color(0XFF00154C), |
|||
Color(0XFF150532), |
|||
body: SizedBox.expand( |
|||
child: GestureDetector( |
|||
onTap: () => context.read<IntroBloc>().add(ChangeIntroEvent()), |
|||
child: Stack( |
|||
children: [ |
|||
_mainScreen(), |
|||
_skipButton(context), |
|||
], |
|||
), |
|||
image: DecorationImage( |
|||
image: AssetImage(MyAssets.pattern), |
|||
scale: 3, |
|||
repeat: ImageRepeat.repeat, |
|||
colorFilter: ColorFilter.mode( |
|||
Colors.white.withValues(alpha: 0.2), |
|||
BlendMode.srcIn, |
|||
), |
|||
), |
|||
), |
|||
child: Stack( |
|||
alignment: Alignment.center, |
|||
children: [ |
|||
_image(), |
|||
_loading(context), |
|||
], |
|||
), |
|||
), |
|||
); |
|||
} |
|||
|
|||
MyImage _image() { |
|||
return MyImage( |
|||
image: MyAssets.hadiHoda, |
|||
size: 200, |
|||
BlocBuilder<IntroBloc, IntroState> _mainScreen() { |
|||
return BlocBuilder<IntroBloc, IntroState>( |
|||
builder: (context, state) => AnimatedSwitcher( |
|||
duration: Duration(milliseconds: 200), |
|||
reverseDuration: Duration(milliseconds: 200), |
|||
switchInCurve: Curves.linear, |
|||
switchOutCurve: Curves.linear, |
|||
child: context.read<IntroBloc>().intros[state.currentIntro], |
|||
transitionBuilder: (child, animation) => |
|||
FadeTransition(opacity: animation, child: child), |
|||
), |
|||
); |
|||
} |
|||
|
|||
|
|||
Positioned _loading(BuildContext context) { |
|||
return Positioned( |
|||
bottom: MediaQuery.viewPaddingOf(context).bottom + MySpaces.s16, |
|||
child: RotationAnim( |
|||
child: MyImage( |
|||
image: MyAssets.loading, |
|||
size: 70, |
|||
PositionedDirectional _skipButton(BuildContext context) { |
|||
return PositionedDirectional( |
|||
start: MySpaces.s30, |
|||
bottom: MySpaces.s16, |
|||
child: TextButton( |
|||
onPressed: () => context.read<IntroBloc>().goToLevelPage(), |
|||
style: TextButton.styleFrom( |
|||
foregroundColor: MyColors.white.withValues(alpha: 0.7), |
|||
), |
|||
) |
|||
child: Text( |
|||
context.translate.skip, |
|||
style: MYTextStyle.button2.copyWith( |
|||
color: MyColors.white.withValues(alpha: 0.7), |
|||
), |
|||
), |
|||
), |
|||
); |
|||
} |
|||
} |
|||
@ -0,0 +1,54 @@ |
|||
import 'package:flutter/material.dart'; |
|||
import 'package:hadi_hoda_flutter/common_ui/resources/my_assets.dart'; |
|||
import 'package:hadi_hoda_flutter/common_ui/resources/my_spaces.dart'; |
|||
import 'package:hadi_hoda_flutter/core/utils/my_localization.dart'; |
|||
import 'package:hadi_hoda_flutter/core/utils/screen_size.dart'; |
|||
import 'package:hadi_hoda_flutter/core/utils/set_platform_size.dart'; |
|||
import 'package:hadi_hoda_flutter/core/widgets/animations/slide_up_fade.dart'; |
|||
import 'package:hadi_hoda_flutter/core/widgets/images/my_image.dart'; |
|||
import 'package:hadi_hoda_flutter/features/intro/presentation/ui/widgets/bubble_chat_widget.dart'; |
|||
|
|||
class Intro1Screen extends StatelessWidget { |
|||
const Intro1Screen({super.key}); |
|||
|
|||
@override |
|||
Widget build(BuildContext context) { |
|||
return Stack( |
|||
alignment: Alignment.center, |
|||
children: [ |
|||
Positioned.fill( |
|||
child: MyImage(image: MyAssets.intro_1, fit: BoxFit.cover), |
|||
), |
|||
PositionedDirectional( |
|||
end: setSize<double>( |
|||
context: context, |
|||
mobile: MySpaces.s10, |
|||
tablet: 0.15.w, |
|||
), |
|||
top: setSize<double>( |
|||
context: context, |
|||
mobile: 0.15.h, |
|||
tablet: 0.25.h, |
|||
), |
|||
width: 290, |
|||
child: SlideUpFade( |
|||
delay: Duration(milliseconds: 300), |
|||
child: BubbleChatWidget( |
|||
text: context.translate.intro_1_1, |
|||
flip: true, |
|||
), |
|||
), |
|||
), |
|||
PositionedDirectional( |
|||
start: setSize(context: context, mobile: MySpaces.s30, tablet: 0.2.w), |
|||
top: setSize(context: context, mobile: 0.3.h, tablet: 0.35.h), |
|||
width: 250, |
|||
child: SlideUpFade( |
|||
delay: Duration(milliseconds: 800), |
|||
child: BubbleChatWidget(text: context.translate.intro_1_2), |
|||
), |
|||
), |
|||
], |
|||
); |
|||
} |
|||
} |
|||
@ -0,0 +1,37 @@ |
|||
import 'package:flutter/material.dart'; |
|||
import 'package:hadi_hoda_flutter/common_ui/resources/my_assets.dart'; |
|||
import 'package:hadi_hoda_flutter/common_ui/resources/my_spaces.dart'; |
|||
import 'package:hadi_hoda_flutter/core/utils/my_localization.dart'; |
|||
import 'package:hadi_hoda_flutter/core/utils/screen_size.dart'; |
|||
import 'package:hadi_hoda_flutter/core/utils/set_platform_size.dart'; |
|||
import 'package:hadi_hoda_flutter/core/widgets/animations/slide_up_fade.dart'; |
|||
import 'package:hadi_hoda_flutter/core/widgets/images/my_image.dart'; |
|||
import 'package:hadi_hoda_flutter/features/intro/presentation/ui/widgets/bubble_chat_widget.dart'; |
|||
|
|||
class Intro2Screen extends StatelessWidget { |
|||
const Intro2Screen({super.key}); |
|||
|
|||
@override |
|||
Widget build(BuildContext context) { |
|||
return Stack( |
|||
alignment: Alignment.center, |
|||
children: [ |
|||
Positioned.fill( |
|||
child: Transform.flip( |
|||
flipX: true, |
|||
child: MyImage(image: MyAssets.intro_2, fit: BoxFit.cover), |
|||
), |
|||
), |
|||
PositionedDirectional( |
|||
end: setSize(context: context, mobile: MySpaces.s40, tablet: 0.3.w), |
|||
top: setSize(context: context, mobile: 0.17.h, tablet: 0.23.h), |
|||
width: 250, |
|||
child: SlideUpFade( |
|||
delay: Duration(milliseconds: 300), |
|||
child: BubbleChatWidget(text: context.translate.intro_2), |
|||
), |
|||
), |
|||
], |
|||
); |
|||
} |
|||
} |
|||
@ -0,0 +1,37 @@ |
|||
import 'package:flutter/material.dart'; |
|||
import 'package:hadi_hoda_flutter/common_ui/resources/my_assets.dart'; |
|||
import 'package:hadi_hoda_flutter/common_ui/resources/my_spaces.dart'; |
|||
import 'package:hadi_hoda_flutter/core/utils/my_localization.dart'; |
|||
import 'package:hadi_hoda_flutter/core/utils/screen_size.dart'; |
|||
import 'package:hadi_hoda_flutter/core/utils/set_platform_size.dart'; |
|||
import 'package:hadi_hoda_flutter/core/widgets/animations/slide_up_fade.dart'; |
|||
import 'package:hadi_hoda_flutter/core/widgets/images/my_image.dart'; |
|||
import 'package:hadi_hoda_flutter/features/intro/presentation/ui/widgets/bubble_chat_widget.dart'; |
|||
|
|||
class Intro3Screen extends StatelessWidget { |
|||
const Intro3Screen({super.key}); |
|||
|
|||
@override |
|||
Widget build(BuildContext context) { |
|||
return Stack( |
|||
alignment: Alignment.center, |
|||
children: [ |
|||
Positioned.fill( |
|||
child: MyImage(image: MyAssets.intro_3, fit: BoxFit.cover), |
|||
), |
|||
PositionedDirectional( |
|||
start: setSize(context: context, mobile: MySpaces.s30), |
|||
top: setSize(context: context, mobile: 180, tablet: 0.25.h), |
|||
width: 270, |
|||
child: SlideUpFade( |
|||
delay: Duration(milliseconds: 300), |
|||
child: BubbleChatWidget( |
|||
text: context.translate.intro_3, |
|||
flip: true, |
|||
), |
|||
), |
|||
), |
|||
], |
|||
); |
|||
} |
|||
} |
|||
@ -0,0 +1,36 @@ |
|||
import 'package:flutter/material.dart'; |
|||
import 'package:hadi_hoda_flutter/common_ui/resources/my_assets.dart'; |
|||
import 'package:hadi_hoda_flutter/common_ui/resources/my_spaces.dart'; |
|||
import 'package:hadi_hoda_flutter/core/utils/my_localization.dart'; |
|||
import 'package:hadi_hoda_flutter/core/utils/screen_size.dart'; |
|||
import 'package:hadi_hoda_flutter/core/utils/set_platform_size.dart'; |
|||
import 'package:hadi_hoda_flutter/core/widgets/animations/slide_up_fade.dart'; |
|||
import 'package:hadi_hoda_flutter/core/widgets/images/my_image.dart'; |
|||
import 'package:hadi_hoda_flutter/features/intro/presentation/ui/widgets/bubble_chat_widget.dart'; |
|||
|
|||
class Intro4Screen extends StatelessWidget { |
|||
const Intro4Screen({super.key}); |
|||
|
|||
@override |
|||
Widget build(BuildContext context) { |
|||
return Stack( |
|||
alignment: Alignment.center, |
|||
children: [ |
|||
Positioned.fill( |
|||
child: MyImage(image: MyAssets.intro_4, fit: BoxFit.cover), |
|||
), |
|||
PositionedDirectional( |
|||
start: setSize(context: context, mobile: MySpaces.s10, tablet: 0.2.w), |
|||
bottom: setSize(context: context, mobile: 0.4.h, tablet: 0.4.h), |
|||
width: 237, |
|||
child: SlideUpFade( |
|||
delay: Duration(milliseconds: 300), |
|||
child: BubbleChatWidget( |
|||
text: context.translate.intro_4, |
|||
), |
|||
), |
|||
), |
|||
], |
|||
); |
|||
} |
|||
} |
|||
@ -0,0 +1,34 @@ |
|||
import 'package:flutter/material.dart'; |
|||
import 'package:hadi_hoda_flutter/common_ui/resources/my_assets.dart'; |
|||
import 'package:hadi_hoda_flutter/core/utils/my_localization.dart'; |
|||
import 'package:hadi_hoda_flutter/core/utils/screen_size.dart'; |
|||
import 'package:hadi_hoda_flutter/core/utils/set_platform_size.dart'; |
|||
import 'package:hadi_hoda_flutter/core/widgets/animations/slide_up_fade.dart'; |
|||
import 'package:hadi_hoda_flutter/core/widgets/images/my_image.dart'; |
|||
import 'package:hadi_hoda_flutter/features/intro/presentation/ui/widgets/bubble_chat_widget.dart'; |
|||
|
|||
class Intro5Screen extends StatelessWidget { |
|||
const Intro5Screen({super.key}); |
|||
|
|||
@override |
|||
Widget build(BuildContext context) { |
|||
return Stack( |
|||
alignment: Alignment.center, |
|||
children: [ |
|||
Positioned.fill( |
|||
child: MyImage(image: MyAssets.intro_5, fit: BoxFit.cover), |
|||
), |
|||
PositionedDirectional( |
|||
top: setSize(context: context, mobile: 0.37.h, tablet: 0.42.h), |
|||
width: 200, |
|||
child: SlideUpFade( |
|||
delay: Duration(milliseconds: 300), |
|||
child: BubbleChatWidget( |
|||
text: context.translate.intro_5, |
|||
), |
|||
), |
|||
), |
|||
], |
|||
); |
|||
} |
|||
} |
|||
@ -0,0 +1,91 @@ |
|||
import 'package:flutter/material.dart'; |
|||
import 'package:hadi_hoda_flutter/common_ui/resources/my_colors.dart'; |
|||
import 'package:hadi_hoda_flutter/common_ui/resources/my_spaces.dart'; |
|||
import 'package:hadi_hoda_flutter/common_ui/resources/my_text_style.dart'; |
|||
|
|||
class BubbleChatWidget extends StatelessWidget { |
|||
const BubbleChatWidget({ |
|||
super.key, |
|||
this.text, |
|||
this.width, |
|||
this.flip = false, |
|||
}); |
|||
|
|||
final String? text; |
|||
final double? width; |
|||
final bool flip; |
|||
|
|||
@override |
|||
Widget build(BuildContext context) { |
|||
return ClipPath( |
|||
clipper: _ShapeClipper(flip: flip), |
|||
child: Container( |
|||
width: width, |
|||
padding: EdgeInsets.only( |
|||
left: MySpaces.s18, |
|||
right: MySpaces.s18, |
|||
top: MySpaces.s16, |
|||
bottom: MySpaces.s28, |
|||
), |
|||
decoration: BoxDecoration( |
|||
color: Color(0XFFF5E8D7).withValues(alpha: 0.5), |
|||
borderRadius: BorderRadius.all(Radius.circular(20)), |
|||
border: Border.all( |
|||
width: 1, |
|||
color: MyColors.white.withValues(alpha: 0.5), |
|||
), |
|||
), |
|||
child: Text( |
|||
text ?? '', |
|||
style: MYTextStyle.titr3.copyWith( |
|||
color: MyColors.black, |
|||
), |
|||
), |
|||
), |
|||
); |
|||
} |
|||
} |
|||
|
|||
|
|||
|
|||
class _ShapeClipper extends CustomClipper<Path> { |
|||
final bool flip; |
|||
|
|||
_ShapeClipper({this.flip = false}); // Add constructor |
|||
|
|||
@override |
|||
Path getClip(Size size) { |
|||
var path = Path(); |
|||
double w = size.width; |
|||
double h = size.height; |
|||
|
|||
// The drawing logic remains exactly the same |
|||
path.moveTo(w * 0.92, 0); |
|||
path.cubicTo(w * 0.96, 0, w, h * 0.05, w, h * 0.12); |
|||
path.lineTo(w, h * 0.70); |
|||
path.cubicTo(w, h * 0.78, w * 0.96, h * 0.83, w * 0.92, h * 0.83); |
|||
path.lineTo(w * 0.35, h * 0.83); |
|||
path.lineTo(w * 0.285, h); |
|||
path.lineTo(w * 0.20, h * 0.83); |
|||
path.lineTo(w * 0.08, h * 0.83); |
|||
path.cubicTo(w * 0.03, h * 0.83, 0, h * 0.78, 0, h * 0.70); |
|||
path.lineTo(0, h * 0.12); |
|||
path.cubicTo(0, h * 0.05, w * 0.03, 0, w * 0.08, 0); |
|||
path.close(); |
|||
|
|||
// If flip is true, transform the path horizontally |
|||
if (flip) { |
|||
final flipMatrix = Matrix4.identity() |
|||
..translateByDouble(w, 0.0, 0.0, 1.0) |
|||
..scaleByDouble(-1.0, 1.0, 1.0, 1.0); |
|||
return path.transform(flipMatrix.storage); |
|||
} |
|||
|
|||
return path; |
|||
} |
|||
|
|||
@override |
|||
bool shouldReclip(covariant _ShapeClipper oldClipper) { |
|||
return oldClipper.flip != flip; // Reclip if the flip state changes |
|||
} |
|||
} |
|||
@ -0,0 +1,44 @@ |
|||
import 'package:bloc/bloc.dart'; |
|||
import 'package:flutter/cupertino.dart'; |
|||
import 'package:go_router/go_router.dart'; |
|||
import 'package:hadi_hoda_flutter/common_ui/resources/my_assets.dart'; |
|||
import 'package:hadi_hoda_flutter/core/routers/my_routes.dart'; |
|||
import 'package:hadi_hoda_flutter/features/splash/presentation/bloc/splash_event.dart'; |
|||
import 'package:hadi_hoda_flutter/features/splash/presentation/bloc/splash_state.dart'; |
|||
|
|||
class SplashBloc extends Bloc<SplashEvent, SplashState> { |
|||
/// ------------constructor------------ |
|||
SplashBloc() : super(const SplashState()); |
|||
|
|||
/// ------------UseCases------------ |
|||
|
|||
/// ------------Variables------------ |
|||
|
|||
/// ------------Controllers------------ |
|||
|
|||
/// ------------Functions------------ |
|||
Future<void> _precacheAllImages(BuildContext context) async { |
|||
await Future.wait( |
|||
MyAssets.images.map( |
|||
(assetPath) => precacheImage(AssetImage(assetPath), context), |
|||
), |
|||
); |
|||
} |
|||
|
|||
Future<void> goToHomePage(BuildContext context) async { |
|||
if (context.mounted) { |
|||
await _precacheAllImages(context); |
|||
} |
|||
|
|||
await Future.delayed( |
|||
Duration(seconds: 2), |
|||
() { |
|||
if (context.mounted) { |
|||
context.goNamed(Routes.homePage); |
|||
} |
|||
}, |
|||
); |
|||
} |
|||
|
|||
/// ------------Api Calls------------ |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
sealed class SplashEvent { |
|||
const SplashEvent(); |
|||
} |
|||
@ -0,0 +1,15 @@ |
|||
import 'package:hadi_hoda_flutter/core/status/base_status.dart'; |
|||
|
|||
class SplashState { |
|||
final BaseStatus getFilesStatus; |
|||
|
|||
const SplashState({this.getFilesStatus = const BaseInit()}); |
|||
|
|||
SplashState copyWith({ |
|||
BaseStatus? getFilesStatus, |
|||
}) { |
|||
return SplashState( |
|||
getFilesStatus: getFilesStatus ?? this.getFilesStatus, |
|||
); |
|||
} |
|||
} |
|||
@ -0,0 +1,82 @@ |
|||
import 'package:flutter/material.dart'; |
|||
import 'package:flutter_bloc/flutter_bloc.dart'; |
|||
import 'package:hadi_hoda_flutter/common_ui/resources/my_assets.dart'; |
|||
import 'package:hadi_hoda_flutter/common_ui/resources/my_spaces.dart'; |
|||
import 'package:hadi_hoda_flutter/core/utils/screen_size.dart'; |
|||
import 'package:hadi_hoda_flutter/core/widgets/animations/rotation_anim.dart'; |
|||
import 'package:hadi_hoda_flutter/core/widgets/images/my_image.dart'; |
|||
import 'package:hadi_hoda_flutter/features/splash/presentation/bloc/splash_bloc.dart'; |
|||
|
|||
class SplashPage extends StatefulWidget { |
|||
const SplashPage({super.key}); |
|||
|
|||
@override |
|||
State<SplashPage> createState() => _SplashPageState(); |
|||
} |
|||
|
|||
class _SplashPageState extends State<SplashPage> { |
|||
@override |
|||
void initState() { |
|||
super.initState(); |
|||
WidgetsBinding.instance.addPostFrameCallback((_) { |
|||
context.read<SplashBloc>().goToHomePage(context); |
|||
}); |
|||
} |
|||
|
|||
|
|||
@override |
|||
Widget build(BuildContext context) { |
|||
return Scaffold( |
|||
body: Container( |
|||
height: context.heightScreen, |
|||
width: context.widthScreen, |
|||
decoration: BoxDecoration( |
|||
gradient: LinearGradient( |
|||
begin: Alignment.topCenter, |
|||
end: Alignment.bottomCenter, |
|||
colors: [ |
|||
Color(0XFF00154C), |
|||
Color(0XFF150532), |
|||
], |
|||
), |
|||
image: DecorationImage( |
|||
image: AssetImage(MyAssets.pattern), |
|||
scale: 3, |
|||
repeat: ImageRepeat.repeat, |
|||
colorFilter: ColorFilter.mode( |
|||
Colors.white.withValues(alpha: 0.2), |
|||
BlendMode.srcIn, |
|||
), |
|||
), |
|||
), |
|||
child: Stack( |
|||
alignment: Alignment.center, |
|||
children: [ |
|||
_image(), |
|||
_loading(context), |
|||
], |
|||
), |
|||
), |
|||
); |
|||
} |
|||
|
|||
MyImage _image() { |
|||
return MyImage( |
|||
image: MyAssets.hadiHoda, |
|||
size: 200, |
|||
); |
|||
} |
|||
|
|||
|
|||
Positioned _loading(BuildContext context) { |
|||
return Positioned( |
|||
bottom: MediaQuery.viewPaddingOf(context).bottom + MySpaces.s16, |
|||
child: RotationAnim( |
|||
child: MyImage( |
|||
image: MyAssets.loading, |
|||
size: 70, |
|||
), |
|||
) |
|||
); |
|||
} |
|||
} |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue