result =
57 | flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam,
58 | lparam);
59 | if (result) {
60 | return *result;
61 | }
62 | }
63 |
64 | switch (message) {
65 | case WM_FONTCHANGE:
66 | flutter_controller_->engine()->ReloadSystemFonts();
67 | break;
68 | }
69 |
70 | return Win32Window::MessageHandler(hwnd, message, wparam, lparam);
71 | }
72 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://codemagic.io/app/65f0be96f45e54589b271055/build/6609ce7c2ba7389d8681049b)
2 |
3 |
4 | # Ramazan 2024 🌙
5 |
6 | This application aims to provide users with easy and fast access to daily fasting hours, prayer times, and spiritual content during the month of Ramadan.
7 |
8 | ## Key Features:
9 |
10 | 1. **Fasting Hours and Prayer Times:** Daily fasting hours and prayer times can be instantly viewed. Organize your worship with accurate and up-to-date information.
11 |
12 | 2. **Colorful and User-Friendly Interface:** Our application stands out with its visual richness and user-friendly interface. The colorful design makes information clear and attractive.
13 |
14 | 3. **Hadiths for Special Days:** Strengthen your spirituality by reading hadiths on special days of the Ramadan month. Add meaning to your prayers.
15 |
16 | 4. **Reminders with Notifications:** Keep the application up-to-date with reminders that will notify you at important times, such as iftar times.
17 |
18 | 5. **Privacy and Security:** We value user privacy. We do not share information with third parties.
19 |
20 | ## Screenshots
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | ## Contribute 🤝
31 |
32 | If you want to contribute to this project, please fork and send a pull request. You can also share issues or suggestions in the [Issues](https://github.com/sameetdmr/RamadanApp/issues) section.
33 |
34 | ## Contact 📧
35 |
36 | If you have any questions or suggestions, you can contact us at [dsamed568@gmail.com](mailto:dsamed568@gmail.com).
37 |
38 | ## License
39 |
40 | [](/LICENSE)
41 |
42 | 2024 created for [@Sameetdmr](https://github.com/Sameetdmr)
43 |
--------------------------------------------------------------------------------
/lib/ui/login/components/CustomTextField.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:ramadan/utils/constants/color_constant.dart';
3 | import 'package:ramadan/utils/theme/CustomTextTheme.dart';
4 |
5 | class CustomTextField extends StatelessWidget {
6 | CustomTextField({required this.textEditingController, required this.onChanged, required this.hintText, required this.prefixIcon, required this.validator, super.key, this.obscureText = false, this.suffixIcon});
7 | final TextEditingController textEditingController;
8 | final String hintText;
9 | final Widget? suffixIcon;
10 | final IconData prefixIcon;
11 | final bool obscureText;
12 | String? Function(String?)? validator;
13 | void Function(String)? onChanged;
14 |
15 | @override
16 | Widget build(BuildContext context) {
17 | return DecoratedBox(
18 | decoration: BoxDecoration(
19 | borderRadius: BorderRadius.circular(12),
20 | color: ColorCommonConstant.greyShade100,
21 | ),
22 | child: TextFormField(
23 | controller: textEditingController,
24 | obscureText: obscureText,
25 | validator: validator,
26 | onChanged: onChanged,
27 | textInputAction: TextInputAction.done,
28 | autovalidateMode: AutovalidateMode.onUserInteraction,
29 | decoration: InputDecoration(
30 | iconColor: ColorCommonConstant.red,
31 | hintText: hintText,
32 | hintStyle: CustomTextTheme(context).bodySmall.copyWith(
33 | color: ColorCommonConstant.grey,
34 | ),
35 | prefixIcon: Icon(
36 | prefixIcon,
37 | color: ColorCommonConstant.grey,
38 | ),
39 | suffixIcon: suffixIcon,
40 | border: OutlineInputBorder(
41 | borderRadius: BorderRadius.circular(12),
42 | borderSide: BorderSide(
43 | color: ColorCommonConstant.grey,
44 | ),
45 | ),
46 | enabledBorder: OutlineInputBorder(
47 | borderRadius: BorderRadius.circular(12),
48 | borderSide: BorderSide(
49 | color: ColorCommonConstant.white,
50 | ),
51 | ),
52 | focusedBorder: OutlineInputBorder(
53 | borderRadius: BorderRadius.circular(12),
54 | borderSide: BorderSide(
55 | color: ColorCommonConstant.grey,
56 | ),
57 | ),
58 | ),
59 | ),
60 | );
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/lib/firebase_options.dart:
--------------------------------------------------------------------------------
1 | // File generated by FlutterFire CLI.
2 | // ignore_for_file: lines_longer_than_80_chars, avoid_classes_with_only_static_members
3 | import 'package:firebase_core/firebase_core.dart' show FirebaseOptions;
4 | import 'package:flutter/foundation.dart' show defaultTargetPlatform, kIsWeb, TargetPlatform;
5 |
6 | /// Default [FirebaseOptions] for use with your Firebase apps.
7 | ///
8 | /// Example:
9 | /// ```dart
10 | /// import 'firebase_options.dart';
11 | /// // ...
12 | /// await Firebase.initializeApp(
13 | /// options: DefaultFirebaseOptions.currentPlatform,
14 | /// );
15 | /// ```
16 | class DefaultFirebaseOptions {
17 | static FirebaseOptions get currentPlatform {
18 | if (kIsWeb) {
19 | throw UnsupportedError(
20 | 'DefaultFirebaseOptions have not been configured for web - '
21 | 'you can reconfigure this by running the FlutterFire CLI again.',
22 | );
23 | }
24 | switch (defaultTargetPlatform) {
25 | case TargetPlatform.android:
26 | return android;
27 | case TargetPlatform.iOS:
28 | throw UnsupportedError(
29 | 'DefaultFirebaseOptions have not been configured for ios - '
30 | 'you can reconfigure this by running the FlutterFire CLI again.',
31 | );
32 | case TargetPlatform.macOS:
33 | throw UnsupportedError(
34 | 'DefaultFirebaseOptions have not been configured for macos - '
35 | 'you can reconfigure this by running the FlutterFire CLI again.',
36 | );
37 | case TargetPlatform.windows:
38 | throw UnsupportedError(
39 | 'DefaultFirebaseOptions have not been configured for windows - '
40 | 'you can reconfigure this by running the FlutterFire CLI again.',
41 | );
42 | case TargetPlatform.linux:
43 | throw UnsupportedError(
44 | 'DefaultFirebaseOptions have not been configured for linux - '
45 | 'you can reconfigure this by running the FlutterFire CLI again.',
46 | );
47 | default:
48 | throw UnsupportedError(
49 | 'DefaultFirebaseOptions are not supported for this platform.',
50 | );
51 | }
52 | }
53 |
54 | static const FirebaseOptions android = FirebaseOptions(
55 | apiKey: 'AIzaSyA7GE0saobr15V_d7wqmTTTkbQ-821N0bU',
56 | appId: '1:14384038248:android:442d25a1d96d59968756dd',
57 | messagingSenderId: '14384038248',
58 | projectId: 'ramadanapp-fb663',
59 | storageBucket: 'ramadanapp-fb663.appspot.com',
60 | );
61 | }
62 |
--------------------------------------------------------------------------------
/lib/ui/home/CustomNavigationPage.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_screenutil/flutter_screenutil.dart';
3 | import 'package:get/get.dart';
4 | import 'package:ramadan/ui/home/CustomNavigationPageViewModel.dart';
5 | import 'package:ramadan/ui/home/components/CustomBottomNavigation.dart';
6 | import 'package:ramadan/utils/constants/color_constant.dart';
7 | import 'package:ramadan/utils/navigation/CustomNavigator.dart';
8 |
9 | class CustomNavigationPage extends StatelessWidget {
10 | CustomNavigationPage({super.key});
11 |
12 | late CustomNavigationPageViewModel _customNavigationPageViewModel;
13 | @override
14 | Widget build(BuildContext context) {
15 | _customNavigationPageViewModel = Get.put(CustomNavigationPageViewModel());
16 | return Obx(
17 | () => WillPopScope(
18 | onWillPop: () async {
19 | CustomNavigator().popFromMain();
20 | return false;
21 | },
22 | child: GestureDetector(
23 | child: DefaultTabController(
24 | length: CustomNavigator.navigators.length,
25 | child: Scaffold(
26 | body: TabBarView(
27 | physics: const NeverScrollableScrollPhysics(),
28 | controller: _customNavigationPageViewModel.tabController!.value,
29 | children: CustomNavigator.navigators,
30 | ),
31 | bottomNavigationBar: CustomBottomNavigation(
32 | tabController: _customNavigationPageViewModel.tabController!.value,
33 | onSelectedTab: (value) {
34 | if (value == _customNavigationPageViewModel.currentTab.value) {
35 | CustomNavigator().popUntilCurrentTab();
36 | } else {
37 | _customNavigationPageViewModel.changeTab(value);
38 | }
39 | },
40 | ),
41 | floatingActionButtonLocation: FloatingActionButtonLocation.miniCenterDocked,
42 | floatingActionButton: FloatingActionButton(
43 | elevation: 5,
44 | backgroundColor: ColorCommonConstant.white,
45 | child: Icon(Icons.location_on_outlined, size: 32.sp, color: ColorTextConstant.forestMaid),
46 | onPressed: () async {
47 | await _customNavigationPageViewModel.changeCity();
48 | },
49 | ),
50 | ),
51 | ),
52 | ),
53 | ),
54 | );
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/ios/Runner/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/lib/ui/splash/SplashPageViewModel.dart:
--------------------------------------------------------------------------------
1 | import 'package:get/get.dart';
2 | import 'package:ramadan/services/common/core/PermissionManager.dart';
3 | import 'package:ramadan/ui/ViewModelBase.dart';
4 | import 'package:ramadan/ui/home/CustomNavigationPage.dart';
5 | import 'package:ramadan/ui/slider/SliderPage.dart';
6 | import 'package:ramadan/utils/constants/string_constant.dart';
7 | import 'package:ramadan/utils/exceptions/CustomException.dart';
8 | import 'package:ramadan/utils/initialize/AppPreferences.dart';
9 | import 'package:ramadan/utils/initialize/AppVersionChecker.dart';
10 | import 'package:ramadan/utils/navigation/CustomNavigator.dart';
11 | import 'package:ramadan/utils/servicelocator/ServiceLocator.dart';
12 |
13 | class SplashPageViewModel extends ViewModelBase {
14 | SplashPageViewModel() {
15 | setCurrentScreen('Splash Page');
16 | }
17 | final IAppPreferences _appPreferences = ServiceLocator().get();
18 | final IPermissionManager _iPermissionManager = ServiceLocator().get();
19 | final IAppVersionChecker _appVersionChecker = ServiceLocator().get();
20 |
21 | RxBool isCurrentVersionOk = true.obs;
22 | RxString appVersion = ''.obs;
23 |
24 | @override
25 | Future onInit() async {
26 | super.onInit();
27 | try {
28 | final result = await _appVersionChecker.checkAppVersion();
29 | appVersion.value = await _appVersionChecker.getAppVersion();
30 | if (result) {
31 | isCurrentVersionOk.value = true;
32 | await _checkStartConditions();
33 | } else {
34 | isCurrentVersionOk.value = false;
35 | }
36 | } catch (e) {
37 | await exceptionHandlingService.handleException(e);
38 | }
39 | }
40 |
41 | Future _checkStartConditions() async {
42 | try {
43 | await _appPreferences.init();
44 | final isFirstOpen = await _appPreferences.isFirstOpen();
45 | final hasNotificationPermission = await _iPermissionManager.checkAndRequestNotificationPermission();
46 | await _appPreferences.setNotificationPermission(value: hasNotificationPermission);
47 |
48 | if (isFirstOpen) {
49 | // Uygulama ilk defa mı açıldı.
50 | await _appPreferences.setFirstOpen(value: false);
51 | await CustomNavigator().pushAndRemoveUntil(SliderPage());
52 | } else {
53 | await CustomNavigator().pushAndRemoveUntil(CustomNavigationPage());
54 | }
55 | } catch (e) {
56 | throw CustomException(StringHomeConstant.loginError);
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/lib/services/common/core/PermissionManager.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:geolocator/geolocator.dart';
3 | import 'package:permission_handler/permission_handler.dart';
4 | import 'package:ramadan/utils/constants/string_constant.dart';
5 | import 'package:ramadan/utils/exceptions/CustomException.dart';
6 |
7 | abstract class IPermissionManager {
8 | Future checkLocationPermission();
9 | Future getCurrentLocation();
10 | Future checkAndRequestNotificationPermission();
11 | }
12 |
13 | @immutable
14 | final class PermissionManager extends IPermissionManager {
15 | @override
16 | Future checkLocationPermission() async {
17 | try {
18 | LocationPermission permission;
19 |
20 | permission = await Geolocator.checkPermission();
21 |
22 | if (permission == LocationPermission.denied) {
23 | permission = await Geolocator.requestPermission();
24 |
25 | if (permission == LocationPermission.whileInUse || permission == LocationPermission.always) {
26 | return true;
27 | } else if (permission == LocationPermission.deniedForever) {
28 | await Geolocator.openAppSettings();
29 | return false;
30 | }
31 | } else if (permission == LocationPermission.whileInUse || permission == LocationPermission.always) {
32 | return true;
33 | }
34 |
35 | return false;
36 | } catch (e) {
37 | throw CustomException(StringCommonConstant.checkLocationPermissionError);
38 | }
39 | }
40 |
41 | @override
42 | Future getCurrentLocation() async {
43 | try {
44 | final hasPermission = await checkLocationPermission();
45 |
46 | if (hasPermission) {
47 | return await Geolocator.getCurrentPosition(
48 | desiredAccuracy: LocationAccuracy.high,
49 | );
50 | } else {
51 | return null;
52 | }
53 | } catch (e) {
54 | throw CustomException(StringCommonConstant.getCurrentLocationError);
55 | }
56 | }
57 |
58 | @override
59 | Future checkAndRequestNotificationPermission() async {
60 | final status = await Permission.notification.request();
61 |
62 | if (status == PermissionStatus.granted) {
63 | // Kullanıcı zaten izin verdi.
64 | return true;
65 | } else {
66 | // Kullanıcı izin vermedi, izin talep et.
67 | final requestedStatus = await Permission.notification.request();
68 |
69 | // Kullanıcı izin verdiyse true döner, aksi takdirde false döner.
70 | return requestedStatus == PermissionStatus.granted;
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id "com.android.application"
3 | id "kotlin-android"
4 | id "dev.flutter.flutter-gradle-plugin"
5 | id 'com.google.gms.google-services'
6 | id 'com.google.firebase.crashlytics'
7 | }
8 |
9 | def localProperties = new Properties()
10 | def localPropertiesFile = rootProject.file('local.properties')
11 | if (localPropertiesFile.exists()) {
12 | localPropertiesFile.withReader('UTF-8') { reader ->
13 | localProperties.load(reader)
14 | }
15 | }
16 |
17 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
18 | if (flutterVersionCode == null) {
19 | flutterVersionCode = '1'
20 | }
21 |
22 | def flutterVersionName = localProperties.getProperty('flutter.versionName')
23 | if (flutterVersionName == null) {
24 | flutterVersionName = '1.0'
25 | }
26 |
27 | def keystoreProperties = new Properties()
28 | def keystorePropertiesFile = rootProject.file('key.properties')
29 | if (keystorePropertiesFile.exists()) {
30 | keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
31 | }
32 |
33 | android {
34 | namespace "com.sameetdmr.eramadanapp.ramadan"
35 | compileSdkVersion flutter.compileSdkVersion
36 | ndkVersion flutter.ndkVersion
37 |
38 | compileOptions {
39 | sourceCompatibility JavaVersion.VERSION_1_8
40 | targetCompatibility JavaVersion.VERSION_1_8
41 | }
42 |
43 | defaultConfig {
44 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
45 | applicationId "com.sameetdmr.eramadanapp.ramadan"
46 | // You can update the following values to match your application needs.
47 | // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
48 | minSdkVersion 21
49 | targetSdkVersion flutter.targetSdkVersion
50 | versionCode flutterVersionCode.toInteger()
51 | versionName flutterVersionName
52 | multiDexEnabled true
53 | }
54 |
55 | signingConfigs {
56 | release {
57 | keyAlias keystoreProperties['keyAlias']
58 | keyPassword keystoreProperties['keyPassword']
59 | storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
60 | storePassword keystoreProperties['storePassword']
61 | }
62 | }
63 |
64 | buildTypes {
65 | release {
66 | // TODO: Add your own signing config for the release build.
67 | // Signing with the debug keys for now, so `flutter run --release` works.
68 | signingConfig signingConfigs.release
69 | }
70 | debug {
71 | // TODO: Add your own signing config for the release build.
72 | // Signing with the debug keys for now, so `flutter run --release` works.
73 | signingConfig signingConfigs.debug
74 | }
75 | }
76 | }
77 |
78 | flutter {
79 | source '../..'
80 | }
81 |
--------------------------------------------------------------------------------
/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
30 |
31 |
32 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/lib/rest/ramadan/RamadanDataProvider.dart:
--------------------------------------------------------------------------------
1 | // ignore_for_file: one_member_abstracts
2 |
3 | import 'dart:async';
4 | import 'package:ramadan/model/domain/PrayerTimeDetails.dart';
5 | import 'package:ramadan/model/domain/PrayerTimesModel.dart';
6 | import 'package:ramadan/rest/RestServiceManager.dart';
7 | import 'package:ramadan/services/common/core/ConfigurationService.dart';
8 | import 'package:ramadan/utils/constants/string_constant.dart';
9 | import 'package:ramadan/utils/exceptions/CustomException.dart';
10 | import 'package:ramadan/utils/servicelocator/ServiceLocator.dart';
11 |
12 | abstract class IRamadanDataProvider {
13 | Future loadRamadanData({required String cityName, String? date});
14 | }
15 |
16 | final class RamadanDataProvider implements IRamadanDataProvider {
17 | RamadanDataProvider() {
18 | final configurationService = ServiceLocator().get();
19 | _apiUrl = configurationService.getApiServiceURL();
20 | }
21 | late String _apiUrl;
22 |
23 | @override
24 | Future loadRamadanData({required String cityName, String? date}) async {
25 | try {
26 | final lowercaseUserCityChoiceString = cityName.toLowerCase();
27 | final rawData = await RestServiceManager.call(_apiUrl, lowercaseUserCityChoiceString, null);
28 | if (date != null) {
29 | return _convertDataForDate(rawData, cityName, date);
30 | } else {
31 | return _convertData(rawData, cityName);
32 | }
33 | } catch (e) {
34 | throw CustomException(StringHomeConstant.prayerTimesError);
35 | }
36 | }
37 |
38 | PrayerTimesModel _convertDataForDate(List rawData, String cityName, String date) {
39 | final prayerTimeDetailsList = [];
40 |
41 | for (var i = 0; i < rawData.length / 8; i++) {
42 | final currentRawDate = rawData[8 * i + 1];
43 |
44 | if (currentRawDate.contains(date)) {
45 | final times = rawData.sublist(8 * i + 2, 8 * i + 8);
46 |
47 | // Date formatını düzenle
48 | final dateParts = currentRawDate.split(' ');
49 | final formattedDate = '${dateParts[0]} ${dateParts[1]}, ${dateParts[2]}';
50 |
51 | // times listesini map'e ekle
52 | prayerTimeDetailsList.add(PrayerTimeDetails(date: formattedDate, times: times));
53 | }
54 | }
55 |
56 | return PrayerTimesModel(cityName: cityName, region: cityName, times: prayerTimeDetailsList);
57 | }
58 |
59 | PrayerTimesModel _convertData(List rawData, String cityName) {
60 | final prayerTimeDetailsList = [];
61 |
62 | for (var i = 0; i < rawData.length / 8; i++) {
63 | final date = rawData[8 * i + 1];
64 | final times = rawData.sublist(8 * i + 2, 8 * i + 8);
65 |
66 | // Date formatını düzenle
67 | final dateParts = date.split(' ');
68 | final formattedDate = '${dateParts[0]} ${dateParts[1]}, ${dateParts[2]}';
69 |
70 | // times listesini map'e ekle
71 | prayerTimeDetailsList.add(PrayerTimeDetails(date: formattedDate, times: times));
72 | }
73 |
74 | return PrayerTimesModel(cityName: cityName, region: cityName, times: prayerTimeDetailsList);
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "20x20",
5 | "idiom" : "iphone",
6 | "filename" : "Icon-App-20x20@2x.png",
7 | "scale" : "2x"
8 | },
9 | {
10 | "size" : "20x20",
11 | "idiom" : "iphone",
12 | "filename" : "Icon-App-20x20@3x.png",
13 | "scale" : "3x"
14 | },
15 | {
16 | "size" : "29x29",
17 | "idiom" : "iphone",
18 | "filename" : "Icon-App-29x29@1x.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "size" : "29x29",
23 | "idiom" : "iphone",
24 | "filename" : "Icon-App-29x29@2x.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "29x29",
29 | "idiom" : "iphone",
30 | "filename" : "Icon-App-29x29@3x.png",
31 | "scale" : "3x"
32 | },
33 | {
34 | "size" : "40x40",
35 | "idiom" : "iphone",
36 | "filename" : "Icon-App-40x40@2x.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "40x40",
41 | "idiom" : "iphone",
42 | "filename" : "Icon-App-40x40@3x.png",
43 | "scale" : "3x"
44 | },
45 | {
46 | "size" : "60x60",
47 | "idiom" : "iphone",
48 | "filename" : "Icon-App-60x60@2x.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "60x60",
53 | "idiom" : "iphone",
54 | "filename" : "Icon-App-60x60@3x.png",
55 | "scale" : "3x"
56 | },
57 | {
58 | "size" : "20x20",
59 | "idiom" : "ipad",
60 | "filename" : "Icon-App-20x20@1x.png",
61 | "scale" : "1x"
62 | },
63 | {
64 | "size" : "20x20",
65 | "idiom" : "ipad",
66 | "filename" : "Icon-App-20x20@2x.png",
67 | "scale" : "2x"
68 | },
69 | {
70 | "size" : "29x29",
71 | "idiom" : "ipad",
72 | "filename" : "Icon-App-29x29@1x.png",
73 | "scale" : "1x"
74 | },
75 | {
76 | "size" : "29x29",
77 | "idiom" : "ipad",
78 | "filename" : "Icon-App-29x29@2x.png",
79 | "scale" : "2x"
80 | },
81 | {
82 | "size" : "40x40",
83 | "idiom" : "ipad",
84 | "filename" : "Icon-App-40x40@1x.png",
85 | "scale" : "1x"
86 | },
87 | {
88 | "size" : "40x40",
89 | "idiom" : "ipad",
90 | "filename" : "Icon-App-40x40@2x.png",
91 | "scale" : "2x"
92 | },
93 | {
94 | "size" : "76x76",
95 | "idiom" : "ipad",
96 | "filename" : "Icon-App-76x76@1x.png",
97 | "scale" : "1x"
98 | },
99 | {
100 | "size" : "76x76",
101 | "idiom" : "ipad",
102 | "filename" : "Icon-App-76x76@2x.png",
103 | "scale" : "2x"
104 | },
105 | {
106 | "size" : "83.5x83.5",
107 | "idiom" : "ipad",
108 | "filename" : "Icon-App-83.5x83.5@2x.png",
109 | "scale" : "2x"
110 | },
111 | {
112 | "size" : "1024x1024",
113 | "idiom" : "ios-marketing",
114 | "filename" : "Icon-App-1024x1024@1x.png",
115 | "scale" : "1x"
116 | }
117 | ],
118 | "info" : {
119 | "version" : 1,
120 | "author" : "xcode"
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/lib/services/common/core/AuthService.dart:
--------------------------------------------------------------------------------
1 | import 'package:firebase_auth/firebase_auth.dart';
2 | import 'package:google_sign_in/google_sign_in.dart';
3 | import 'package:ramadan/utils/constants/string_constant.dart';
4 | import 'package:ramadan/utils/exceptions/CustomException.dart';
5 |
6 | abstract class IAuthService {
7 | Future isUserLoggedIn();
8 | Future signInWithEmailAndPassword(String email, String password);
9 | Future signInWithGoogle();
10 | Future signOut();
11 | Future resetPassword(String email);
12 | Future register(String email, String password);
13 | }
14 |
15 | final class AuthService implements IAuthService {
16 | final FirebaseAuth _auth = FirebaseAuth.instance;
17 |
18 | @override
19 | Future isUserLoggedIn() async {
20 | final user = _auth.currentUser;
21 | return user != null;
22 | }
23 |
24 | @override
25 | Future signInWithEmailAndPassword(String email, String password) async {
26 | try {
27 | final userCredential = await _auth.signInWithEmailAndPassword(
28 | email: email,
29 | password: password,
30 | );
31 | if (userCredential.user != null) {
32 | return userCredential.user;
33 | } else {
34 | return null;
35 | }
36 | } catch (e) {
37 | if (e is FirebaseAuthException) {
38 | if (e.code == StringCommonConstant.firebaseLoginErrorCode) {
39 | return null;
40 | } else {
41 | throw CustomException(StringCommonConstant.firebaseLoginError);
42 | }
43 | }
44 | throw CustomException(StringCommonConstant.firebaseLoginError);
45 | }
46 | }
47 |
48 | @override
49 | Future signInWithGoogle() async {
50 | try {
51 | final googleSignInAccount = await GoogleSignIn().signIn();
52 | final googleSignInAuthentication = await googleSignInAccount!.authentication;
53 |
54 | final AuthCredential credential = GoogleAuthProvider.credential(
55 | accessToken: googleSignInAuthentication.accessToken,
56 | idToken: googleSignInAuthentication.idToken,
57 | );
58 |
59 | final userCredential = await _auth.signInWithCredential(credential);
60 | if (userCredential.user != null) {
61 | return userCredential.user;
62 | } else {
63 | return null;
64 | }
65 | } catch (e) {
66 | throw CustomException(StringCommonConstant.googleLoginError);
67 | }
68 | }
69 |
70 | @override
71 | Future signOut() async {
72 | await _auth.signOut();
73 | }
74 |
75 | @override
76 | Future resetPassword(String email) async {
77 | try {
78 | await _auth.sendPasswordResetEmail(email: email);
79 | } catch (e) {
80 | throw CustomException(StringCommonConstant.resetPasswordError);
81 | }
82 | }
83 |
84 | @override
85 | Future register(String email, String password) async {
86 | try {
87 | final userCredential = await _auth.createUserWithEmailAndPassword(email: email, password: password);
88 |
89 | if (userCredential.user != null) {
90 | return userCredential;
91 | } else {
92 | return null;
93 | }
94 | } catch (e) {
95 | throw CustomException(StringCommonConstant.registerError);
96 | }
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/lib/ui/slider/SliderPageViewModel.dart:
--------------------------------------------------------------------------------
1 | // ignore_for_file: use_setters_to_change_properties
2 |
3 | import 'package:flutter/material.dart';
4 | import 'package:get/get.dart';
5 | import 'package:google_fonts/google_fonts.dart';
6 | import 'package:intro_slider/intro_slider.dart';
7 | import 'package:ramadan/ui/ViewModelBase.dart';
8 | import 'package:ramadan/utils/constants/color_constant.dart';
9 | import 'package:ramadan/utils/constants/image_constant.dart';
10 | import 'package:ramadan/utils/constants/string_constant.dart';
11 | import 'package:ramadan/utils/theme/CustomTextTheme.dart';
12 |
13 | class SliderPageViewModel extends ViewModelBase {
14 | SliderPageViewModel(BuildContext context) {
15 | setCurrentScreen('Slider Page');
16 | _context = context;
17 | }
18 | late BuildContext _context;
19 |
20 | // Intro
21 | List slides = [];
22 | RxInt currentIndex = 0.obs;
23 |
24 | RxBool isLocationOk = false.obs;
25 |
26 | @override
27 | void onInit() {
28 | slides.addAll([
29 | ContentConfig(
30 | title: StringSplashSliderConstant.splashSlider1TitleText,
31 | styleTitle: GoogleFonts.nunito(
32 | textStyle: CustomTextTheme(_context).bodyMedium.copyWith(
33 | color: ColorTextConstant.forestMaid,
34 | fontWeight: FontWeight.bold,
35 | ),
36 | ),
37 | description: StringSplashSliderConstant.splashSlider1SubTitleText,
38 | styleDescription: GoogleFonts.nunito(
39 | textStyle: CustomTextTheme(_context).labelMedium.copyWith(color: ColorTextConstant.black),
40 | ),
41 | centerWidget: AppSplashSliderLottiesConstant.appLottie1.toLottie,
42 | backgroundColor: ColorBackgroundConstant.white,
43 | ),
44 | ContentConfig(
45 | title: StringSplashSliderConstant.splashSlider2TitleText,
46 | styleTitle: GoogleFonts.nunito(
47 | textStyle: CustomTextTheme(_context).bodyMedium.copyWith(
48 | color: ColorTextConstant.forestMaid,
49 | fontWeight: FontWeight.bold,
50 | ),
51 | ),
52 | description: StringSplashSliderConstant.splashSlider2SubTitleText,
53 | styleDescription: GoogleFonts.nunito(
54 | textStyle: CustomTextTheme(_context).labelMedium.copyWith(color: ColorTextConstant.black),
55 | ),
56 | centerWidget: AppSplashSliderLottiesConstant.appLottie2.toLottie,
57 | backgroundColor: ColorBackgroundConstant.white,
58 | ),
59 | ContentConfig(
60 | title: StringSplashSliderConstant.splashSlider3TitleText,
61 | maxLineTitle: 3,
62 | styleTitle: GoogleFonts.nunito(
63 | textStyle: CustomTextTheme(_context).bodyMedium.copyWith(
64 | color: ColorTextConstant.forestMaid,
65 | fontWeight: FontWeight.bold,
66 | ),
67 | ),
68 | description: StringSplashSliderConstant.splashSlider3SubTitleText,
69 | styleDescription: GoogleFonts.nunito(
70 | textStyle: CustomTextTheme(_context).labelMedium.copyWith(color: ColorTextConstant.black),
71 | ),
72 | centerWidget: AppSplashSliderLottiesConstant.appLottie3.toLottie,
73 | backgroundColor: ColorBackgroundConstant.white,
74 | ),
75 | ]);
76 |
77 | super.onInit();
78 | }
79 |
80 | void updateCurrentIndex(int index) {
81 | currentIndex.value = index;
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/lib/ui/home/city/CityListPage.dart:
--------------------------------------------------------------------------------
1 | // ignore_for_file: public_member_api_docs, sort_constructors_first
2 | import 'package:flutter/material.dart';
3 | import 'package:kartal/kartal.dart';
4 |
5 | import 'package:ramadan/model/domain/TurkeyCity.dart';
6 | import 'package:ramadan/utils/constants/color_constant.dart';
7 | import 'package:ramadan/utils/constants/string_constant.dart';
8 | import 'package:ramadan/utils/navigation/CustomNavigator.dart';
9 | import 'package:ramadan/utils/theme/CustomTextTheme.dart';
10 |
11 | class CityListPage extends StatelessWidget {
12 | List turkeyCities;
13 | CityListPage({
14 | required this.turkeyCities,
15 | super.key,
16 | });
17 |
18 | @override
19 | Widget build(BuildContext context) {
20 | return SafeArea(
21 | child: Scaffold(
22 | backgroundColor: ColorCommonConstant.white,
23 | appBar: AppBar(
24 | centerTitle: false,
25 | actions: [IconButton(onPressed: () {}, icon: const Icon(Icons.search_outlined))],
26 | leading: IconButton(
27 | icon: Icon(
28 | Icons.arrow_back_outlined,
29 | color: ColorCommonConstant.black,
30 | ),
31 | onPressed: () {
32 | CustomNavigator().popFromMain();
33 | },
34 | ),
35 | elevation: 0,
36 | title: Text(
37 | 'Şehir Seçiniz',
38 | style: CustomTextTheme(context).bodyMedium.copyWith(color: ColorTextConstant.black, fontWeight: FontWeight.bold),
39 | ),
40 | backgroundColor: ColorCommonConstant.transparent,
41 | ),
42 | body: Padding(
43 | padding: context.padding.low,
44 | child: Column(
45 | children: [
46 | GestureDetector(
47 | onTap: () async {
48 | CustomNavigator().popFromMain();
49 | },
50 | child: ListTile(
51 | title: Text(StringHomeConstant.usePreciseLocation, style: CustomTextTheme(context).bodyMedium.copyWith(color: ColorTextConstant.orangeAccent)),
52 | trailing: Icon(
53 | Icons.location_on_outlined,
54 | color: ColorTextConstant.orangeAccent,
55 | ),
56 | ),
57 | ),
58 | Expanded(
59 | child: ListView.separated(
60 | separatorBuilder: (context, index) {
61 | return Divider(
62 | color: ColorCommonConstant.black,
63 | );
64 | },
65 | itemCount: turkeyCities.length,
66 | itemBuilder: (context, index) {
67 | return GestureDetector(
68 | onTap: () {
69 | CustomNavigator().popFromMain(index);
70 | },
71 | child: ListTile(
72 | title: Text(
73 | turkeyCities[index].name,
74 | style: CustomTextTheme(context).labelMedium,
75 | ),
76 | trailing: Icon(
77 | Icons.arrow_forward_outlined,
78 | color: ColorCommonConstant.black,
79 | ),
80 | ),
81 | );
82 | },
83 | ),
84 | ),
85 | ],
86 | ),
87 | ),
88 | ),
89 | );
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/lib/ui/login/passwordReset/PasswordResetPage.dart:
--------------------------------------------------------------------------------
1 | // ignore_for_file: public_member_api_docs, sort_constructors_first
2 | import 'package:flutter/material.dart';
3 | import 'package:flutter_screenutil/flutter_screenutil.dart';
4 | import 'package:kartal/kartal.dart';
5 |
6 | import 'package:ramadan/ui/common/button/CustomLoginButton.dart';
7 | import 'package:ramadan/ui/login/components/CustomLoginButtonType.dart';
8 | import 'package:ramadan/ui/login/components/CustomTextField.dart';
9 | import 'package:ramadan/utils/constants/color_constant.dart';
10 | import 'package:ramadan/utils/constants/string_constant.dart';
11 | import 'package:ramadan/utils/enums/LoginTypeEnum.dart';
12 | import 'package:ramadan/utils/navigation/CustomNavigator.dart';
13 | import 'package:ramadan/utils/theme/CustomTextTheme.dart';
14 | import 'package:ramadan/utils/validator/LoginValidator.dart';
15 |
16 | class PasswordResetScreen extends StatelessWidget {
17 | final TextEditingController textEditingController;
18 | final GlobalKey formKey;
19 | const PasswordResetScreen({
20 | required this.textEditingController,
21 | required this.formKey,
22 | super.key,
23 | });
24 |
25 | @override
26 | Widget build(BuildContext context) {
27 | return SingleChildScrollView(
28 | padding: MediaQuery.of(context).viewInsets,
29 | child: Padding(
30 | padding: context.padding.low,
31 | child: Form(
32 | key: formKey,
33 | autovalidateMode: AutovalidateMode.onUserInteraction,
34 | child: Column(
35 | crossAxisAlignment: CrossAxisAlignment.stretch,
36 | mainAxisSize: MainAxisSize.min,
37 | children: [
38 | Row(
39 | mainAxisAlignment: MainAxisAlignment.end,
40 | children: [
41 | IconButton(
42 | icon: const Icon(Icons.close),
43 | onPressed: () {
44 | CustomNavigator().popFromMain([false]);
45 | textEditingController.clear();
46 | },
47 | ),
48 | ],
49 | ),
50 | SizedBox(height: 10.h),
51 | Text(StringLoginConstant.passwordResetEmailText, style: CustomTextTheme(context).bodyMedium),
52 | SizedBox(height: 20.h),
53 | CustomTextField(
54 | textEditingController: textEditingController,
55 | hintText: StringLoginConstant.passwordResetEmailHintText,
56 | prefixIcon: Icons.mail_outlined,
57 | validator: (value) {
58 | if (value != null) {
59 | return LoginValidator.validateLogin(value, LoginTypeEnum.email);
60 | }
61 | return null;
62 | },
63 | onChanged: null,
64 | ),
65 | SizedBox(height: 20.h),
66 | CustomButton.getButton(
67 | onPressed: () {
68 | if (formKey.currentState!.validate()) {
69 | CustomNavigator().popFromMain([true, textEditingController.text]);
70 | textEditingController.clear();
71 | }
72 | },
73 | customLoginButtonType: CustomLoginButtonType.primary,
74 | textStyle: CustomTextTheme(context).bodyMedium.copyWith(color: ColorTextConstant.white),
75 | text: StringLoginConstant.passwordResetApplyButton,
76 | ),
77 | SizedBox(height: 20.h),
78 | ],
79 | ),
80 | ),
81 | ),
82 | );
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/windows/runner/Runner.rc:
--------------------------------------------------------------------------------
1 | // Microsoft Visual C++ generated resource script.
2 | //
3 | #pragma code_page(65001)
4 | #include "resource.h"
5 |
6 | #define APSTUDIO_READONLY_SYMBOLS
7 | /////////////////////////////////////////////////////////////////////////////
8 | //
9 | // Generated from the TEXTINCLUDE 2 resource.
10 | //
11 | #include "winres.h"
12 |
13 | /////////////////////////////////////////////////////////////////////////////
14 | #undef APSTUDIO_READONLY_SYMBOLS
15 |
16 | /////////////////////////////////////////////////////////////////////////////
17 | // English (United States) resources
18 |
19 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
20 | LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
21 |
22 | #ifdef APSTUDIO_INVOKED
23 | /////////////////////////////////////////////////////////////////////////////
24 | //
25 | // TEXTINCLUDE
26 | //
27 |
28 | 1 TEXTINCLUDE
29 | BEGIN
30 | "resource.h\0"
31 | END
32 |
33 | 2 TEXTINCLUDE
34 | BEGIN
35 | "#include ""winres.h""\r\n"
36 | "\0"
37 | END
38 |
39 | 3 TEXTINCLUDE
40 | BEGIN
41 | "\r\n"
42 | "\0"
43 | END
44 |
45 | #endif // APSTUDIO_INVOKED
46 |
47 |
48 | /////////////////////////////////////////////////////////////////////////////
49 | //
50 | // Icon
51 | //
52 |
53 | // Icon with lowest ID value placed first to ensure application icon
54 | // remains consistent on all systems.
55 | IDI_APP_ICON ICON "resources\\app_icon.ico"
56 |
57 |
58 | /////////////////////////////////////////////////////////////////////////////
59 | //
60 | // Version
61 | //
62 |
63 | #if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD)
64 | #define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD
65 | #else
66 | #define VERSION_AS_NUMBER 1,0,0,0
67 | #endif
68 |
69 | #if defined(FLUTTER_VERSION)
70 | #define VERSION_AS_STRING FLUTTER_VERSION
71 | #else
72 | #define VERSION_AS_STRING "1.0.0"
73 | #endif
74 |
75 | VS_VERSION_INFO VERSIONINFO
76 | FILEVERSION VERSION_AS_NUMBER
77 | PRODUCTVERSION VERSION_AS_NUMBER
78 | FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
79 | #ifdef _DEBUG
80 | FILEFLAGS VS_FF_DEBUG
81 | #else
82 | FILEFLAGS 0x0L
83 | #endif
84 | FILEOS VOS__WINDOWS32
85 | FILETYPE VFT_APP
86 | FILESUBTYPE 0x0L
87 | BEGIN
88 | BLOCK "StringFileInfo"
89 | BEGIN
90 | BLOCK "040904e4"
91 | BEGIN
92 | VALUE "CompanyName", "com.sameetdmr.eramadanapp" "\0"
93 | VALUE "FileDescription", "ramadan" "\0"
94 | VALUE "FileVersion", VERSION_AS_STRING "\0"
95 | VALUE "InternalName", "ramadan" "\0"
96 | VALUE "LegalCopyright", "Copyright (C) 2024 com.sameetdmr.eramadanapp. All rights reserved." "\0"
97 | VALUE "OriginalFilename", "ramadan.exe" "\0"
98 | VALUE "ProductName", "ramadan" "\0"
99 | VALUE "ProductVersion", VERSION_AS_STRING "\0"
100 | END
101 | END
102 | BLOCK "VarFileInfo"
103 | BEGIN
104 | VALUE "Translation", 0x409, 1252
105 | END
106 | END
107 |
108 | #endif // English (United States) resources
109 | /////////////////////////////////////////////////////////////////////////////
110 |
111 |
112 |
113 | #ifndef APSTUDIO_INVOKED
114 | /////////////////////////////////////////////////////////////////////////////
115 | //
116 | // Generated from the TEXTINCLUDE 3 resource.
117 | //
118 |
119 |
120 | /////////////////////////////////////////////////////////////////////////////
121 | #endif // not APSTUDIO_INVOKED
122 |
--------------------------------------------------------------------------------
/lib/ui/home/hadith/HadithPage.dart:
--------------------------------------------------------------------------------
1 | // ignore_for_file: must_be_immutable
2 |
3 | import 'package:flutter/material.dart';
4 | import 'package:flutter_screenutil/flutter_screenutil.dart';
5 | import 'package:get/get.dart';
6 | import 'package:kartal/kartal.dart';
7 | import 'package:ramadan/ui/home/hadith/HadithPageViewModel.dart';
8 | import 'package:ramadan/ui/home/hadith/components/HadithCard.dart';
9 | import 'package:ramadan/ui/home/hadith/components/HadithCategoryFilterButton.dart';
10 | import 'package:ramadan/utils/constants/color_constant.dart';
11 | import 'package:ramadan/utils/constants/string_constant.dart';
12 | import 'package:ramadan/utils/theme/CustomTextTheme.dart';
13 |
14 | class HadithPage extends StatelessWidget {
15 | HadithPage({super.key});
16 | late HadithPageViewModel _hadithPageViewModel;
17 |
18 | @override
19 | Widget build(BuildContext context) {
20 | _hadithPageViewModel = Get.put(HadithPageViewModel());
21 | return SafeArea(
22 | child: Obx(
23 | () => Scaffold(
24 | backgroundColor: ColorBackgroundConstant.white,
25 | appBar: AppBar(
26 | elevation: 0,
27 | backgroundColor: ColorCommonConstant.transparent,
28 | automaticallyImplyLeading: false,
29 | title: _Header(
30 | title: StringHadithConstant.hadithAppBarTitle,
31 | hadithCategory: _hadithPageViewModel.uniqueCategoryList,
32 | categoryName: _hadithPageViewModel.categoryName.value,
33 | onSelected: (String value) async {
34 | await _hadithPageViewModel.getHadithsByCategory(value);
35 | },
36 | ),
37 | ),
38 | body: Obx(
39 | () => _hadithPageViewModel.isLoading.value
40 | ? Padding(
41 | padding: context.padding.low,
42 | child: ListView.builder(
43 | itemCount: _hadithPageViewModel.hadithList.length,
44 | itemBuilder: (BuildContext context, int index) {
45 | return HadithCard(
46 | text: _hadithPageViewModel.hadithList[index].hadith,
47 | author: _hadithPageViewModel.hadithList[index].author,
48 | );
49 | },
50 | ),
51 | )
52 | : const Center(
53 | child: CircularProgressIndicator(),
54 | ),
55 | ),
56 | ),
57 | ),
58 | );
59 | }
60 | }
61 |
62 | class _Header extends StatelessWidget {
63 | const _Header({
64 | required this.title,
65 | required this.hadithCategory,
66 | required this.categoryName,
67 | required this.onSelected,
68 | });
69 | final String title;
70 | final List hadithCategory;
71 | final String categoryName;
72 | final void Function(String)? onSelected;
73 | @override
74 | Widget build(BuildContext context) {
75 | return Row(
76 | children: [
77 | Column(
78 | crossAxisAlignment: CrossAxisAlignment.start,
79 | children: [
80 | Text(
81 | title,
82 | style: CustomTextTheme(context).bodyMedium.copyWith(color: ColorTextConstant.black),
83 | ),
84 | SizedBox(
85 | height: 5.h,
86 | ),
87 | Text(
88 | categoryName,
89 | style: CustomTextTheme(context).bodySmall.copyWith(color: ColorTextConstant.orangeAccent),
90 | ),
91 | ],
92 | ),
93 | const Spacer(),
94 | HadithCategoryFilterButton(
95 | hadithCategory: hadithCategory,
96 | onSelected: onSelected,
97 | ),
98 | ],
99 | );
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/windows/runner/win32_window.h:
--------------------------------------------------------------------------------
1 | #ifndef RUNNER_WIN32_WINDOW_H_
2 | #define RUNNER_WIN32_WINDOW_H_
3 |
4 | #include
5 |
6 | #include
7 | #include
8 | #include
9 |
10 | // A class abstraction for a high DPI-aware Win32 Window. Intended to be
11 | // inherited from by classes that wish to specialize with custom
12 | // rendering and input handling
13 | class Win32Window {
14 | public:
15 | struct Point {
16 | unsigned int x;
17 | unsigned int y;
18 | Point(unsigned int x, unsigned int y) : x(x), y(y) {}
19 | };
20 |
21 | struct Size {
22 | unsigned int width;
23 | unsigned int height;
24 | Size(unsigned int width, unsigned int height)
25 | : width(width), height(height) {}
26 | };
27 |
28 | Win32Window();
29 | virtual ~Win32Window();
30 |
31 | // Creates a win32 window with |title| that is positioned and sized using
32 | // |origin| and |size|. New windows are created on the default monitor. Window
33 | // sizes are specified to the OS in physical pixels, hence to ensure a
34 | // consistent size this function will scale the inputted width and height as
35 | // as appropriate for the default monitor. The window is invisible until
36 | // |Show| is called. Returns true if the window was created successfully.
37 | bool Create(const std::wstring& title, const Point& origin, const Size& size);
38 |
39 | // Show the current window. Returns true if the window was successfully shown.
40 | bool Show();
41 |
42 | // Release OS resources associated with window.
43 | void Destroy();
44 |
45 | // Inserts |content| into the window tree.
46 | void SetChildContent(HWND content);
47 |
48 | // Returns the backing Window handle to enable clients to set icon and other
49 | // window properties. Returns nullptr if the window has been destroyed.
50 | HWND GetHandle();
51 |
52 | // If true, closing this window will quit the application.
53 | void SetQuitOnClose(bool quit_on_close);
54 |
55 | // Return a RECT representing the bounds of the current client area.
56 | RECT GetClientArea();
57 |
58 | protected:
59 | // Processes and route salient window messages for mouse handling,
60 | // size change and DPI. Delegates handling of these to member overloads that
61 | // inheriting classes can handle.
62 | virtual LRESULT MessageHandler(HWND window,
63 | UINT const message,
64 | WPARAM const wparam,
65 | LPARAM const lparam) noexcept;
66 |
67 | // Called when CreateAndShow is called, allowing subclass window-related
68 | // setup. Subclasses should return false if setup fails.
69 | virtual bool OnCreate();
70 |
71 | // Called when Destroy is called.
72 | virtual void OnDestroy();
73 |
74 | private:
75 | friend class WindowClassRegistrar;
76 |
77 | // OS callback called by message pump. Handles the WM_NCCREATE message which
78 | // is passed when the non-client area is being created and enables automatic
79 | // non-client DPI scaling so that the non-client area automatically
80 | // responds to changes in DPI. All other messages are handled by
81 | // MessageHandler.
82 | static LRESULT CALLBACK WndProc(HWND const window,
83 | UINT const message,
84 | WPARAM const wparam,
85 | LPARAM const lparam) noexcept;
86 |
87 | // Retrieves a class instance pointer for |window|
88 | static Win32Window* GetThisFromHandle(HWND const window) noexcept;
89 |
90 | // Update the window frame's theme to match the system theme.
91 | static void UpdateTheme(HWND const window);
92 |
93 | bool quit_on_close_ = false;
94 |
95 | // window handle for top level window.
96 | HWND window_handle_ = nullptr;
97 |
98 | // window handle for hosted content.
99 | HWND child_content_ = nullptr;
100 | };
101 |
102 | #endif // RUNNER_WIN32_WINDOW_H_
103 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
37 |
38 |
39 |
40 |
43 |
49 |
50 |
51 |
52 |
53 |
63 |
65 |
71 |
72 |
73 |
74 |
80 |
82 |
88 |
89 |
90 |
91 |
93 |
94 |
97 |
98 |
99 |
--------------------------------------------------------------------------------
/windows/flutter/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # This file controls Flutter-level build steps. It should not be edited.
2 | cmake_minimum_required(VERSION 3.14)
3 |
4 | set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral")
5 |
6 | # Configuration provided via flutter tool.
7 | include(${EPHEMERAL_DIR}/generated_config.cmake)
8 |
9 | # TODO: Move the rest of this into files in ephemeral. See
10 | # https://github.com/flutter/flutter/issues/57146.
11 | set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper")
12 |
13 | # === Flutter Library ===
14 | set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll")
15 |
16 | # Published to parent scope for install step.
17 | set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE)
18 | set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE)
19 | set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE)
20 | set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE)
21 |
22 | list(APPEND FLUTTER_LIBRARY_HEADERS
23 | "flutter_export.h"
24 | "flutter_windows.h"
25 | "flutter_messenger.h"
26 | "flutter_plugin_registrar.h"
27 | "flutter_texture_registrar.h"
28 | )
29 | list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/")
30 | add_library(flutter INTERFACE)
31 | target_include_directories(flutter INTERFACE
32 | "${EPHEMERAL_DIR}"
33 | )
34 | target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib")
35 | add_dependencies(flutter flutter_assemble)
36 |
37 | # === Wrapper ===
38 | list(APPEND CPP_WRAPPER_SOURCES_CORE
39 | "core_implementations.cc"
40 | "standard_codec.cc"
41 | )
42 | list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/")
43 | list(APPEND CPP_WRAPPER_SOURCES_PLUGIN
44 | "plugin_registrar.cc"
45 | )
46 | list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/")
47 | list(APPEND CPP_WRAPPER_SOURCES_APP
48 | "flutter_engine.cc"
49 | "flutter_view_controller.cc"
50 | )
51 | list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/")
52 |
53 | # Wrapper sources needed for a plugin.
54 | add_library(flutter_wrapper_plugin STATIC
55 | ${CPP_WRAPPER_SOURCES_CORE}
56 | ${CPP_WRAPPER_SOURCES_PLUGIN}
57 | )
58 | apply_standard_settings(flutter_wrapper_plugin)
59 | set_target_properties(flutter_wrapper_plugin PROPERTIES
60 | POSITION_INDEPENDENT_CODE ON)
61 | set_target_properties(flutter_wrapper_plugin PROPERTIES
62 | CXX_VISIBILITY_PRESET hidden)
63 | target_link_libraries(flutter_wrapper_plugin PUBLIC flutter)
64 | target_include_directories(flutter_wrapper_plugin PUBLIC
65 | "${WRAPPER_ROOT}/include"
66 | )
67 | add_dependencies(flutter_wrapper_plugin flutter_assemble)
68 |
69 | # Wrapper sources needed for the runner.
70 | add_library(flutter_wrapper_app STATIC
71 | ${CPP_WRAPPER_SOURCES_CORE}
72 | ${CPP_WRAPPER_SOURCES_APP}
73 | )
74 | apply_standard_settings(flutter_wrapper_app)
75 | target_link_libraries(flutter_wrapper_app PUBLIC flutter)
76 | target_include_directories(flutter_wrapper_app PUBLIC
77 | "${WRAPPER_ROOT}/include"
78 | )
79 | add_dependencies(flutter_wrapper_app flutter_assemble)
80 |
81 | # === Flutter tool backend ===
82 | # _phony_ is a non-existent file to force this command to run every time,
83 | # since currently there's no way to get a full input/output list from the
84 | # flutter tool.
85 | set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_")
86 | set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE)
87 | add_custom_command(
88 | OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}
89 | ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN}
90 | ${CPP_WRAPPER_SOURCES_APP}
91 | ${PHONY_OUTPUT}
92 | COMMAND ${CMAKE_COMMAND} -E env
93 | ${FLUTTER_TOOL_ENVIRONMENT}
94 | "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat"
95 | windows-x64 $
96 | VERBATIM
97 | )
98 | add_custom_target(flutter_assemble DEPENDS
99 | "${FLUTTER_LIBRARY}"
100 | ${FLUTTER_LIBRARY_HEADERS}
101 | ${CPP_WRAPPER_SOURCES_CORE}
102 | ${CPP_WRAPPER_SOURCES_PLUGIN}
103 | ${CPP_WRAPPER_SOURCES_APP}
104 | )
105 |
--------------------------------------------------------------------------------
/windows/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # Project-level configuration.
2 | cmake_minimum_required(VERSION 3.14)
3 | project(ramadan LANGUAGES CXX)
4 |
5 | # The name of the executable created for the application. Change this to change
6 | # the on-disk name of your application.
7 | set(BINARY_NAME "Ramazan 2024")
8 |
9 | # Explicitly opt in to modern CMake behaviors to avoid warnings with recent
10 | # versions of CMake.
11 | cmake_policy(VERSION 3.14...3.25)
12 |
13 | # Define build configuration option.
14 | get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
15 | if(IS_MULTICONFIG)
16 | set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release"
17 | CACHE STRING "" FORCE)
18 | else()
19 | if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
20 | set(CMAKE_BUILD_TYPE "Debug" CACHE
21 | STRING "Flutter build mode" FORCE)
22 | set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
23 | "Debug" "Profile" "Release")
24 | endif()
25 | endif()
26 | # Define settings for the Profile build mode.
27 | set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}")
28 | set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}")
29 | set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}")
30 | set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}")
31 |
32 | # Use Unicode for all projects.
33 | add_definitions(-DUNICODE -D_UNICODE)
34 |
35 | # Compilation settings that should be applied to most targets.
36 | #
37 | # Be cautious about adding new options here, as plugins use this function by
38 | # default. In most cases, you should add new options to specific targets instead
39 | # of modifying this function.
40 | function(APPLY_STANDARD_SETTINGS TARGET)
41 | target_compile_features(${TARGET} PUBLIC cxx_std_17)
42 | target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100")
43 | target_compile_options(${TARGET} PRIVATE /EHsc)
44 | target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0")
45 | target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>")
46 | endfunction()
47 |
48 | # Flutter library and tool build rules.
49 | set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
50 | add_subdirectory(${FLUTTER_MANAGED_DIR})
51 |
52 | # Application build; see runner/CMakeLists.txt.
53 | add_subdirectory("runner")
54 |
55 |
56 | # Generated plugin build rules, which manage building the plugins and adding
57 | # them to the application.
58 | include(flutter/generated_plugins.cmake)
59 |
60 |
61 | # === Installation ===
62 | # Support files are copied into place next to the executable, so that it can
63 | # run in place. This is done instead of making a separate bundle (as on Linux)
64 | # so that building and running from within Visual Studio will work.
65 | set(BUILD_BUNDLE_DIR "$")
66 | # Make the "install" step default, as it's required to run.
67 | set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1)
68 | if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
69 | set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
70 | endif()
71 |
72 | set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
73 | set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}")
74 |
75 | install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
76 | COMPONENT Runtime)
77 |
78 | install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
79 | COMPONENT Runtime)
80 |
81 | install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
82 | COMPONENT Runtime)
83 |
84 | if(PLUGIN_BUNDLED_LIBRARIES)
85 | install(FILES "${PLUGIN_BUNDLED_LIBRARIES}"
86 | DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
87 | COMPONENT Runtime)
88 | endif()
89 |
90 | # Fully re-copy the assets directory on each build to avoid having stale files
91 | # from a previous install.
92 | set(FLUTTER_ASSET_DIR_NAME "flutter_assets")
93 | install(CODE "
94 | file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\")
95 | " COMPONENT Runtime)
96 | install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}"
97 | DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
98 |
99 | # Install the AOT library on non-Debug builds only.
100 | install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
101 | CONFIGURATIONS Profile;Release
102 | COMPONENT Runtime)
103 |
--------------------------------------------------------------------------------
/lib/services/common/notification/LocalNotificationService.dart:
--------------------------------------------------------------------------------
1 | // ignore_for_file: depend_on_referenced_packages, directives_ordering
2 |
3 | import 'dart:async';
4 | import 'dart:math';
5 |
6 | import 'package:flutter/material.dart';
7 | import 'package:flutter_local_notifications/flutter_local_notifications.dart';
8 | import 'package:ramadan/utils/constants/string_constant.dart';
9 | import 'package:ramadan/utils/exceptions/CustomException.dart';
10 | import 'package:timezone/timezone.dart' as tz;
11 | import 'package:timezone/data/latest.dart' as tz;
12 |
13 | FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
14 | Random random = Random();
15 |
16 | abstract class ILocalNotificationService {
17 | Future notificationDetails();
18 | Future initializePlatformNotifications();
19 | Future showFirebaseNotification(String title, String body);
20 | Future schedulePrayerTimeNotification(String city, DateTime notificationDate);
21 | }
22 |
23 | final class LocalNotificationService implements ILocalNotificationService {
24 | @override
25 | Future notificationDetails() async {
26 | const androidNotificationChannel = AndroidNotificationChannel(
27 | 'ramadanAppChannelId-1',
28 | 'E-Imsakiye Ramadan',
29 | description: 'Ramadan App Push Notifications With Sound',
30 | sound: RawResourceAndroidNotificationSound('cannon'),
31 | importance: Importance.max,
32 | );
33 |
34 | await flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation()?.createNotificationChannel(androidNotificationChannel);
35 |
36 | final platformChannelSpecificsWithoutCabinSound = NotificationDetails(
37 | android: AndroidNotificationDetails(
38 | androidNotificationChannel.id,
39 | androidNotificationChannel.name,
40 | importance: androidNotificationChannel.importance,
41 | priority: Priority.high,
42 | enableLights: true,
43 | sound: androidNotificationChannel.sound,
44 | icon: '@drawable/cannon',
45 | showWhen: false,
46 | color: const Color.fromRGBO(0, 0, 0, 0),
47 | channelDescription: androidNotificationChannel.description,
48 | ),
49 | iOS: const DarwinNotificationDetails(),
50 | );
51 |
52 | return platformChannelSpecificsWithoutCabinSound;
53 | }
54 |
55 | @override
56 | Future initializePlatformNotifications() async {
57 | const initializationSettingsAndroid = AndroidInitializationSettings('@drawable/cannon');
58 |
59 | const initializationSettings = InitializationSettings(android: initializationSettingsAndroid);
60 |
61 | await flutterLocalNotificationsPlugin.initialize(
62 | initializationSettings,
63 | onDidReceiveNotificationResponse: (details) {},
64 | onDidReceiveBackgroundNotificationResponse: (details) {},
65 | );
66 | }
67 |
68 | @override
69 | Future showFirebaseNotification(String title, String body) async {
70 | await flutterLocalNotificationsPlugin.show(random.nextInt(1 << 31), title, body, await notificationDetails());
71 | }
72 |
73 | @override
74 | Future schedulePrayerTimeNotification(String city, DateTime notificationDate) async {
75 | try {
76 | await flutterLocalNotificationsPlugin.cancelAll();
77 | final id = DateTime.now().millisecondsSinceEpoch.remainder(100000);
78 | final timeZone = await _setup();
79 | final originalTZDateTime = tz.TZDateTime.from(notificationDate, timeZone);
80 |
81 | await flutterLocalNotificationsPlugin.zonedSchedule(
82 | id,
83 | '$city için İftar Vakti!',
84 | StringCommonConstant.notificationBody,
85 | originalTZDateTime,
86 | await notificationDetails(),
87 | androidScheduleMode: AndroidScheduleMode.inexactAllowWhileIdle,
88 | uiLocalNotificationDateInterpretation: UILocalNotificationDateInterpretation.absoluteTime,
89 | matchDateTimeComponents: DateTimeComponents.dateAndTime,
90 | );
91 | } catch (e) {
92 | throw CustomException(StringCommonConstant.anErrorOccured);
93 | }
94 | }
95 |
96 | Future _setup() async {
97 | tz.initializeTimeZones();
98 | tz.getLocation('Europe/Istanbul');
99 | return tz.local;
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/lib/ui/login/LoginPageViewModel.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:get/get.dart';
3 | import 'package:ramadan/services/common/core/AuthService.dart';
4 | import 'package:ramadan/ui/ViewModelBase.dart';
5 | import 'package:ramadan/ui/home/CustomNavigationPage.dart';
6 | import 'package:ramadan/utils/constants/string_constant.dart';
7 | import 'package:ramadan/utils/enums/LoginTypeEnum.dart';
8 | import 'package:ramadan/utils/navigation/CustomNavigator.dart';
9 | import 'package:ramadan/utils/popups/CustomDialog.dart';
10 | import 'package:ramadan/utils/popups/CustomSnackBar.dart';
11 | import 'package:ramadan/utils/popups/CustomSnackBarType.dart';
12 | import 'package:ramadan/utils/servicelocator/ServiceLocator.dart';
13 | import 'package:ramadan/utils/validator/LoginValidator.dart';
14 |
15 | class LoginPageViewModel extends ViewModelBase {
16 | LoginPageViewModel(BuildContext context) {
17 | setCurrentScreen('Login Page');
18 | _context = context;
19 | }
20 | late final BuildContext _context;
21 |
22 | // Secure
23 | RxInt failedSignInCount = 0.obs;
24 |
25 | // TextEditingController
26 | final TextEditingController emailTextController = TextEditingController();
27 | final TextEditingController passwordTextController = TextEditingController();
28 | final TextEditingController forgotPasswordTextController = TextEditingController();
29 |
30 | // Form
31 | final GlobalKey formKey = GlobalKey();
32 | final GlobalKey forgotPasswordFormKey = GlobalKey();
33 |
34 | // Password Icon Config
35 | RxBool obscureText = false.obs;
36 |
37 | final IAuthService _authService = ServiceLocator().get();
38 |
39 | @override
40 | void dispose() {
41 | emailTextController.dispose();
42 | passwordTextController.dispose();
43 | super.dispose();
44 | }
45 |
46 | void clearTextController() {
47 | emailTextController.clear();
48 | passwordTextController.clear();
49 | }
50 |
51 | void loginTextFormFieldOnChanged(String? value, TextEditingController controller, LoginTypeEnum loginTypeEnum) {
52 | if (value!.isEmpty) {
53 | return;
54 | } else {
55 | final result = LoginValidator.validateLogin(value, loginTypeEnum);
56 | if (result == null) {
57 | controller.text = value;
58 | }
59 | }
60 | }
61 |
62 | Future signInWithEmailAndPassword(String email, String password) async {
63 | try {
64 | CustomDialog.showLoadingDialog();
65 | final user = await _authService.signInWithEmailAndPassword(email, password);
66 | if (user != null) {
67 | CustomDialog.dismiss();
68 | failedSignInCount.value = 0;
69 | await CustomNavigator().pushAndRemoveUntil(CustomNavigationPage());
70 | } else {
71 | CustomDialog.dismiss();
72 | failedSignInCount.value++;
73 | if (_context.mounted) await CustomSnackBar.showSnackBar(_context, CustomSnackBarType.error, StringLoginConstant.snackbarErrorEmailPasswordControlText);
74 | }
75 | } catch (e) {
76 | await exceptionHandlingService.handleException(e);
77 | }
78 | }
79 |
80 | RxBool get signInButtonVisible => failedSignInCount.value >= 3 ? false.obs : true.obs;
81 |
82 | Future signInGoogle() async {
83 | try {
84 | final user = await _authService.signInWithGoogle();
85 | clearTextController();
86 | if (user != null) {
87 | await CustomNavigator().pushAndRemoveUntil(CustomNavigationPage());
88 | } else {
89 | if (_context.mounted) await CustomSnackBar.showSnackBar(_context, CustomSnackBarType.error, StringLoginConstant.snackbarErrorRetryText);
90 | }
91 | } catch (e) {
92 | await exceptionHandlingService.handleException(e);
93 | }
94 | }
95 |
96 | void withoutSignIn(BuildContext context) {
97 | try {
98 | CustomNavigator().pushAndRemoveUntil(CustomNavigationPage());
99 | } catch (e) {
100 | exceptionHandlingService.handleException(e);
101 | }
102 | }
103 |
104 | Future resetPassword(String email) async {
105 | try {
106 | await _authService.resetPassword(email);
107 | if (_context.mounted) await CustomSnackBar.showSnackBar(_context, CustomSnackBarType.success, StringLoginConstant.snackbarErrorEmailControlText);
108 | } catch (e) {
109 | await exceptionHandlingService.handleException(e);
110 | if (_context.mounted) await CustomSnackBar.showSnackBar(_context, CustomSnackBarType.error, StringLoginConstant.snackbarErrorRetryText);
111 | }
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/lib/model/home/PrayerTimeWord.dart:
--------------------------------------------------------------------------------
1 | // ignore_for_file: public_member_api_docs, sort_constructors_first
2 | class PrayerTimeWord {
3 | final int id;
4 | final String trWord;
5 | final String enWord;
6 | PrayerTimeWord({
7 | required this.id,
8 | required this.trWord,
9 | required this.enWord,
10 | });
11 |
12 | static List ramadanWordList = [
13 | PrayerTimeWord(id: 1, trWord: 'Ramazan ayı bereket ve huzur getirsin.', enWord: 'May the month of Ramadan bring blessings and peace.'),
14 | PrayerTimeWord(id: 2, trWord: 'Dualarınız kabul olsun.', enWord: 'May your prayers be accepted.'),
15 | PrayerTimeWord(id: 3, trWord: 'Oruç, sabır ve dayanıklılığın simgesidir.', enWord: 'Fasting is a symbol of patience and resilience.'),
16 | PrayerTimeWord(id: 4, trWord: 'Ramazan, kalp ve ruhumuzu temizler.', enWord: 'Ramadan cleanses our hearts and souls.'),
17 | PrayerTimeWord(id: 5, trWord: 'İftar sofraları sevdiklerimizle birleştirir.', enWord: 'Iftar tables bring us together with our loved ones.'),
18 | PrayerTimeWord(id: 6, trWord: 'Ramazan, manevi bir yolculuktur.', enWord: 'Ramadan is a spiritual journey.'),
19 | PrayerTimeWord(id: 7, trWord: 'Oruç, kendimizi kontrol etme sanatıdır.', enWord: 'Fasting is the art of self-control.'),
20 | PrayerTimeWord(id: 8, trWord: 'Güzel dualarla dolu bir Ramazan geçirmeniz dileğiyle.', enWord: 'Wishing you a Ramadan filled with beautiful prayers.'),
21 | PrayerTimeWord(id: 9, trWord: 'Rahmet ve mağfiret ayı olan Ramazan hoş geldin.', enWord: 'Welcome, Ramadan, the month of mercy and forgiveness.'),
22 | PrayerTimeWord(id: 10, trWord: 'Ramazan, güzellikleriyle dolu bir mücevher gibidir.', enWord: 'Ramadan is like a jewel filled with beauties.'),
23 | PrayerTimeWord(id: 11, trWord: 'İftar sofralarınız şen olsun.', enWord: 'May your iftar tables be joyful.'),
24 | PrayerTimeWord(id: 12, trWord: "Allah'ın rahmeti üzerinize olsun.", enWord: 'May the mercy of Allah be upon you.'),
25 | PrayerTimeWord(id: 13, trWord: 'Ruhunuzu ve bedeninizi arındıran bir Ramazan geçirmeniz dileğiyle.', enWord: 'Wishing you a Ramadan that purifies your soul and body.'),
26 | PrayerTimeWord(id: 14, trWord: 'İyi niyetlerle dolu bir ay geçirmeniz dileğiyle.', enWord: 'Wishing you a month filled with good intentions.'),
27 | PrayerTimeWord(id: 15, trWord: 'Dualarınızın kabul olduğu bir Ramazan geçirmeniz dileğiyle.', enWord: 'Wishing you a Ramadan where your prayers are answered.'),
28 | PrayerTimeWord(id: 16, trWord: "Ramazan'ın huzurunu ve mutluluğunu yaşayın.", enWord: 'Experience the peace and joy of Ramadan.'),
29 | PrayerTimeWord(id: 17, trWord: 'Oruç, şükür ve minnettarlık duygularını güçlendirir.', enWord: 'Fasting strengthens feelings of gratitude and thankfulness.'),
30 | PrayerTimeWord(id: 18, trWord: 'Rahmet dolu bir Ramazan ayı geçirmeniz dileğiyle.', enWord: 'Wishing you a Ramadan filled with mercy.'),
31 | PrayerTimeWord(id: 19, trWord: 'Dualarınızın gerçekleştiği bir ay olsun.', enWord: 'May it be a month where your prayers come true.'),
32 | PrayerTimeWord(id: 20, trWord: 'Sevdiklerinizle bir araya geldiğiniz neşeli iftarlar geçirmeniz dileğiyle.', enWord: 'Wishing you joyful iftars with your loved ones.'),
33 | PrayerTimeWord(id: 21, trWord: 'Oruç, manevi bir detoks gibidir.', enWord: 'Fasting is like a spiritual detox.'),
34 | PrayerTimeWord(id: 22, trWord: 'Kalbinizdeki güzellikleri paylaşmanız dileğiyle.', enWord: 'Wishing you share the beauty in your heart.'),
35 | PrayerTimeWord(id: 23, trWord: 'Ruhunuza huzur veren bir Ramazan geçirmeniz dileğiyle.', enWord: 'Wishing you a Ramadan that brings peace to your soul.'),
36 | PrayerTimeWord(id: 24, trWord: 'İyilik ve sevgi dolu bir ay geçirmeniz dileğiyle.', enWord: 'Wishing you a month filled with goodness and love.'),
37 | PrayerTimeWord(id: 25, trWord: 'Dualarınızın ve ibadetlerinizin kabul olduğu bir Ramazan olsun.', enWord: 'May it be a Ramadan where your prayers and worship are accepted.'),
38 | PrayerTimeWord(id: 26, trWord: 'Oruç, kendimizi daha iyi tanımamıza yardımcı olur.', enWord: 'Fasting helps us better understand ourselves.'),
39 | PrayerTimeWord(id: 27, trWord: "Allah'ın rahmeti ve mağfireti üzerinize olsun.", enWord: 'May the mercy and forgiveness of Allah be upon you.'),
40 | PrayerTimeWord(id: 28, trWord: 'Ruhunuzun derinliklerine yolculuk yapın.', enWord: 'Take a journey into the depths of your soul.'),
41 | PrayerTimeWord(id: 29, trWord: 'Dualarınızın gerçekleştiği bir ay dilerim.', enWord: 'I wish you a month where your prayers come true.'),
42 | PrayerTimeWord(id: 30, trWord: 'Ramazan bayramınız kutlu olsun!', enWord: 'Wishing you a blessed Ramadan holiday!'),
43 | ];
44 | }
45 |
--------------------------------------------------------------------------------
/lib/utils/manager/GridItemManager.dart:
--------------------------------------------------------------------------------
1 | // ignore_for_file: lines_longer_than_80_chars, public_member_api_docs
2 |
3 | import 'package:flutter/material.dart';
4 | import 'package:get/get.dart';
5 | import 'package:ramadan/model/domain/GridItemResult.dart';
6 | import 'package:ramadan/model/domain/PrayerTimeDetails.dart';
7 | import 'package:ramadan/model/home/GridItem.dart';
8 | import 'package:ramadan/utils/constants/color_constant.dart';
9 | import 'package:ramadan/utils/constants/image_constant.dart';
10 | import 'package:ramadan/utils/constants/string_constant.dart';
11 | import 'package:ramadan/utils/manager/TimeManager.dart';
12 |
13 | final class GridItemManager {
14 | int? id;
15 | String? prayerIcon;
16 | Color? prayerColor;
17 | String? prayerTimeTitle;
18 | RxBool? isActive;
19 | String? prayerDate;
20 | String? prayerTimeText;
21 | GridItemResult fillGridItem(List prayerTimes, RxList gridItemList, RxList isActiveList) {
22 | for (var i = 0; i < prayerTimes.length; i++) {
23 | for (var j = 0; j < prayerTimes[i].times.length; j++) {
24 | final prayerTime = prayerTimes[i];
25 |
26 | isActiveList.value = TimeManager.calculatePrayerTimes(prayerTimes[i].times);
27 |
28 | switch (j) {
29 | case 0: // İmsak
30 | id = j;
31 | prayerIcon = PrayerTimeIconConstant.imsak.toPng;
32 | prayerColor = PrayerTimeColor.imsak;
33 | prayerTimeTitle = StringHomeConstant.fajr;
34 | isActive = isActiveList[j];
35 | prayerDate = prayerTime.date.isNotEmpty ? prayerTimes[i].date : StringCommonConstant.noDateInformation;
36 | prayerTimeText = prayerTime.times.isNotEmpty ? prayerTimes[i].times[j] : StringCommonConstant.noTimeInformation;
37 | case 1: // Güneş
38 | id = j;
39 | prayerIcon = PrayerTimeIconConstant.gunes.toPng;
40 | prayerColor = PrayerTimeColor.gunes;
41 | prayerTimeTitle = StringHomeConstant.sunrise;
42 | isActive = isActiveList[j];
43 | prayerDate = prayerTime.date.isNotEmpty ? prayerTimes[i].date : StringCommonConstant.noDateInformation;
44 |
45 | prayerTimeText = prayerTime.times.isNotEmpty ? prayerTimes[i].times[j] : StringCommonConstant.noTimeInformation;
46 | case 2: // Öğle
47 | id = j;
48 | prayerIcon = PrayerTimeIconConstant.ogle.toPng;
49 | prayerColor = PrayerTimeColor.ogle;
50 | prayerTimeTitle = StringHomeConstant.dhuhr;
51 | isActive = isActiveList[j];
52 | prayerDate = prayerTime.date.isNotEmpty ? prayerTimes[i].date : StringCommonConstant.noDateInformation;
53 |
54 | prayerTimeText = prayerTime.times.isNotEmpty ? prayerTimes[i].times[j] : StringCommonConstant.noTimeInformation;
55 | case 3: // İkindi
56 | id = j;
57 | prayerIcon = PrayerTimeIconConstant.ikindi.toPng;
58 | prayerColor = PrayerTimeColor.ikindi;
59 | prayerTimeTitle = StringHomeConstant.asr;
60 | isActive = isActiveList[j];
61 | prayerDate = prayerTime.date.isNotEmpty ? prayerTimes[i].date : StringCommonConstant.noDateInformation;
62 |
63 | prayerTimeText = prayerTime.times.isNotEmpty ? prayerTimes[i].times[j] : StringCommonConstant.noTimeInformation;
64 | case 4: // İftar
65 | id = j;
66 | prayerIcon = PrayerTimeIconConstant.iftar.toPng;
67 | prayerColor = PrayerTimeColor.iftar;
68 | prayerTimeTitle = StringHomeConstant.sunset;
69 | isActive = isActiveList[j];
70 | prayerDate = prayerTime.date.isNotEmpty ? prayerTimes[i].date : StringCommonConstant.noDateInformation;
71 |
72 | prayerTimeText = prayerTime.times.isNotEmpty ? prayerTimes[i].times[j] : StringCommonConstant.noTimeInformation;
73 | case 5: // Yatsı
74 | id = j;
75 | prayerIcon = PrayerTimeIconConstant.yatsi.toPng;
76 | prayerColor = PrayerTimeColor.yatsi;
77 | prayerTimeTitle = StringHomeConstant.isha;
78 | isActive = isActiveList[j];
79 | prayerDate = prayerTime.date.isNotEmpty ? prayerTimes[i].date : StringCommonConstant.noDateInformation;
80 |
81 | prayerTimeText = prayerTime.times.isNotEmpty ? prayerTimes[i].times[j] : StringCommonConstant.noTimeInformation;
82 | default:
83 | break;
84 | }
85 |
86 | gridItemList.add(
87 | GridItem(
88 | id: id!,
89 | color: prayerColor!,
90 | iconPath: prayerIcon!,
91 | title: prayerTimeTitle!,
92 | time: prayerTimeText!,
93 | date: prayerDate!,
94 | isActive: isActive!,
95 | ),
96 | );
97 | }
98 | }
99 | return GridItemResult(gridItemList, isActiveList);
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/assets/image/hadith/logo_hadith.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/lib/model/domain/TurkeyCity.dart:
--------------------------------------------------------------------------------
1 | class TurkeyCity {
2 | TurkeyCity({required this.id, required this.name, required this.lowercaseName});
3 | final int id;
4 | final String name;
5 | final String lowercaseName;
6 |
7 | static List turkeyCities = [
8 | TurkeyCity(id: 1, name: 'ADANA', lowercaseName: 'adana'),
9 | TurkeyCity(id: 2, name: 'ADIYAMAN', lowercaseName: 'adiyaman'),
10 | TurkeyCity(id: 3, name: 'AFYONKARAHİSAR', lowercaseName: 'afyonkarahisar'),
11 | TurkeyCity(id: 4, name: 'AĞRI', lowercaseName: 'agri'),
12 | TurkeyCity(id: 68, name: 'AKSARAY', lowercaseName: 'aksaray'),
13 | TurkeyCity(id: 5, name: 'AMASYA', lowercaseName: 'amasya'),
14 | TurkeyCity(id: 6, name: 'ANKARA', lowercaseName: 'ankara'),
15 | TurkeyCity(id: 7, name: 'ANTALYA', lowercaseName: 'antalya'),
16 | TurkeyCity(id: 75, name: 'ARDAHAN', lowercaseName: 'ardahan'),
17 | TurkeyCity(id: 8, name: 'ARTVİN', lowercaseName: 'artvin'),
18 | TurkeyCity(id: 9, name: 'AYDIN', lowercaseName: 'aydin'),
19 | TurkeyCity(id: 10, name: 'BALIKESİR', lowercaseName: 'balikesir'),
20 | TurkeyCity(id: 74, name: 'BARTIN', lowercaseName: 'bartin'),
21 | TurkeyCity(id: 72, name: 'BATMAN', lowercaseName: 'batman'),
22 | TurkeyCity(id: 69, name: 'BAYBURT', lowercaseName: 'bayburt'),
23 | TurkeyCity(id: 11, name: 'BİLECİK', lowercaseName: 'bilecik'),
24 | TurkeyCity(id: 12, name: 'BİNGÖL', lowercaseName: 'bingol'),
25 | TurkeyCity(id: 13, name: 'BİTLİS', lowercaseName: 'bitlis'),
26 | TurkeyCity(id: 14, name: 'BOLU', lowercaseName: 'bolu'),
27 | TurkeyCity(id: 15, name: 'BURDUR', lowercaseName: 'burdur'),
28 | TurkeyCity(id: 16, name: 'BURSA', lowercaseName: 'bursa'),
29 | TurkeyCity(id: 17, name: 'ÇANAKKALE', lowercaseName: 'canakkale'),
30 | TurkeyCity(id: 18, name: 'ÇANKIRI', lowercaseName: 'cankiri'),
31 | TurkeyCity(id: 19, name: 'ÇORUM', lowercaseName: 'corum'),
32 | TurkeyCity(id: 20, name: 'DENİZLİ', lowercaseName: 'denizli'),
33 | TurkeyCity(id: 21, name: 'DİYARBAKIR', lowercaseName: 'diyarbakir'),
34 | TurkeyCity(id: 81, name: 'DÜZCE', lowercaseName: 'duzce'),
35 | TurkeyCity(id: 22, name: 'EDİRNE', lowercaseName: 'edirne'),
36 | TurkeyCity(id: 23, name: 'ELAZIĞ', lowercaseName: 'elazig'),
37 | TurkeyCity(id: 24, name: 'ERZİNCAN', lowercaseName: 'erzincan'),
38 | TurkeyCity(id: 25, name: 'ERZURUM', lowercaseName: 'erzurum'),
39 | TurkeyCity(id: 26, name: 'ESKİŞEHİR', lowercaseName: 'eskisehir'),
40 | TurkeyCity(id: 27, name: 'GAZİANTEP', lowercaseName: 'gaziantep'),
41 | TurkeyCity(id: 28, name: 'GİRESUN', lowercaseName: 'giresun'),
42 | TurkeyCity(id: 29, name: 'GÜMÜŞHANE', lowercaseName: 'gumushane'),
43 | TurkeyCity(id: 30, name: 'HAKKARİ', lowercaseName: 'hakkari'),
44 | TurkeyCity(id: 31, name: 'HATAY', lowercaseName: 'hatay'),
45 | TurkeyCity(id: 76, name: 'IĞDIR', lowercaseName: 'igdir'),
46 | TurkeyCity(id: 32, name: 'ISPARTA', lowercaseName: 'isparta'),
47 | TurkeyCity(id: 34, name: 'İSTANBUL', lowercaseName: 'istanbul'),
48 | TurkeyCity(id: 35, name: 'İZMİR', lowercaseName: 'izmir'),
49 | TurkeyCity(id: 46, name: 'KAHRAMANMARAŞ', lowercaseName: 'kahramanmaras'),
50 | TurkeyCity(id: 78, name: 'KARABÜK', lowercaseName: 'karabuk'),
51 | TurkeyCity(id: 70, name: 'KARAMAN', lowercaseName: 'karaman'),
52 | TurkeyCity(id: 36, name: 'KARS', lowercaseName: 'kars'),
53 | TurkeyCity(id: 37, name: 'KASTAMONU', lowercaseName: 'kastamonu'),
54 | TurkeyCity(id: 38, name: 'KAYSERİ', lowercaseName: 'kayseri'),
55 | TurkeyCity(id: 71, name: 'KIRIKKALE', lowercaseName: 'kirikkale'),
56 | TurkeyCity(id: 39, name: 'KIRKLARELİ', lowercaseName: 'kirklareli'),
57 | TurkeyCity(id: 40, name: 'KIRŞEHİR', lowercaseName: 'kirsehir'),
58 | TurkeyCity(id: 79, name: 'KİLİS', lowercaseName: 'kilis'),
59 | TurkeyCity(id: 41, name: 'KOCAELİ', lowercaseName: 'kocaeli'),
60 | TurkeyCity(id: 42, name: 'KONYA', lowercaseName: 'konya'),
61 | TurkeyCity(id: 43, name: 'KÜTAHYA', lowercaseName: 'kutahya'),
62 | TurkeyCity(id: 44, name: 'MALATYA', lowercaseName: 'malatya'),
63 | TurkeyCity(id: 45, name: 'MANİSA', lowercaseName: 'manisa'),
64 | TurkeyCity(id: 47, name: 'MARDİN', lowercaseName: 'mardin'),
65 | TurkeyCity(id: 33, name: 'MERSİN', lowercaseName: 'mersin'),
66 | TurkeyCity(id: 48, name: 'MUĞLA', lowercaseName: 'mugla'),
67 | TurkeyCity(id: 49, name: 'MUŞ', lowercaseName: 'mus'),
68 | TurkeyCity(id: 50, name: 'NEVŞEHİR', lowercaseName: 'nevsehir'),
69 | TurkeyCity(id: 51, name: 'NİĞDE', lowercaseName: 'nigde'),
70 | TurkeyCity(id: 52, name: 'ORDU', lowercaseName: 'ordu'),
71 | TurkeyCity(id: 80, name: 'OSMANİYE', lowercaseName: 'osmaniye'),
72 | TurkeyCity(id: 53, name: 'RİZE', lowercaseName: 'rize'),
73 | TurkeyCity(id: 54, name: 'SAKARYA', lowercaseName: 'sakarya'),
74 | TurkeyCity(id: 55, name: 'SAMSUN', lowercaseName: 'samsun'),
75 | TurkeyCity(id: 56, name: 'SİİRT', lowercaseName: 'siirt'),
76 | TurkeyCity(id: 57, name: 'SİNOP', lowercaseName: 'sinop'),
77 | TurkeyCity(id: 58, name: 'SİVAS', lowercaseName: 'sivas'),
78 | TurkeyCity(id: 63, name: 'ŞANLIURFA', lowercaseName: 'sanliurfa'),
79 | TurkeyCity(id: 73, name: 'ŞIRNAK', lowercaseName: 'sirnak'),
80 | TurkeyCity(id: 59, name: 'TEKİRDAĞ', lowercaseName: 'tekirdag'),
81 | TurkeyCity(id: 60, name: 'TOKAT', lowercaseName: 'tokat'),
82 | TurkeyCity(id: 61, name: 'TRABZON', lowercaseName: 'trabzon'),
83 | TurkeyCity(id: 62, name: 'TUNCELİ', lowercaseName: 'tunceli'),
84 | TurkeyCity(id: 64, name: 'UŞAK', lowercaseName: 'usak'),
85 | TurkeyCity(id: 65, name: 'VAN', lowercaseName: 'van'),
86 | TurkeyCity(id: 77, name: 'YALOVA', lowercaseName: 'yalova'),
87 | TurkeyCity(id: 66, name: 'YOZGAT', lowercaseName: 'yozgat'),
88 | TurkeyCity(id: 67, name: 'ZONGULDAK', lowercaseName: 'zonguldak'),
89 | ];
90 | }
91 |
--------------------------------------------------------------------------------