Browse Source

add: complete intro feature and responsive

pull/27/head
AmirrezaChegini 3 days ago
parent
commit
ad38ffae6d
  1. BIN
      assets/fonts/Baloo2-Bold.ttf
  2. BIN
      assets/fonts/Baloo2-ExtraBold.ttf
  3. BIN
      assets/fonts/Baloo2-Medium.ttf
  4. BIN
      assets/fonts/Baloo2-SemiBold.ttf
  5. 0
      assets/fonts/DinoKids-Regular.ttf
  6. BIN
      assets/fonts/Marhey-Light.ttf
  7. BIN
      assets/fonts/Marhey-Medium.ttf
  8. BIN
      assets/fonts/Marhey-Regular.ttf
  9. BIN
      assets/images/intro_1.jpg
  10. BIN
      assets/images/intro_2.jpg
  11. BIN
      assets/images/intro_3.jpg
  12. BIN
      assets/images/intro_4.jpg
  13. BIN
      assets/images/intro_5.jpg
  14. 10
      lib/common_ui/resources/my_assets.dart
  15. 137
      lib/common_ui/resources/my_text_style.dart
  16. 18
      lib/common_ui/theme/my_theme.dart
  17. 2
      lib/core/routers/my_routes.dart
  18. 14
      lib/core/utils/my_device.dart
  19. 7
      lib/core/utils/screen_size.dart
  20. 18
      lib/core/utils/set_platform_size.dart
  21. 16
      lib/core/widgets/about_us_dialog/about_us_dialog.dart
  22. 6
      lib/core/widgets/about_us_dialog/styles/background.dart
  23. 67
      lib/core/widgets/animations/slide_up_fade.dart
  24. 8
      lib/core/widgets/hadith_dialog/hadith_dialog.dart
  25. 29
      lib/features/intro/presentation/bloc/intro_bloc.dart
  26. 2
      lib/features/intro/presentation/bloc/intro_event.dart
  27. 8
      lib/features/intro/presentation/bloc/intro_state.dart
  28. 55
      lib/features/intro/presentation/ui/intro_page.dart
  29. 54
      lib/features/intro/presentation/ui/screens/intro_1_screen.dart
  30. 37
      lib/features/intro/presentation/ui/screens/intro_2_screen.dart
  31. 37
      lib/features/intro/presentation/ui/screens/intro_3_screen.dart
  32. 36
      lib/features/intro/presentation/ui/screens/intro_4_screen.dart
  33. 34
      lib/features/intro/presentation/ui/screens/intro_5_screen.dart
  34. 91
      lib/features/intro/presentation/ui/widgets/bubble_chat_widget.dart
  35. 9
      lib/l10n/app_en.arb
  36. 42
      lib/l10n/app_localizations.dart
  37. 24
      lib/l10n/app_localizations_en.dart
  38. 1
      lib/main.dart
  39. 31
      pubspec.yaml

BIN
assets/fonts/Baloo2-Bold.ttf

BIN
assets/fonts/Baloo2-ExtraBold.ttf

BIN
assets/fonts/Baloo2-Medium.ttf

BIN
assets/fonts/Baloo2-SemiBold.ttf

0
assets/fonts/dinokids.ttf → assets/fonts/DinoKids-Regular.ttf

BIN
assets/fonts/Marhey-Light.ttf

BIN
assets/fonts/Marhey-Medium.ttf

BIN
assets/fonts/Marhey-Regular.ttf

BIN
assets/images/intro_1.jpg

After

Width: 819  |  Height: 1229  |  Size: 147 KiB

BIN
assets/images/intro_2.jpg

After

Width: 819  |  Height: 1229  |  Size: 139 KiB

BIN
assets/images/intro_3.jpg

After

Width: 819  |  Height: 1229  |  Size: 134 KiB

BIN
assets/images/intro_4.jpg

After

Width: 819  |  Height: 1229  |  Size: 141 KiB

BIN
assets/images/intro_5.jpg

After

Width: 819  |  Height: 1229  |  Size: 179 KiB

10
lib/common_ui/resources/my_assets.dart

@ -22,6 +22,11 @@ class MyAssets {
static const String ship = 'assets/images/ship.png';
static const String shiny = 'assets/images/shiny.png';
static const String loading = 'assets/images/loading.png';
static const String intro_1 = 'assets/images/intro_1.jpg';
static const String intro_2 = 'assets/images/intro_2.jpg';
static const String intro_3 = 'assets/images/intro_3.jpg';
static const String intro_4 = 'assets/images/intro_4.jpg';
static const String intro_5 = 'assets/images/intro_5.jpg';
/// SVG
static const String closeBtn = 'assets/svg/close_btn.svg';
@ -71,5 +76,10 @@ class MyAssets {
ship,
shiny,
loading,
intro_1,
intro_2,
intro_3,
intro_4,
intro_5,
];
}

137
lib/common_ui/resources/my_text_style.dart

@ -1,11 +1,12 @@
import 'package:flutter/material.dart';
import 'package:hadi_hoda_flutter/common_ui/resources/my_colors.dart';
class DinoKids {
static const DinoKids _i = DinoKids._internal();
const DinoKids._internal();
factory DinoKids() => _i;
static const String fontFamily = 'dinokids';
static const String fontFamily = 'DinoKids';
/// Regular
static const TextStyle regular17 = TextStyle(
@ -33,6 +34,11 @@ class DinoKids {
fontSize: 45,
fontWeight: FontWeight.w400,
);
static const TextStyle regular = TextStyle(
fontFamily: fontFamily,
fontWeight: FontWeight.w400,
);
}
class Marhey {
@ -40,7 +46,7 @@ class Marhey {
const Marhey._internal();
factory Marhey() => _i;
static const String fontFamily = 'marhey';
static const String fontFamily = 'Marhey';
/// Medium
static const TextStyle medium12 = TextStyle(
@ -97,4 +103,131 @@ class Marhey {
fontSize: 26,
fontWeight: FontWeight.w700,
);
static const TextStyle semiBold = TextStyle(
fontFamily: fontFamily,
fontWeight: FontWeight.w600,
);
static const TextStyle bold = TextStyle(
fontFamily: fontFamily,
fontWeight: FontWeight.w700,
);
}
class Baloo2 {
static const Baloo2 _i = Baloo2._internal();
const Baloo2._internal();
factory Baloo2() => _i;
static const String fontFamily = 'Baloo_2';
static const TextStyle medium = TextStyle(
fontFamily: fontFamily,
fontWeight: FontWeight.w500,
);
static const TextStyle semiBold = TextStyle(
fontFamily: fontFamily,
fontWeight: FontWeight.w600,
);
static const TextStyle bold = TextStyle(
fontFamily: fontFamily,
fontWeight: FontWeight.w700,
);
static const TextStyle extraBold = TextStyle(
fontFamily: fontFamily,
fontWeight: FontWeight.w800,
);
}
class MYTextStyle {
static const MYTextStyle _i = MYTextStyle._internal();
const MYTextStyle._internal();
factory MYTextStyle() => _i;
static const String dinoKids = 'DinoKids';
static const String marhey = 'Marhey';
static const String baloo2 = 'Baloo_2';
static const Color textColor = MyColors.white;
static const TextStyle titr0 = TextStyle(
fontFamily: marhey,
fontWeight: FontWeight.w700,
fontSize: 26,
color: textColor,
);
static const TextStyle titr1 = TextStyle(
fontFamily: baloo2,
fontWeight: FontWeight.w800,
fontSize: 20,
color: textColor,
);
static const TextStyle titr3 = TextStyle(
fontFamily: marhey,
fontWeight: FontWeight.w600,
fontSize: 18,
color: textColor,
);
static const TextStyle titr4 = TextStyle(
fontFamily: baloo2,
fontWeight: FontWeight.w700,
fontSize: 14,
color: textColor,
);
static const TextStyle matn1 = TextStyle(
fontFamily: baloo2,
fontWeight: FontWeight.w600,
fontSize: 18,
color: textColor,
);
static const TextStyle matn2_3 = TextStyle(
fontFamily: baloo2,
fontWeight: FontWeight.w700,
fontSize: 18,
color: textColor,
);
static const TextStyle matn2_2 = TextStyle(
fontFamily: baloo2,
fontWeight: FontWeight.w700,
fontSize: 16,
color: textColor,
);
static const TextStyle matn2 = TextStyle(
fontFamily: baloo2,
fontWeight: FontWeight.w700,
fontSize: 14,
color: textColor,
);
static const TextStyle matn3 = TextStyle(
fontFamily: baloo2,
fontWeight: FontWeight.w500,
fontSize: 12,
color: textColor,
);
static const TextStyle button1 = TextStyle(
fontFamily: dinoKids,
fontWeight: FontWeight.w400,
fontSize: 45,
color: textColor,
);
static const TextStyle button2 = TextStyle(
fontFamily: dinoKids,
fontWeight: FontWeight.w400,
fontSize: 30,
color: textColor,
);
}

18
lib/common_ui/theme/my_theme.dart

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

2
lib/core/routers/my_routes.dart

@ -40,7 +40,7 @@ class Routes {
}
GoRouter get appPages => GoRouter(
initialLocation: Routes.introPage,
initialLocation: Routes.splashPage,
navigatorKey: ContextProvider.navigatorKey,
routes: [
GoRoute(

14
lib/core/utils/my_device.dart

@ -65,7 +65,6 @@ class MyDevice {
await SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
]);
}
static Future<void> setLandscape() async {
@ -83,4 +82,17 @@ class MyDevice {
DeviceOrientation.portraitDown,
]);
}
/// Set System UI Mode
static Future<void> setEdgeToEdge() async {
await SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
}
static Future<void> setImmersiveSticky() async {
await SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky);
}
static Future<void> setImmersive() async {
await SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersive);
}
}

7
lib/core/utils/screen_size.dart

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

18
lib/core/utils/check_platform.dart → lib/core/utils/set_platform_size.dart

@ -1,10 +1,10 @@
import 'package:flutter/cupertino.dart';
import 'package:hadi_hoda_flutter/core/utils/my_device.dart';
dynamic checkPlatform({
dynamic android,
dynamic iOS,
dynamic web,
T? setPlatform<T>({
T? android,
T? iOS,
T? web,
}) {
if (MyDevice.isAndroid()) {
return android;
@ -12,14 +12,16 @@ dynamic checkPlatform({
return iOS;
} else if (MyDevice.isWeb()) {
return web;
} else {
return null;
}
}
double? checkSize({
T? setSize<T>({
required BuildContext context,
double? mobile,
double? tablet,
double? desktop,
T? mobile,
T? tablet,
T? desktop,
}) {
if (MyDevice.isMobile(context)) {
return mobile;

16
lib/core/widgets/about_us_dialog/about_us_dialog.dart

@ -5,8 +5,8 @@ import 'package:go_router/go_router.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_text_style.dart';
import 'package:hadi_hoda_flutter/core/utils/check_platform.dart';
import 'package:hadi_hoda_flutter/core/utils/my_localization.dart';
import 'package:hadi_hoda_flutter/core/utils/set_platform_size.dart';
import 'package:hadi_hoda_flutter/core/widgets/about_us_dialog/styles/background.dart';
import 'package:hadi_hoda_flutter/core/widgets/images/my_image.dart';
@ -31,7 +31,7 @@ class AboutUsDialog extends StatelessWidget {
child: Center(
child: Padding(
padding: EdgeInsets.symmetric(
horizontal: checkSize(
horizontal: setSize(
context: context,
mobile: 18,
tablet: 120,
@ -69,19 +69,19 @@ class AboutUsDialog extends StatelessWidget {
children: [
MyImage(
image: MyAssets.facebook,
size: checkSize(context: context, mobile: 33, tablet: 46),
size: setSize(context: context, mobile: 33, tablet: 46),
),
MyImage(
image: MyAssets.instagram,
size: checkSize(context: context, mobile: 33, tablet: 46),
size: setSize(context: context, mobile: 33, tablet: 46),
),
MyImage(
image: MyAssets.whatsapp,
size: checkSize(context: context, mobile: 33, tablet: 46),
size: setSize(context: context, mobile: 33, tablet: 46),
),
MyImage(
image: MyAssets.youtube,
size: checkSize(context: context, mobile: 33, tablet: 46),
size: setSize(context: context, mobile: 33, tablet: 46),
),
],
),
@ -89,14 +89,14 @@ class AboutUsDialog extends StatelessWidget {
),
),
Positioned(
right: checkSize(context: context, mobile: 30, tablet: 40),
right: setSize(context: context, mobile: 30, tablet: 40),
top: -12,
child: GestureDetector(
onTap: context.pop,
behavior: HitTestBehavior.opaque,
child: MyImage(
image: MyAssets.closeBtn,
size: checkSize(context: context, mobile: 40, tablet: 60),
size: setSize(context: context, mobile: 40, tablet: 60),
),
),
),

6
lib/core/widgets/about_us_dialog/styles/background.dart

@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
import 'package:hadi_hoda_flutter/core/utils/check_platform.dart';
import 'package:hadi_hoda_flutter/core/utils/screen_size.dart';
import 'package:hadi_hoda_flutter/core/utils/set_platform_size.dart';
class AboutUSDialogBackground extends StatelessWidget {
const AboutUSDialogBackground({super.key, this.child});
@ -13,9 +13,9 @@ class AboutUSDialogBackground extends StatelessWidget {
clipper: _BottomShapeClipper(),
child: Container(
width: context.widthScreen,
height: checkSize(context: context, mobile: 525, tablet: 740),
height: setSize(context: context, mobile: 525, tablet: 740),
padding: EdgeInsets.all(
checkSize(
setSize(
context: context,
mobile: 30,
tablet: 60,

67
lib/core/widgets/animations/slide_up_fade.dart

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

8
lib/core/widgets/hadith_dialog/hadith_dialog.dart

@ -6,7 +6,7 @@ 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/common_ui/resources/my_text_style.dart';
import 'package:hadi_hoda_flutter/core/utils/check_platform.dart';
import 'package:hadi_hoda_flutter/core/utils/set_platform_size.dart';
import 'package:hadi_hoda_flutter/core/widgets/about_us_dialog/styles/background.dart';
import 'package:hadi_hoda_flutter/core/widgets/images/my_image.dart';
import 'package:hadi_hoda_flutter/features/question/domain/entity/hadith_entity.dart';
@ -37,7 +37,7 @@ class HadithDialog extends StatelessWidget {
child: Center(
child: Padding(
padding: EdgeInsets.symmetric(
horizontal: checkSize(
horizontal: setSize(
context: context,
mobile: 18,
tablet: 120,
@ -65,14 +65,14 @@ class HadithDialog extends StatelessWidget {
),
),
Positioned(
right: checkSize(context: context, mobile: 30, tablet: 40),
right: setSize(context: context, mobile: 30, tablet: 40),
top: -12,
child: GestureDetector(
onTap: context.pop,
behavior: HitTestBehavior.opaque,
child: MyImage(
image: MyAssets.closeBtn,
size: checkSize(context: context, mobile: 40, tablet: 60),
size: setSize(context: context, mobile: 40, tablet: 60),
),
),
),

29
lib/features/intro/presentation/bloc/intro_bloc.dart

@ -1,23 +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/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()){
on<GetIntroEvent>(_getIntroEvent);
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------------
void goToLevelPage(){
ContextProvider.context.go(Routes.levelPage);
}
/// ------------Api Calls------------
FutureOr<void> _getIntroEvent(event, emit) async {}
FutureOr<void> _changeIntroEvent(ChangeIntroEvent event, Emitter emit) async {
if (state.currentIntro < intros.length - 1) {
emit(state.copyWith(currentIntro: state.currentIntro + 1));
} else {
goToLevelPage();
}
}
}

2
lib/features/intro/presentation/bloc/intro_event.dart

@ -2,4 +2,4 @@ sealed class IntroEvent {
const IntroEvent();
}
class GetIntroEvent extends IntroEvent {}
class ChangeIntroEvent extends IntroEvent {}

8
lib/features/intro/presentation/bloc/intro_state.dart

@ -2,14 +2,20 @@ import 'package:hadi_hoda_flutter/core/status/base_status.dart';
class IntroState {
final BaseStatus getIntroStatus;
final int currentIntro;
const IntroState({this.getIntroStatus = const BaseInit()});
const IntroState({
this.getIntroStatus = const BaseInit(),
this.currentIntro = 0,
});
IntroState copyWith({
BaseStatus? getIntroStatus,
int? currentIntro,
}) {
return IntroState(
getIntroStatus: getIntroStatus ?? this.getIntroStatus,
currentIntro: currentIntro ?? this.currentIntro,
);
}
}

55
lib/features/intro/presentation/ui/intro_page.dart

@ -1,10 +1,63 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.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';
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 StatelessWidget {
const IntroPage({super.key});
@override
Widget build(BuildContext context) {
return const Scaffold();
return Scaffold(
body: SizedBox.expand(
child: GestureDetector(
onTap: () => context.read<IntroBloc>().add(ChangeIntroEvent()),
child: Stack(
children: [
_mainScreen(),
_skipButton(context),
],
),
),
),
);
}
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),
),
);
}
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),
),
),
),
);
}
}

54
lib/features/intro/presentation/ui/screens/intro_1_screen.dart

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

37
lib/features/intro/presentation/ui/screens/intro_2_screen.dart

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

37
lib/features/intro/presentation/ui/screens/intro_3_screen.dart

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

36
lib/features/intro/presentation/ui/screens/intro_4_screen.dart

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

34
lib/features/intro/presentation/ui/screens/intro_5_screen.dart

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

91
lib/features/intro/presentation/ui/widgets/bubble_chat_widget.dart

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

9
lib/l10n/app_en.arb

@ -17,5 +17,12 @@
"you_got_diamond": "You got the diamond",
"view_map": "View Map",
"go_next": "Go Next",
"you_win": "You Win!"
"you_win": "You Win!",
"skip": "Skip",
"intro_1_1": "Dinner is ready! Come quickly and wash your beautiful hands!",
"intro_1_2": "Mom! Our hands aren't that dirty! We'll just wipe them with a tissue!",
"intro_2": "The purity of faith... \nIt means cleanliness is a sign of faith!",
"intro_3": "These good deeds make our souls strong and beautiful!",
"intro_4": "Do you want to travel to the Promised Garden?",
"intro_5": "Yessss....\nWe are ready!"
}

42
lib/l10n/app_localizations.dart

@ -207,6 +207,48 @@ abstract class AppLocalizations {
/// In en, this message translates to:
/// **'You Win!'**
String get you_win;
/// No description provided for @skip.
///
/// In en, this message translates to:
/// **'Skip'**
String get skip;
/// No description provided for @intro_1_1.
///
/// In en, this message translates to:
/// **'Dinner is ready! Come quickly and wash your beautiful hands!'**
String get intro_1_1;
/// No description provided for @intro_1_2.
///
/// In en, this message translates to:
/// **'Mom! Our hands aren\'t that dirty! We\'ll just wipe them with a tissue!'**
String get intro_1_2;
/// No description provided for @intro_2.
///
/// In en, this message translates to:
/// **'The purity of faith... \nIt means cleanliness is a sign of faith!'**
String get intro_2;
/// No description provided for @intro_3.
///
/// In en, this message translates to:
/// **'These good deeds make our souls strong and beautiful!'**
String get intro_3;
/// No description provided for @intro_4.
///
/// In en, this message translates to:
/// **'Do you want to travel to the Promised Garden?'**
String get intro_4;
/// No description provided for @intro_5.
///
/// In en, this message translates to:
/// **'Yessss....\nWe are ready!'**
String get intro_5;
}
class _AppLocalizationsDelegate

24
lib/l10n/app_localizations_en.dart

@ -66,4 +66,28 @@ class AppLocalizationsEn extends AppLocalizations {
@override
String get you_win => 'You Win!';
@override
String get skip => 'Skip';
@override
String get intro_1_1 =>
'Dinner is ready! Come quickly and wash your beautiful hands!';
@override
String get intro_1_2 =>
'Mom! Our hands aren\'t that dirty! We\'ll just wipe them with a tissue!';
@override
String get intro_2 =>
'The purity of faith... \nIt means cleanliness is a sign of faith!';
@override
String get intro_3 => 'These good deeds make our souls strong and beautiful!';
@override
String get intro_4 => 'Do you want to travel to the Promised Garden?';
@override
String get intro_5 => 'Yessss....\nWe are ready!';
}

1
lib/main.dart

@ -17,6 +17,7 @@ Future<void> main() async {
StoragePath.getDocumentDir(),
initDataBase(),
MyDevice.setPortrait(),
MyDevice.setImmersiveSticky(),
]);
runApp(const MainApp());
}

31
pubspec.yaml

@ -53,26 +53,23 @@ flutter:
fonts:
- family: dinokids
- family: DinoKids
fonts:
- asset: assets/fonts/dinokids.ttf
- family: marhey
fonts:
- asset: assets/fonts/Marhey-Light.ttf
weight: 100
- asset: assets/fonts/Marhey-Light.ttf
weight: 200
- asset: assets/fonts/Marhey-Light.ttf
weight: 300
- asset: assets/fonts/Marhey-Regular.ttf
- asset: assets/fonts/DinoKids-Regular.ttf
weight: 400
- asset: assets/fonts/Marhey-Medium.ttf
weight: 500
- family: Marhey
fonts:
- asset: assets/fonts/Marhey-SemiBold.ttf
weight: 600
- asset: assets/fonts/Marhey-Bold.ttf
weight: 700
- asset: assets/fonts/Marhey-Bold.ttf
weight: 800
- asset: assets/fonts/Marhey-Bold.ttf
weight: 900
- family: Baloo_2
fonts:
- asset: assets/fonts/Baloo2-Medium.ttf
weight: 500
- asset: assets/fonts/Baloo2-SemiBold.ttf
weight: 600
- asset: assets/fonts/Baloo2-Bold.ttf
weight: 700
- asset: assets/fonts/Baloo2-ExtraBold.ttf
weight: 800
Loading…
Cancel
Save