diff --git a/.github/workflows/analyze.yaml b/.github/workflows/analyze.yaml
new file mode 100644
index 0000000..fdf76ba
--- /dev/null
+++ b/.github/workflows/analyze.yaml
@@ -0,0 +1,40 @@
+name: analyze
+
+env:
+ FLUTTER_VERSION: stable
+
+on:
+ pull_request:
+ paths-ignore:
+ - '**.md'
+ push:
+ branches:
+ - main
+ paths-ignore:
+ - '**.md'
+jobs:
+ format:
+ runs-on: macos-latest
+ steps:
+ - uses: actions/checkout@v2.3.4
+ - uses: subosito/flutter-action@v1
+ with:
+ channel: 'stable'
+
+ - run: flutter pub get
+
+ - run: flutter analyze .
+
+ - run: flutter format lib/** --set-exit-if-changed
+
+ test:
+ runs-on: macos-latest
+ steps:
+ - uses: actions/checkout@v2.3.4
+ - uses: subosito/flutter-action@v1
+ with:
+ channel: 'stable'
+
+ - run: flutter pub get
+
+ - run: flutter test
diff --git a/README.md b/README.md
index 23f3dc0..ab60579 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,7 @@
# [Noor App | تطبيق نُور](https://noorathkar.com)
+[![Codemagic build status](https://api.codemagic.io/apps/6208f023546bd24402e57b64/6208f023546bd24402e57b63/status_badge.svg)](https://codemagic.io/apps/6208f023546bd24402e57b64/6208f023546bd24402e57b63/latest_build)
+
diff --git a/analysis_options.yaml b/analysis_options.yaml
index 5bfd898..a3be6b8 100644
--- a/analysis_options.yaml
+++ b/analysis_options.yaml
@@ -1,17 +1 @@
-linter:
- rules:
- - always_specify_types
- - avoid_unnecessary_containers
- - unnecessary_statements
- - prefer_conditional_assignment
- - curly_braces_in_flow_control_structures
- - flutter_style_todos
- - join_return_with_assignment
- - prefer_single_quotes
- - avoid_returning_null_for_future
- - avoid_returning_null
- - unnecessary_this
- - sized_box_for_whitespace
- - always_use_package_imports
- - avoid_relative_lib_imports
- - lines_longer_than_80_chars
+include: package:flutter_lints/flutter.yaml
\ No newline at end of file
diff --git a/android/app/build.gradle b/android/app/build.gradle
index 5b548d3..b414d17 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -29,7 +29,7 @@ if (keystorePropertiesFile.exists()) {
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}
android {
- compileSdkVersion 29
+ compileSdkVersion 31
lintOptions {
disable 'InvalidPackage'
@@ -37,8 +37,8 @@ android {
defaultConfig {
applicationId "com.noor.sa"
- minSdkVersion 16
- targetSdkVersion 29
+ minSdkVersion 19
+ targetSdkVersion 31
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 86dc806..9442ec6 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -10,7 +10,7 @@
@@ -24,7 +24,8 @@
-
+ android:name="io.flutter.app.android.SplashScreenUntilFirstFrame"
+ android:value="true" />
+
diff --git a/android/app/src/main/kotlin/com/noor/noor/MainActivity.kt b/android/app/src/main/kotlin/com/noor/noor/MainActivity.kt
deleted file mode 100644
index ef6a635..0000000
--- a/android/app/src/main/kotlin/com/noor/noor/MainActivity.kt
+++ /dev/null
@@ -1,6 +0,0 @@
-package com.noor.noor
-
-import io.flutter.embedding.android.FlutterActivity
-
-class MainActivity: FlutterActivity() {
-}
diff --git a/android/build.gradle b/android/build.gradle
index 417af53..fed9310 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -2,7 +2,6 @@ buildscript {
repositories {
google()
mavenCentral()
- jcenter()
}
dependencies {
@@ -13,7 +12,7 @@ buildscript {
allprojects {
repositories {
google()
- jcenter()
+ mavenCentral()
}
}
diff --git a/android/gradle.properties b/android/gradle.properties
index 1515360..755300e 100644
--- a/android/gradle.properties
+++ b/android/gradle.properties
@@ -2,4 +2,3 @@ org.gradle.jvmargs=-Xmx1536M
android.useAndroidX=true
android.enableJetifier=true
-android.enableR8=true
diff --git a/assets/icons/p_subha_list.svg b/assets/icons/p_subha_list.svg
new file mode 100644
index 0000000..5e94e09
--- /dev/null
+++ b/assets/icons/p_subha_list.svg
@@ -0,0 +1,83 @@
+
+
+
diff --git a/assets/icons/p_subha_lock.svg b/assets/icons/p_subha_lock.svg
new file mode 100644
index 0000000..1a38f2f
--- /dev/null
+++ b/assets/icons/p_subha_lock.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/icons/p_subha_reset.svg b/assets/icons/p_subha_reset.svg
new file mode 100644
index 0000000..1154aa3
--- /dev/null
+++ b/assets/icons/p_subha_reset.svg
@@ -0,0 +1,39 @@
+
+
+
diff --git a/assets/json/default_subha_list.json b/assets/json/default_subha_list.json
new file mode 100644
index 0000000..b4e0e3e
--- /dev/null
+++ b/assets/json/default_subha_list.json
@@ -0,0 +1,11 @@
+{
+ "default": [
+ "سبحان الله",
+ "الحمدلله",
+ "لا إله إلا الله",
+ "الله أكبر",
+ "لا حول ولاقوة إلا بالله العلي العظيم",
+ "سبحان الله العظيم وبحمده",
+ "لا إله إلا الله وحده لا شريك له، له الملك وله الحمد، وهو على كل شيء قدير"
+ ]
+}
\ No newline at end of file
diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist
index 9367d48..8d4492f 100644
--- a/ios/Flutter/AppFrameworkInfo.plist
+++ b/ios/Flutter/AppFrameworkInfo.plist
@@ -21,6 +21,6 @@
CFBundleVersion
1.0
MinimumOSVersion
- 8.0
+ 9.0
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index f6150e2..6f0be01 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -1,93 +1,89 @@
PODS:
- - Firebase/CoreOnly (7.11.0):
- - FirebaseCore (= 7.11.0)
- - Firebase/Messaging (7.11.0):
+ - Firebase/CoreOnly (8.9.0):
+ - FirebaseCore (= 8.9.0)
+ - Firebase/Messaging (8.9.0):
- Firebase/CoreOnly
- - FirebaseMessaging (~> 7.11.0)
- - Firebase/RemoteConfig (7.11.0):
+ - FirebaseMessaging (~> 8.9.0)
+ - Firebase/RemoteConfig (8.9.0):
- Firebase/CoreOnly
- - FirebaseRemoteConfig (~> 7.11.0)
- - firebase_core (1.1.1):
- - Firebase/CoreOnly (= 7.11.0)
+ - FirebaseRemoteConfig (~> 8.9.0)
+ - firebase_core (1.10.2):
+ - Firebase/CoreOnly (= 8.9.0)
- Flutter
- - firebase_messaging (9.1.4):
- - Firebase/Messaging (= 7.11.0)
+ - firebase_messaging (11.2.0):
+ - Firebase/Messaging (= 8.9.0)
- firebase_core
- Flutter
- - firebase_remote_config (0.10.0-dev.3):
- - Firebase/RemoteConfig (= 7.11.0)
+ - firebase_remote_config (1.0.0-dev.3):
+ - Firebase/RemoteConfig (= 8.9.0)
- firebase_core
- Flutter
- - FirebaseABTesting (7.11.0):
- - FirebaseCore (~> 7.0)
- - FirebaseCore (7.11.0):
- - FirebaseCoreDiagnostics (~> 7.4)
- - GoogleUtilities/Environment (~> 7.0)
- - GoogleUtilities/Logger (~> 7.0)
- - FirebaseCoreDiagnostics (7.11.0):
- - GoogleDataTransport (~> 8.4)
- - GoogleUtilities/Environment (~> 7.0)
- - GoogleUtilities/Logger (~> 7.0)
+ - FirebaseABTesting (8.9.0):
+ - FirebaseCore (~> 8.0)
+ - FirebaseCore (8.9.0):
+ - FirebaseCoreDiagnostics (~> 8.0)
+ - GoogleUtilities/Environment (~> 7.6)
+ - GoogleUtilities/Logger (~> 7.6)
+ - FirebaseCoreDiagnostics (8.9.0):
+ - GoogleDataTransport (~> 9.1)
+ - GoogleUtilities/Environment (~> 7.6)
+ - GoogleUtilities/Logger (~> 7.6)
- nanopb (~> 2.30908.0)
- - FirebaseInstallations (7.11.0):
- - FirebaseCore (~> 7.0)
- - GoogleUtilities/Environment (~> 7.0)
- - GoogleUtilities/UserDefaults (~> 7.0)
- - PromisesObjC (~> 1.2)
- - FirebaseInstanceID (7.11.0):
- - FirebaseCore (~> 7.0)
- - FirebaseInstallations (~> 7.0)
- - GoogleUtilities/Environment (~> 7.0)
- - GoogleUtilities/UserDefaults (~> 7.0)
- - FirebaseMessaging (7.11.0):
- - FirebaseCore (~> 7.0)
- - FirebaseInstallations (~> 7.0)
- - FirebaseInstanceID (~> 7.0)
- - GoogleUtilities/AppDelegateSwizzler (~> 7.0)
- - GoogleUtilities/Environment (~> 7.0)
- - GoogleUtilities/Reachability (~> 7.0)
- - GoogleUtilities/UserDefaults (~> 7.0)
- - FirebaseRemoteConfig (7.11.0):
- - FirebaseABTesting (~> 7.0)
- - FirebaseCore (~> 7.0)
- - FirebaseInstallations (~> 7.0)
- - GoogleUtilities/Environment (~> 7.0)
- - "GoogleUtilities/NSData+zlib (~> 7.0)"
+ - FirebaseInstallations (8.9.0):
+ - FirebaseCore (~> 8.0)
+ - GoogleUtilities/Environment (~> 7.6)
+ - GoogleUtilities/UserDefaults (~> 7.6)
+ - PromisesObjC (< 3.0, >= 1.2)
+ - FirebaseMessaging (8.9.0):
+ - FirebaseCore (~> 8.0)
+ - FirebaseInstallations (~> 8.0)
+ - GoogleDataTransport (~> 9.1)
+ - GoogleUtilities/AppDelegateSwizzler (~> 7.6)
+ - GoogleUtilities/Environment (~> 7.6)
+ - GoogleUtilities/Reachability (~> 7.6)
+ - GoogleUtilities/UserDefaults (~> 7.6)
+ - nanopb (~> 2.30908.0)
+ - FirebaseRemoteConfig (8.9.0):
+ - FirebaseABTesting (~> 8.0)
+ - FirebaseCore (~> 8.0)
+ - FirebaseInstallations (~> 8.0)
+ - GoogleUtilities/Environment (~> 7.6)
+ - "GoogleUtilities/NSData+zlib (~> 7.6)"
- Flutter (1.0.0)
- flutter_local_notifications (0.0.1):
- Flutter
- FMDB (2.7.5):
- FMDB/standard (= 2.7.5)
- FMDB/standard (2.7.5)
- - GoogleDataTransport (8.4.0):
+ - GoogleDataTransport (9.1.2):
- GoogleUtilities/Environment (~> 7.2)
- nanopb (~> 2.30908.0)
- - PromisesObjC (~> 1.2)
- - GoogleUtilities/AppDelegateSwizzler (7.4.1):
+ - PromisesObjC (< 3.0, >= 1.2)
+ - GoogleUtilities/AppDelegateSwizzler (7.6.0):
- GoogleUtilities/Environment
- GoogleUtilities/Logger
- GoogleUtilities/Network
- - GoogleUtilities/Environment (7.4.1):
- - PromisesObjC (~> 1.2)
- - GoogleUtilities/Logger (7.4.1):
+ - GoogleUtilities/Environment (7.6.0):
+ - PromisesObjC (< 3.0, >= 1.2)
+ - GoogleUtilities/Logger (7.6.0):
- GoogleUtilities/Environment
- - GoogleUtilities/Network (7.4.1):
+ - GoogleUtilities/Network (7.6.0):
- GoogleUtilities/Logger
- "GoogleUtilities/NSData+zlib"
- GoogleUtilities/Reachability
- - "GoogleUtilities/NSData+zlib (7.4.1)"
- - GoogleUtilities/Reachability (7.4.1):
+ - "GoogleUtilities/NSData+zlib (7.6.0)"
+ - GoogleUtilities/Reachability (7.6.0):
- GoogleUtilities/Logger
- - GoogleUtilities/UserDefaults (7.4.1):
+ - GoogleUtilities/UserDefaults (7.6.0):
- GoogleUtilities/Logger
- nanopb (2.30908.0):
- nanopb/decode (= 2.30908.0)
- nanopb/encode (= 2.30908.0)
- nanopb/decode (2.30908.0)
- nanopb/encode (2.30908.0)
- - path_provider (0.0.1):
+ - path_provider_ios (0.0.1):
- Flutter
- - PromisesObjC (1.2.12)
+ - PromisesObjC (2.0.0)
- share (0.0.1):
- Flutter
- shared_preferences (0.0.1):
@@ -104,7 +100,7 @@ DEPENDENCIES:
- firebase_remote_config (from `.symlinks/plugins/firebase_remote_config/ios`)
- Flutter (from `Flutter`)
- flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`)
- - path_provider (from `.symlinks/plugins/path_provider/ios`)
+ - path_provider_ios (from `.symlinks/plugins/path_provider_ios/ios`)
- share (from `.symlinks/plugins/share/ios`)
- shared_preferences (from `.symlinks/plugins/shared_preferences/ios`)
- sqflite (from `.symlinks/plugins/sqflite/ios`)
@@ -117,7 +113,6 @@ SPEC REPOS:
- FirebaseCore
- FirebaseCoreDiagnostics
- FirebaseInstallations
- - FirebaseInstanceID
- FirebaseMessaging
- FirebaseRemoteConfig
- FMDB
@@ -137,8 +132,8 @@ EXTERNAL SOURCES:
:path: Flutter
flutter_local_notifications:
:path: ".symlinks/plugins/flutter_local_notifications/ios"
- path_provider:
- :path: ".symlinks/plugins/path_provider/ios"
+ path_provider_ios:
+ :path: ".symlinks/plugins/path_provider_ios/ios"
share:
:path: ".symlinks/plugins/share/ios"
shared_preferences:
@@ -149,25 +144,24 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/url_launcher/ios"
SPEC CHECKSUMS:
- Firebase: c121feb35e4126c0b355e3313fa9b487d47319fd
- firebase_core: 54856a8a39b8f3e35f34fdd3373f3b92a1daa68b
- firebase_messaging: 64d2a9b095bc7afa54eff3f4e13522d9098619d2
- firebase_remote_config: 44bb7d35f010caf2d28c2719a5b3585cea4ee558
- FirebaseABTesting: e66f1f80747792630d9b292966de206d5df9853b
- FirebaseCore: 907447d8917a4d3eb0cce2829c5a0ad21d90b432
- FirebaseCoreDiagnostics: 68ad972f99206cef818230f3f3179d52ccfb7f8c
- FirebaseInstallations: a58d4f72ec5861840b84df489f2668d970df558a
- FirebaseInstanceID: ad5135045a498d7775903efd39762d2cdfa1be27
- FirebaseMessaging: 163435fb6db065e3b6228f1e577b10ed2cc506d2
- FirebaseRemoteConfig: 0ea30de5fb0231df8c1bdcdf3b6c23bdc5066131
- Flutter: 434fef37c0980e73bb6479ef766c45957d4b510c
+ Firebase: 13d8d96499e2635428d5bf0ec675df21f95d9a95
+ firebase_core: 6d1a5e12a83b6d9419ecb8f2a53d876e7b4695da
+ firebase_messaging: 4f7eab3f100c30d0544f5a6f6ca549f7f8c12705
+ firebase_remote_config: 387ba6e443177a276acfdcb24bce201c023e0d99
+ FirebaseABTesting: 9de50b34bf9eb4a07d4edb7af82c14152fd905aa
+ FirebaseCore: 599ee609343eaf4941bd188f85e3aa077ffe325b
+ FirebaseCoreDiagnostics: 5daa63f1c1409d981a2d5007daa100b36eac6a34
+ FirebaseInstallations: caa7c8e0d3e2345b8829d2fa9ca1b4dfbf2fcc85
+ FirebaseMessaging: 82c4a48638f53f7b184f3cc9f6cd2cbe533ab316
+ FirebaseRemoteConfig: a75c1bd44ebd3ed4ad3fa1ff09414a8b133be405
+ Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a
flutter_local_notifications: 0c0b1ae97e741e1521e4c1629a459d04b9aec743
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
- GoogleDataTransport: cd9db2180fcecd8da1b561aea31e3e56cf834aa7
- GoogleUtilities: f8a43108b38a68eebe8b3540e1f4f2d28843ce20
+ GoogleDataTransport: 629c20a4d363167143f30ea78320d5a7eb8bd940
+ GoogleUtilities: 684ee790a24f73ebb2d1d966e9711c203f2a4237
nanopb: a0ba3315591a9ae0a16a309ee504766e90db0c96
- path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c
- PromisesObjC: 3113f7f76903778cf4a0586bd1ab89329a0b7b97
+ path_provider_ios: 7d7ce634493af4477d156294792024ec3485acd5
+ PromisesObjC: 68159ce6952d93e17b2dfe273b8c40907db5ba58
share: 0b2c3e82132f5888bccca3351c504d0003b3b410
shared_preferences: af6bfa751691cdc24be3045c43ec037377ada40d
sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904
@@ -175,4 +169,4 @@ SPEC CHECKSUMS:
PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c
-COCOAPODS: 1.10.0
+COCOAPODS: 1.11.2
diff --git a/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
deleted file mode 100644
index f9b0d7c..0000000
--- a/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
- PreviewsEnabled
-
-
-
diff --git a/lib/app/app.dart b/lib/app/app.dart
index 39339f6..d7e4d70 100644
--- a/lib/app/app.dart
+++ b/lib/app/app.dart
@@ -9,8 +9,11 @@ import 'package:noor/exports/models.dart' show DataModel, SettingsModel;
import 'package:noor/exports/components.dart' show CustomScrollBehavior;
import 'package:noor/exports/controllers.dart' show ThemeModel;
import 'package:noor/exports/constants.dart' show lightTheme, darkTheme;
+import 'package:noor/pages/tabs/page_3_counter/counter_view_model.dart';
class NoorApp extends StatelessWidget {
+ const NoorApp({Key? key}) : super(key: key);
+
@override
Widget build(BuildContext context) {
return MultiProvider(
@@ -24,28 +27,33 @@ class NoorApp extends StatelessWidget {
ChangeNotifierProvider(
create: (_) => GetIt.I(),
),
+ ChangeNotifierProvider(
+ create: (_) => GetIt.I(),
+ ),
],
- child: MaterialAppWithTheme(),
+ child: const MaterialAppWithTheme(),
);
}
}
class MaterialAppWithTheme extends StatelessWidget {
+ const MaterialAppWithTheme({Key? key}) : super(key: key);
+
@override
Widget build(BuildContext context) {
final ThemeModel themeProvider = context.watch();
return MaterialApp(
- localizationsDelegates: >[
+ localizationsDelegates: const >[
// ... app-specific localization delegate[s] here
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
- supportedLocales: [
- const Locale('ar'), // Arabic
+ supportedLocales: const [
+ Locale('ar'), // Arabic
],
- locale: Locale('ar'),
+ locale: const Locale('ar'),
debugShowCheckedModeBanner: false,
title: 'نُور',
themeMode: themeProvider.theme,
@@ -61,7 +69,7 @@ class MaterialAppWithTheme extends StatelessWidget {
),
);
},
- home: SplashScreen(),
+ home: const SplashScreen(),
);
}
}
diff --git a/lib/components/add_dialog.dart b/lib/components/add_dialog.dart
new file mode 100644
index 0000000..7c69a5e
--- /dev/null
+++ b/lib/components/add_dialog.dart
@@ -0,0 +1,205 @@
+import 'package:flutter/material.dart';
+import 'package:noor/components/dialog_button.dart';
+import 'package:noor/pages/tabs/page_3_counter/counter_list_view.dart';
+
+import 'editable_text_max_length_highlighter.dart';
+
+class AddDialog extends StatefulWidget {
+ const AddDialog(
+ this.context, {
+ Key? key,
+ this.mainContent = '',
+ this.mainContentMaxLength,
+ this.secondaryContent = '',
+ this.onSave,
+ this.onCancel,
+ this.enableSecondaryContent = false,
+ }) : super(key: key);
+ final BuildContext context;
+ final String mainContent;
+ final String secondaryContent;
+ final int? mainContentMaxLength;
+ final void Function(String)? onSave;
+ final void Function()? onCancel;
+ final bool enableSecondaryContent;
+
+ static AddDialog of(BuildContext context) {
+ return AddDialog(context);
+ }
+
+ Future show({
+ String mainContent = '',
+ String secondaryContent = '',
+ void Function(String)? onSave,
+ void Function()? onCancel,
+ bool enableSecondaryContent = false,
+ bool barrierDismissible = true,
+ final int? mainContentMaxLength,
+ }) async {
+ return await showGeneralDialog(
+ transitionDuration: const Duration(milliseconds: 600),
+ barrierColor: Colors.black.withOpacity(0.75),
+ barrierLabel: '',
+ barrierDismissible: barrierDismissible,
+ context: context,
+ transitionBuilder: (_, Animation a1, Animation a2, __) {
+ final double curvedValue =
+ Curves.easeInOutBack.transform(a1.value) - 1.0;
+ return Transform(
+ transform: Matrix4.translationValues(0.0, curvedValue * 800, 0.0),
+ child: AddDialog(
+ context,
+ mainContent: mainContent,
+ mainContentMaxLength: mainContentMaxLength,
+ secondaryContent: secondaryContent,
+ onSave: onSave,
+ onCancel: onCancel,
+ enableSecondaryContent: enableSecondaryContent,
+ ),
+ );
+ },
+ pageBuilder: (_, __, ___) => const SizedBox(),
+ );
+ }
+
+ @override
+ _AddDialogState createState() => _AddDialogState();
+}
+
+class _AddDialogState extends State {
+ late TextFieldMaxLengthHighlighter mainContentController;
+ late TextEditingController secondaryContentController;
+ bool mainContentActive = false;
+
+ @override
+ void initState() {
+ super.initState();
+ mainContentController = TextFieldMaxLengthHighlighter(
+ text: widget.mainContent,
+ maxLength: widget.mainContentMaxLength,
+ );
+
+ secondaryContentController =
+ TextEditingController(text: widget.secondaryContent);
+
+ mainContentController.addListener(() {
+ setState(() {
+ if (mainContentController.text.isEmpty ||
+ mainContentController.text.length > kMaxLength) {
+ mainContentActive = false;
+ } else {
+ mainContentActive = true;
+ }
+ });
+ });
+ }
+
+ button({
+ required String text,
+ required BorderRadiusGeometry radius,
+ void Function()? onPressed,
+ BoxBorder? border,
+ Color? textColor,
+ }) {
+ return DialogButton(
+ label: text,
+ border: border,
+ onPressed: onPressed,
+ radius: radius,
+ textColor: textColor,
+ );
+ }
+
+ // Text input design (used in dialoges)
+ input(double height, String text, TextEditingController controller) {
+ return ConstrainedBox(
+ constraints: BoxConstraints(minHeight: height),
+ child: SingleChildScrollView(
+ child: TextField(
+ autofocus: true,
+ controller: controller,
+ style: Theme.of(context).textTheme.bodyText1,
+ decoration: InputDecoration(
+ filled: false,
+ contentPadding:
+ const EdgeInsets.symmetric(vertical: 12, horizontal: 10.0),
+ border: InputBorder.none,
+ hintText: text,
+ counterText: "",
+ ),
+ maxLines: 3,
+ minLines: 3,
+ ),
+ ),
+ );
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Dialog(
+ elevation: 6.0,
+ child: Container(
+ decoration: BoxDecoration(
+ color: Theme.of(context).brightness == Brightness.light
+ ? Colors.white
+ : const Color(0xff1B2349),
+ borderRadius: BorderRadius.circular(15.0),
+ ),
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ SingleChildScrollView(
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ input(100.0, 'أضِف ذِكر...', mainContentController),
+ if (widget.enableSecondaryContent) const Divider(),
+ if (widget.enableSecondaryContent)
+ input(80.0, 'نص إضافي...', secondaryContentController),
+ if (widget.enableSecondaryContent) const SizedBox(height: 40)
+ ],
+ ),
+ ),
+ Align(
+ alignment: Alignment.bottomCenter,
+ child: Container(
+ constraints: const BoxConstraints.expand(height: 40),
+ child: Row(
+ crossAxisAlignment: CrossAxisAlignment.stretch,
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ button(
+ text: 'حفظ',
+ border: Border(
+ left: BorderSide(
+ width: 0.5, color: Theme.of(context).cardColor),
+ ),
+ radius: const BorderRadius.only(
+ bottomRight: Radius.circular(15)),
+ onPressed: !mainContentActive
+ ? null
+ : () =>
+ widget.onSave?.call(mainContentController.text),
+ ),
+ button(
+ text: 'إلغاء',
+ border: Border(
+ right: BorderSide(
+ width: 0.5, color: Theme.of(context).cardColor),
+ ),
+ textColor: Colors.white,
+ radius: const BorderRadius.only(
+ bottomLeft: Radius.circular(15)),
+ onPressed: widget.onCancel,
+ ),
+ ],
+ ),
+ ),
+ )
+ ],
+ ),
+ ),
+ shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15.0)),
+ );
+ }
+}
diff --git a/lib/components/alert_dialog.dart b/lib/components/alert_dialog.dart
new file mode 100644
index 0000000..98537ff
--- /dev/null
+++ b/lib/components/alert_dialog.dart
@@ -0,0 +1,128 @@
+import 'package:flutter/material.dart';
+
+import 'dialog_button.dart';
+
+class NoorAlertDialog extends StatelessWidget {
+ const NoorAlertDialog(
+ this.context, {
+ Key? key,
+ this.title = '',
+ this.content = '',
+ }) : super(key: key);
+ final String title;
+ final String content;
+ final BuildContext context;
+
+ static NoorAlertDialog of(BuildContext context) {
+ return NoorAlertDialog(context);
+ }
+
+ Future show({
+ required String title,
+ required String content,
+ }) async {
+ return await showGeneralDialog(
+ transitionDuration: const Duration(milliseconds: 600),
+ barrierColor: Colors.black.withOpacity(0.75),
+ barrierLabel: '',
+ barrierDismissible: true,
+ context: context,
+ transitionBuilder: (_, Animation a1, Animation a2, __) {
+ final double curvedValue =
+ Curves.easeInOutBack.transform(a1.value) - 1.0;
+ return Transform(
+ transform: Matrix4.translationValues(0.0, curvedValue * 800, 0.0),
+ child: NoorAlertDialog(
+ context,
+ title: title,
+ content: content,
+ ),
+ );
+ },
+ pageBuilder: (_, __, ___) => const SizedBox(),
+ );
+ }
+
+ // Text input design (used in dialoges)
+ input(double height, String text, TextEditingController controller) {
+ return ConstrainedBox(
+ constraints: BoxConstraints(minHeight: height),
+ child: SingleChildScrollView(
+ child: TextField(
+ autofocus: true,
+ controller: controller,
+ style: Theme.of(context).textTheme.bodyText1,
+ decoration: InputDecoration(
+ filled: false,
+ contentPadding:
+ const EdgeInsets.symmetric(vertical: 12, horizontal: 10.0),
+ border: InputBorder.none,
+ hintText: text,
+ counterText: "",
+ ),
+ maxLines: 3,
+ minLines: 3,
+ ),
+ ),
+ );
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Dialog(
+ elevation: 6.0,
+ shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15.0)),
+ child: Container(
+ constraints: const BoxConstraints(maxHeight: 130),
+ child: Stack(
+ children: [
+ Container(
+ padding: const EdgeInsets.all(10),
+ alignment: Alignment.center,
+ child: Column(
+ children: [
+ Text(
+ title,
+ style: TextStyle(
+ color: Theme.of(context).primaryColor,
+ fontSize: 18,
+ fontWeight: FontWeight.bold,
+ ),
+ ),
+ Text(content)
+ ],
+ ),
+ ),
+ Align(
+ alignment: Alignment.bottomCenter,
+ child: Container(
+ constraints: const BoxConstraints.expand(height: 40),
+ child: Row(
+ crossAxisAlignment: CrossAxisAlignment.stretch,
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ DialogButton(
+ label: 'إلغاء',
+ textColor: Colors.white,
+ border: Border(
+ right: BorderSide(
+ width: 0.5, color: Theme.of(context).cardColor),
+ ),
+ onPressed: () async {
+ Navigator.of(context).pop(false);
+ },
+ radius: const BorderRadius.only(
+ bottomLeft: Radius.circular(15),
+ bottomRight: Radius.circular(15),
+ ),
+ ),
+ ],
+ ),
+ ),
+ )
+ ],
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/components/allah_names_title.dart b/lib/components/allah_names_title.dart
index 9a7205e..ca83617 100644
--- a/lib/components/allah_names_title.dart
+++ b/lib/components/allah_names_title.dart
@@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
import 'package:noor/exports/constants.dart' show Images;
class NameTitleCard extends StatelessWidget {
- NameTitleCard({this.title});
+ const NameTitleCard({Key? key, this.title}) : super(key: key);
final String? title;
@override
@@ -18,13 +18,13 @@ class NameTitleCard extends StatelessWidget {
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.headline2,
),
- margin: EdgeInsets.only(
+ margin: const EdgeInsets.only(
left: 30,
right: 30,
top: 10.0,
bottom: 10.0,
),
- padding: EdgeInsets.only(
+ padding: const EdgeInsets.only(
right: 90,
left: 90,
top: 10.0,
@@ -34,8 +34,8 @@ class NameTitleCard extends StatelessWidget {
height: 95,
alignment: Alignment.center,
decoration: BoxDecoration(
- boxShadow: [
- new BoxShadow(
+ boxShadow: const [
+ BoxShadow(
color: Colors.black26,
blurRadius: 8.0,
),
diff --git a/lib/components/athkar_card.dart b/lib/components/athkar_card.dart
index bfe3524..c9b7258 100644
--- a/lib/components/athkar_card.dart
+++ b/lib/components/athkar_card.dart
@@ -44,10 +44,10 @@ class AthkarCard extends StatelessWidget {
alignment: Alignment.bottomCenter,
child: counter.position < 1
? AnimatedContainer(
- duration: Duration(milliseconds: 400),
+ duration: const Duration(milliseconds: 400),
curve: Curves.bounceInOut,
alignment: Alignment.center,
- child: Icon(
+ child: const Icon(
Icons.done,
color: Color(0xff58d1ed),
),
@@ -55,9 +55,9 @@ class AthkarCard extends StatelessWidget {
color: Theme.of(context).brightness ==
Brightness.light
? Colors.white
- : Color(0xff202b54),
+ : const Color(0xff202b54),
border: Border.all(
- color: Color(0xff6f86d6), width: 2),
+ color: const Color(0xff6f86d6), width: 2),
borderRadius: BorderRadius.circular(50.0)),
width: 45.0,
height: 45.0,
@@ -69,21 +69,22 @@ class AthkarCard extends StatelessWidget {
'${counter.position}'.arabicDigit(),
key: ValueKey(counter.position),
style: TextStyle(
- color: Theme.of(context).accentColor,
- fontSize: 16,
- height: 1.25),
+ color: Theme.of(context).colorScheme.secondary,
+ fontSize: 16,
+ height: 1.25,
+ ),
),
),
decoration: BoxDecoration(
color:
Theme.of(context).brightness == Brightness.light
? Colors.white
- : Color(0xff202b54),
+ : const Color(0xff202b54),
border: Border.all(
color: Theme.of(context).brightness ==
Brightness.light
? Colors.grey[400]!
- : Color(0xff33477f),
+ : const Color(0xff33477f),
width: 2),
borderRadius: BorderRadius.circular(50.0),
),
diff --git a/lib/components/athkar_title.dart b/lib/components/athkar_title.dart
index a8f0152..b0a2597 100644
--- a/lib/components/athkar_title.dart
+++ b/lib/components/athkar_title.dart
@@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
import 'package:noor/exports/constants.dart' show Images;
class ThekrTitleCard extends StatelessWidget {
- ThekrTitleCard({this.title});
+ const ThekrTitleCard({Key? key, this.title}) : super(key: key);
final String? title;
@override
@@ -13,7 +13,7 @@ class ThekrTitleCard extends StatelessWidget {
children: [
Positioned(
child: Container(
- margin: EdgeInsets.only(
+ margin: const EdgeInsets.only(
left: 30,
right: 30,
top: 10.0,
@@ -29,7 +29,7 @@ class ThekrTitleCard extends StatelessWidget {
style: Theme.of(context).textTheme.headline2,
),
alignment: Alignment.center,
- padding: EdgeInsets.only(
+ padding: const EdgeInsets.only(
right: 70,
left: 70,
top: 10.0,
@@ -37,8 +37,8 @@ class ThekrTitleCard extends StatelessWidget {
),
),
decoration: BoxDecoration(
- boxShadow: [
- new BoxShadow(
+ boxShadow: const [
+ BoxShadow(
color: Colors.black26,
blurRadius: 8.0,
),
diff --git a/lib/components/bottom_nav.dart b/lib/components/bottom_nav.dart
index 7e7c73a..794a06b 100644
--- a/lib/components/bottom_nav.dart
+++ b/lib/components/bottom_nav.dart
@@ -3,7 +3,7 @@ import 'package:flutter_svg/svg.dart';
import 'package:noor/exports/constants.dart' show NoorIcons;
class BottomNav extends StatefulWidget {
- BottomNav({
+ const BottomNav({
Key? key,
this.onTap,
}) : super(key: key);
@@ -112,17 +112,17 @@ class _BottomItemState extends State
reverseDuration: Duration(milliseconds: duration),
);
- textOffset1 =
- Tween(begin: Offset(0.0, textOffset), end: Offset(0.0, 1.0))
- .animate(
+ textOffset1 = Tween(
+ begin: Offset(0.0, textOffset), end: const Offset(0.0, 1.0))
+ .animate(
CurvedAnimation(
parent: controller,
curve: Curves.elasticOut,
reverseCurve: Curves.elasticIn),
);
- iconOffset1 =
- Tween(begin: Offset(0.0, -1.0), end: Offset(0.0, iconOffset))
- .animate(
+ iconOffset1 = Tween(
+ begin: const Offset(0.0, -1.0), end: Offset(0.0, iconOffset))
+ .animate(
CurvedAnimation(
parent: controller,
curve: Curves.elasticOut,
diff --git a/lib/components/card_template.dart b/lib/components/card_template.dart
index e5f81a2..acba26d 100644
--- a/lib/components/card_template.dart
+++ b/lib/components/card_template.dart
@@ -32,16 +32,16 @@ class CardTemplate extends StatelessWidget {
end: Alignment.bottomCenter,
colors: Theme.of(context).brightness == Brightness.light
? [
- Color(0xfff3f3f3),
- Color(0xfff1f1f1),
+ const Color(0xfff3f3f3),
+ const Color(0xfff1f1f1),
]
: [
- Color(0xff1B2349),
- Color(0xff161A3A),
+ const Color(0xff1B2349),
+ const Color(0xff161A3A),
],
),
boxShadow: [
- new BoxShadow(
+ BoxShadow(
color: Colors.black.withOpacity(0.2),
blurRadius: 12.0,
),
@@ -58,9 +58,9 @@ class CardTemplate extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
- padding: EdgeInsets.symmetric(horizontal: 5.0),
+ padding: const EdgeInsets.symmetric(horizontal: 5.0),
decoration: BoxDecoration(
- borderRadius: BorderRadius.only(
+ borderRadius: const BorderRadius.only(
topLeft: Radius.circular(15.0),
topRight: Radius.circular(15.0),
),
@@ -81,7 +81,7 @@ class CardTemplate extends StatelessWidget {
alignment: Alignment.topRight,
margin: const EdgeInsets.all(5.0),
child: Scrollbar(
- radius: Radius.circular(4),
+ radius: const Radius.circular(4),
child: SingleChildScrollView(
child: Container(
width: double.infinity,
@@ -98,7 +98,7 @@ class CardTemplate extends StatelessWidget {
child: Padding(
padding: const EdgeInsets.all(5.0),
child: Scrollbar(
- radius: Radius.circular(4),
+ radius: const Radius.circular(4),
child: SingleChildScrollView(
child: DefaultTextStyle.merge(
textAlign: TextAlign.justify,
diff --git a/lib/components/card_text.dart b/lib/components/card_text.dart
index 328995f..0fa778e 100644
--- a/lib/components/card_text.dart
+++ b/lib/components/card_text.dart
@@ -1,3 +1,5 @@
+// ignore_for_file: deprecated_member_use
+
import 'package:flutter/material.dart';
import 'package:noor/models/allah_name.dart';
import 'package:provider/provider.dart';
@@ -75,7 +77,7 @@ class CardText extends StatelessWidget {
highlight.map((String e) => Tashkeel.remove(e)).toList().cast();
final RegExp marks = RegExp(
- r'[\u{060C}|\u{FD3F}|\u{060C}|\u{FD3E}|\u{002E}|\u{0029}|\u{0028}|\u{0021}|\u{005B}|\u{005D}|\u{003A}]',
+ r'^[\u{060C}|\u{FD3F}|\u{060C}|\u{FD3E}|\u{002E}|\u{0029}|\u{0028}|\u{0021}|\u{005B}|\u{005D}|\u{003A}]',
unicode: true,
);
@@ -83,6 +85,7 @@ class CardText extends StatelessWidget {
r'^[\u{0648}|\u{0644}|\u{0628}]',
unicode: true,
);
+
int i = 0;
for (String s in sourceList) {
@@ -91,7 +94,7 @@ class CardText extends StatelessWidget {
List match = [];
- if (s.length > 0) {
+ if (s.isNotEmpty) {
for (String m in tmpMatch) {
if (letters.hasMatch(m) && !highlight.contains(m)) {
match.addAll(m.splitWithDelim(letters));
@@ -114,14 +117,12 @@ class CardText extends StatelessWidget {
children.add(
TextSpan(
text: m,
- style: TextStyle(color: Theme.of(context).buttonColor),
+ style: TextStyle(color: Theme.of(context).colorScheme.outline),
),
);
} else {
children.add(
- TextSpan(
- text: m,
- ),
+ TextSpan(text: m),
);
}
}
@@ -132,7 +133,7 @@ class CardText extends StatelessWidget {
children.add(
TextSpan(
text: s,
- style: TextStyle(color: Theme.of(context).buttonColor),
+ style: TextStyle(color: Theme.of(context).colorScheme.outline),
),
);
} else {
@@ -145,7 +146,7 @@ class CardText extends StatelessWidget {
}
children.add(
- TextSpan(
+ const TextSpan(
text: ' ',
),
);
@@ -175,7 +176,7 @@ class CardText extends StatelessWidget {
child: Builder(
builder: (BuildContext context) {
return AnimatedSwitcher(
- duration: Duration(milliseconds: 200),
+ duration: const Duration(milliseconds: 200),
child: item is AllahName
? RichText(
textScaleFactor: settings.fontSize,
diff --git a/lib/components/copy_action.dart b/lib/components/copy_action.dart
index 7ff1fb2..62e0b67 100644
--- a/lib/components/copy_action.dart
+++ b/lib/components/copy_action.dart
@@ -20,7 +20,7 @@ class CopyAction extends StatelessWidget {
barrierLabel: 'Label',
barrierDismissible: false,
barrierColor: Colors.black.withOpacity(0.2),
- transitionDuration: Duration(milliseconds: 500),
+ transitionDuration: const Duration(milliseconds: 500),
context: context,
pageBuilder: (BuildContext context, _, __) {
return Align(
@@ -40,7 +40,7 @@ class CopyAction extends StatelessWidget {
decoration: BoxDecoration(
color: const Color(0xff6f85d5),
borderRadius: BorderRadius.circular(15.0),
- boxShadow: [
+ boxShadow: const [
BoxShadow(blurRadius: 5, color: Colors.black26),
],
),
@@ -49,17 +49,20 @@ class CopyAction extends StatelessWidget {
},
transitionBuilder: (_, Animation anim1, __, Widget child) {
return SlideTransition(
- position: Tween(begin: Offset(0, 0.6), end: Offset(0, 0))
- .animate(CurvedAnimation(
- parent: anim1,
- curve: Curves.easeOutCirc,
- reverseCurve: Curves.easeIn,
- )),
+ position: Tween(
+ begin: const Offset(0, 0.6), end: const Offset(0, 0))
+ .animate(
+ CurvedAnimation(
+ parent: anim1,
+ curve: Curves.easeOutCirc,
+ reverseCurve: Curves.easeIn,
+ ),
+ ),
child: child,
);
},
);
- Future.delayed(Duration(milliseconds: 1000)).then((_) {
+ Future.delayed(const Duration(milliseconds: 1000)).then((_) {
Navigator.of(context, rootNavigator: true).pop('dialog');
});
}
diff --git a/lib/components/custom_scroll_bhaviour.dart b/lib/components/custom_scroll_bhaviour.dart
index d822a0b..c6e2212 100644
--- a/lib/components/custom_scroll_bhaviour.dart
+++ b/lib/components/custom_scroll_bhaviour.dart
@@ -6,4 +6,4 @@ class CustomScrollBehavior extends ScrollBehavior {
BuildContext context, Widget child, AxisDirection axisDirection) {
return child;
}
-}
\ No newline at end of file
+}
diff --git a/lib/components/delete_dialog.dart b/lib/components/delete_dialog.dart
index 9c801cc..cce657c 100644
--- a/lib/components/delete_dialog.dart
+++ b/lib/components/delete_dialog.dart
@@ -1,4 +1,9 @@
+// ignore_for_file: deprecated_member_use
+
import 'package:flutter/material.dart';
+import 'package:noor/constants/strings.dart';
+
+import 'dialog_button.dart';
class DeleteConfirmationDialog extends StatelessWidget {
const DeleteConfirmationDialog(
@@ -13,7 +18,7 @@ class DeleteConfirmationDialog extends StatelessWidget {
Future show() async {
return await showGeneralDialog(
- transitionDuration: Duration(milliseconds: 600),
+ transitionDuration: const Duration(milliseconds: 600),
barrierColor: Colors.black.withOpacity(0.75),
barrierLabel: '',
context: context,
@@ -25,40 +30,7 @@ class DeleteConfirmationDialog extends StatelessWidget {
child: DeleteConfirmationDialog(context),
);
},
- pageBuilder: (_, __, ___) => SizedBox(),
- );
- }
-
- // TODO(Mais): Refactor
- button(
- {required String text,
- BoxBorder? border,
- required BorderRadiusGeometry radius,
- Color? textColor,
- Function? onPress}) {
- return Expanded(
- flex: 1,
- child: Container(
- decoration: BoxDecoration(border: border),
- child: RaisedButton(
- shape: RoundedRectangleBorder(borderRadius: radius),
- elevation: 0.0,
- focusElevation: 0.0,
- highlightElevation: 0.0,
- hoverElevation: 0.0,
- splashColor: Colors.white24,
- highlightColor: Colors.white24,
- onPressed: onPress as void Function()?,
- child: Text(
- text,
- style: TextStyle(
- color: textColor,
- fontWeight: FontWeight.w300,
- fontSize: 12,
- ),
- ),
- ),
- ),
+ pageBuilder: (_, __, ___) => const SizedBox(),
);
}
@@ -66,59 +38,63 @@ class DeleteConfirmationDialog extends StatelessWidget {
Widget build(BuildContext context) {
return Dialog(
elevation: 6.0,
+ shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15.0)),
child: Container(
- constraints: BoxConstraints(maxHeight: 130),
+ constraints: const BoxConstraints(maxHeight: 130),
child: Stack(
children: [
Container(
- padding: EdgeInsets.all(10),
+ padding: const EdgeInsets.all(10),
alignment: Alignment.center,
child: Column(
children: [
Text(
- 'تأكيد الحذف',
+ Strings.confirmDeleteTitle,
style: TextStyle(
color: Theme.of(context).primaryColor,
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
- Text('هل أنت مُتأكد من رغبتك في الحذف؟')
+ const Text(Strings.confirmDeleteContent)
],
),
),
Align(
alignment: Alignment.bottomCenter,
child: Container(
- constraints: BoxConstraints.expand(height: 40),
+ constraints: const BoxConstraints.expand(height: 40),
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.center,
children: [
- button(
- text: 'حذف',
- border: Border(
- left: BorderSide(width: 0.5, color: Colors.white),
- ),
- radius: BorderRadius.only(
- bottomRight: Radius.circular(15),
- ),
- textColor: Colors.lightBlue[100],
- onPress: () async {
- Navigator.of(context).pop(true);
- }),
- button(
- text: 'إلغاء',
- border: Border(
- right: BorderSide(width: 0.5, color: Colors.white),
- ),
- radius: BorderRadius.only(
- bottomLeft: Radius.circular(15),
- ),
- textColor: Colors.white,
- onPress: () {
- Navigator.of(context).pop(false);
- }),
+ DialogButton(
+ label: 'حذف',
+ border: Border(
+ left: BorderSide(
+ width: 0.5, color: Theme.of(context).cardColor),
+ ),
+ onPressed: () async {
+ Navigator.of(context).pop(true);
+ },
+ radius: const BorderRadius.only(
+ bottomRight: Radius.circular(15),
+ ),
+ ),
+ DialogButton(
+ label: 'إلغاء',
+ textColor: Colors.white,
+ border: Border(
+ right: BorderSide(
+ width: 0.5, color: Theme.of(context).cardColor),
+ ),
+ onPressed: () async {
+ Navigator.of(context).pop(false);
+ },
+ radius: const BorderRadius.only(
+ bottomLeft: Radius.circular(15),
+ ),
+ ),
],
),
),
@@ -126,7 +102,6 @@ class DeleteConfirmationDialog extends StatelessWidget {
],
),
),
- shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15.0)),
);
}
}
diff --git a/lib/components/dialog_button.dart b/lib/components/dialog_button.dart
new file mode 100644
index 0000000..58c7ecc
--- /dev/null
+++ b/lib/components/dialog_button.dart
@@ -0,0 +1,43 @@
+import 'package:flutter/material.dart';
+
+class DialogButton extends StatelessWidget {
+ const DialogButton({
+ Key? key,
+ required this.label,
+ this.onPressed,
+ this.radius,
+ this.border,
+ this.textColor,
+ }) : super(key: key);
+
+ final Function()? onPressed;
+ final String label;
+ final BorderRadiusGeometry? radius;
+ final BoxBorder? border;
+ final Color? textColor;
+
+ @override
+ Widget build(BuildContext context) {
+ return Expanded(
+ flex: 1,
+ child: Container(
+ decoration: BoxDecoration(border: border),
+ child: ElevatedButton(
+ style: radius == null
+ ? null
+ : ElevatedButton.styleFrom(
+ shape: RoundedRectangleBorder(borderRadius: radius!),
+ ),
+ onPressed: onPressed,
+ child: DefaultTextStyle.merge(
+ child: Text(
+ label,
+ textScaleFactor: 1,
+ style: TextStyle(color: textColor),
+ ),
+ ),
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/components/editable_text_max_length_highlighter.dart b/lib/components/editable_text_max_length_highlighter.dart
new file mode 100644
index 0000000..71661b5
--- /dev/null
+++ b/lib/components/editable_text_max_length_highlighter.dart
@@ -0,0 +1,33 @@
+import 'package:flutter/material.dart';
+
+class TextFieldMaxLengthHighlighter extends TextEditingController {
+ TextFieldMaxLengthHighlighter({String? text, this.maxLength})
+ : super(text: text);
+
+ final int? maxLength;
+
+ @override
+ TextSpan buildTextSpan(
+ {required BuildContext context,
+ TextStyle? style,
+ required bool withComposing}) {
+ String allowedText = text;
+ String nonAllowedText = '';
+
+ if (maxLength != null && allowedText.length >= maxLength!) {
+ allowedText = text.substring(0, maxLength!);
+ nonAllowedText = text.substring(maxLength!);
+ }
+
+ return TextSpan(style: style, children: [
+ TextSpan(text: allowedText),
+ if (nonAllowedText.isNotEmpty)
+ TextSpan(
+ text: nonAllowedText,
+ style: style?.copyWith(
+ color: Colors.red,
+ ),
+ ),
+ ]);
+ }
+}
diff --git a/lib/components/fav_action.dart b/lib/components/fav_action.dart
index 8bfa27f..0f6516c 100644
--- a/lib/components/fav_action.dart
+++ b/lib/components/fav_action.dart
@@ -31,7 +31,7 @@ class _FavActionState extends State {
crossFadeState: widget.item.isFav
? CrossFadeState.showSecond
: CrossFadeState.showFirst,
- duration: Duration(milliseconds: 500),
+ duration: const Duration(milliseconds: 500),
),
);
}
diff --git a/lib/components/glowing_stars.dart b/lib/components/glowing_stars.dart
index 2d4330c..5e7c839 100644
--- a/lib/components/glowing_stars.dart
+++ b/lib/components/glowing_stars.dart
@@ -1,12 +1,11 @@
import 'package:flutter/material.dart';
import 'package:noor/constants/images.dart';
-import 'package:provider/provider.dart';
-
-import 'package:noor/exports/controllers.dart' show ThemeModel;
enum StarType { circle, normal }
class GlowingStars extends StatelessWidget {
+ const GlowingStars({Key? key}) : super(key: key);
+
@override
Widget build(BuildContext context) {
double width = MediaQuery.of(context).size.width;
@@ -15,7 +14,7 @@ class GlowingStars extends StatelessWidget {
height: 140,
width: width,
child: Stack(
- children: [
+ children: const [
//star 0
Positioned(
top: 10,
@@ -191,7 +190,7 @@ class GlowingStars extends StatelessWidget {
}
class Star extends StatefulWidget {
- Star({
+ const Star({
Key? key,
required this.size,
required this.radius,
@@ -218,8 +217,8 @@ class _StarState extends State with SingleTickerProviderStateMixin {
void initState() {
controller = AnimationController(
vsync: this,
- duration: Duration(seconds: 2),
- reverseDuration: Duration(seconds: 2))
+ duration: const Duration(seconds: 2),
+ reverseDuration: const Duration(seconds: 2))
..forward()
..repeat(reverse: true);
animationStar =
@@ -248,8 +247,6 @@ class _StarState extends State with SingleTickerProviderStateMixin {
@override
Widget build(BuildContext context) {
- final ThemeModel themeProvider = context.watch();
-
return ValueListenableBuilder?>(
valueListenable: opacity,
builder:
diff --git a/lib/components/home-card.dart b/lib/components/home_card.dart
similarity index 86%
rename from lib/components/home-card.dart
rename to lib/components/home_card.dart
index 906d3c6..18421a5 100644
--- a/lib/components/home-card.dart
+++ b/lib/components/home_card.dart
@@ -3,13 +3,15 @@ import 'package:flutter/material.dart';
class HomeCard extends StatelessWidget {
const HomeCard({
+ Key? key,
required this.image,
required this.page,
required this.tag,
- });
+ }) : super(key: key);
final String image;
final Widget page;
final String tag;
+
@override
Widget build(BuildContext context) {
return OpenContainer(
@@ -18,25 +20,25 @@ class HomeCard extends StatelessWidget {
return page;
},
openShape: const RoundedRectangleBorder(
- borderRadius: const BorderRadius.all(
+ borderRadius: BorderRadius.all(
Radius.circular(20),
),
),
tappable: false,
closedColor: Colors.transparent,
closedShape: const RoundedRectangleBorder(
- borderRadius: const BorderRadius.all(
+ borderRadius: BorderRadius.all(
Radius.circular(20),
),
),
closedElevation: 0.0,
openElevation: 0.0,
- transitionDuration: Duration(milliseconds: 400),
+ transitionDuration: const Duration(milliseconds: 400),
closedBuilder: (BuildContext _, VoidCallback openContainer) {
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
- boxShadow: [
+ boxShadow: const [
BoxShadow(
blurRadius: 8,
color: Colors.black12,
@@ -44,7 +46,7 @@ class HomeCard extends StatelessWidget {
],
),
width: double.infinity,
- margin: EdgeInsets.symmetric(horizontal: 20, vertical: 8),
+ margin: const EdgeInsets.symmetric(horizontal: 20, vertical: 8),
child: GestureDetector(
child: SizedBox(
height: MediaQuery.of(context).size.height * 0.25,
diff --git a/lib/components/image_button.dart b/lib/components/image_button.dart
index 38fdc13..85da6bd 100644
--- a/lib/components/image_button.dart
+++ b/lib/components/image_button.dart
@@ -23,8 +23,7 @@ class ImageButton extends StatelessWidget {
height: height,
child: Material(
type: MaterialType.transparency,
- shape:
- RoundedRectangleBorder(borderRadius: new BorderRadius.circular(25)),
+ shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(25)),
child: SizedBox(
child: InkWell(
highlightColor: Colors.black.withOpacity(0.1),
diff --git a/lib/components/list_item.dart b/lib/components/list_item.dart
index 78f9ab7..c045222 100644
--- a/lib/components/list_item.dart
+++ b/lib/components/list_item.dart
@@ -18,7 +18,7 @@ class ListItem extends StatelessWidget {
child: Material(
color: Theme.of(context).brightness == Brightness.light
? Colors.grey[100]
- : Color(0xff33477f).withOpacity(0.2),
+ : const Color(0xff33477f).withOpacity(0.2),
borderRadius: BorderRadius.circular(8),
clipBehavior: Clip.hardEdge,
child: ListTile(
@@ -33,7 +33,7 @@ class ListItem extends StatelessWidget {
size: 22,
color: Theme.of(context).brightness == Brightness.light
? Colors.grey[300]
- : Color(0xff33477f),
+ : const Color(0xff33477f),
),
leading: Image.asset(
icon,
@@ -41,14 +41,14 @@ class ListItem extends StatelessWidget {
),
),
),
- margin: EdgeInsets.only(
+ margin: const EdgeInsets.only(
top: 5.0,
bottom: 5.0,
left: 10.0,
right: 10.0,
),
),
- Padding(
+ const Padding(
child: Divider(),
padding: EdgeInsets.symmetric(horizontal: 30.0),
)
diff --git a/lib/components/logo.dart b/lib/components/logo.dart
index a54fb9c..0542638 100644
--- a/lib/components/logo.dart
+++ b/lib/components/logo.dart
@@ -4,7 +4,7 @@ import 'package:noor/exports/controllers.dart' show ThemeModel;
import 'package:provider/provider.dart';
class NoorLogo extends StatelessWidget {
- const NoorLogo(this.size);
+ const NoorLogo({Key? key, required this.size}) : super(key: key);
final double size;
@override
diff --git a/lib/components/noor_icons.dart b/lib/components/noor_icons.dart
index 8257912..15da3bd 100644
--- a/lib/components/noor_icons.dart
+++ b/lib/components/noor_icons.dart
@@ -11,7 +11,7 @@
/// fonts:
/// - asset: fonts/NoorIcons.ttf
///
-///
+///
///
import 'package:flutter/widgets.dart';
@@ -24,22 +24,22 @@ class NoorIcons {
static const IconData fav = IconData(0xe801, fontFamily: _kFontFam);
static const IconData settings = IconData(0xe802, fontFamily: _kFontFam);
static const IconData counter = IconData(0xe803, fontFamily: _kFontFam);
- static const IconData font_type = IconData(0xe804, fontFamily: _kFontFam);
- static const IconData erase_counter = IconData(0xe805, fontFamily: _kFontFam);
- static const IconData font_size = IconData(0xe807, fontFamily: _kFontFam);
+ static const IconData fontType = IconData(0xe804, fontFamily: _kFontFam);
+ static const IconData eraseCounter = IconData(0xe805, fontFamily: _kFontFam);
+ static const IconData fontSize = IconData(0xe807, fontFamily: _kFontFam);
static const IconData tashkeel = IconData(0xe808, fontFamily: _kFontFam);
- static const IconData auto_jump = IconData(0xe809, fontFamily: _kFontFam);
+ static const IconData autoJump = IconData(0xe809, fontFamily: _kFontFam);
static const IconData vibrate = IconData(0xe80a, fontFamily: _kFontFam);
static const IconData press = IconData(0xe80b, fontFamily: _kFontFam);
static const IconData done = IconData(0xe80c, fontFamily: _kFontFam);
- static const IconData morning_noti = IconData(0xe80d, fontFamily: _kFontFam);
- static const IconData night_noti = IconData(0xe80e, fontFamily: _kFontFam);
- static const IconData night_mode = IconData(0xe80f, fontFamily: _kFontFam);
- static const IconData light_mode = IconData(0xe810, fontFamily: _kFontFam);
+ static const IconData morningNoti = IconData(0xe80d, fontFamily: _kFontFam);
+ static const IconData nightNoti = IconData(0xe80e, fontFamily: _kFontFam);
+ static const IconData nightMode = IconData(0xe80f, fontFamily: _kFontFam);
+ static const IconData lightMode = IconData(0xe810, fontFamily: _kFontFam);
static const IconData share = IconData(0xe812, fontFamily: _kFontFam);
static const IconData rate = IconData(0xe813, fontFamily: _kFontFam);
static const IconData email = IconData(0xe815, fontFamily: _kFontFam);
- static const IconData system_mode = IconData(0xe816, fontFamily: _kFontFam);
+ static const IconData systemMode = IconData(0xe816, fontFamily: _kFontFam);
static const IconData back = IconData(0xe817, fontFamily: _kFontFam);
static const IconData all = IconData(0xe818, fontFamily: _kFontFam);
static const IconData sunnah = IconData(0xe819, fontFamily: _kFontFam);
diff --git a/lib/components/noor_settings_icons.dart b/lib/components/noor_settings_icons.dart
index 5e02ce9..b98c75e 100644
--- a/lib/components/noor_settings_icons.dart
+++ b/lib/components/noor_settings_icons.dart
@@ -13,6 +13,8 @@
///
///
///
+// ignore_for_file: constant_identifier_names
+
import 'package:flutter/widgets.dart';
class NoorSettingsIcons {
diff --git a/lib/constants/categories.dart b/lib/constants/categories.dart
index e3fcd26..3f25565 100644
--- a/lib/constants/categories.dart
+++ b/lib/constants/categories.dart
@@ -1,10 +1,10 @@
-enum NoorCategory { ATHKAR, QURAAN, SUNNAH, RUQIYA, MYAD3YAH, ALLAHNAME }
+enum NoorCategory { athkar, quraan, sunnah, ruqiya, myad3yah, allahname }
const Map categoryTitle = {
- NoorCategory.ATHKAR: 'الأذكار',
- NoorCategory.QURAAN: 'أدعية من القرآن الكريم',
- NoorCategory.SUNNAH: 'أدعية من السنة النبوية',
- NoorCategory.RUQIYA: 'الرقية الشرعية',
- NoorCategory.MYAD3YAH: 'أدعيتي',
- NoorCategory.ALLAHNAME: 'أسماء الله الحسنى',
+ NoorCategory.athkar: 'الأذكار',
+ NoorCategory.quraan: 'أدعية من القرآن الكريم',
+ NoorCategory.sunnah: 'أدعية من السنة النبوية',
+ NoorCategory.ruqiya: 'الرقية الشرعية',
+ NoorCategory.myad3yah: 'أدعيتي',
+ NoorCategory.allahname: 'أسماء الله الحسنى',
};
diff --git a/lib/constants/colors.dart b/lib/constants/colors.dart
new file mode 100644
index 0000000..ed22c18
--- /dev/null
+++ b/lib/constants/colors.dart
@@ -0,0 +1,22 @@
+class NoorColors {
+ static LightModeColors get light => LightModeColors();
+ static DarkModeColors get dark => DarkModeColors();
+
+ final int primary = 0xff6db7e5;
+ final int subhaListItemBg = 0;
+ final int subhaLockBg = 0;
+}
+
+class DarkModeColors extends NoorColors {
+ @override
+ int get subhaListItemBg => 0xff1D274C;
+ @override
+ int get subhaLockBg => 0xff375089;
+}
+
+class LightModeColors extends NoorColors {
+ @override
+ int get subhaListItemBg => 0xffffffff;
+ @override
+ int get subhaLockBg => 0xffb3b3b3;
+}
diff --git a/lib/constants/icons.dart b/lib/constants/icons.dart
index 3ac4451..ced0a39 100644
--- a/lib/constants/icons.dart
+++ b/lib/constants/icons.dart
@@ -6,6 +6,12 @@ class NoorIcons {
static String subha = 'assets/icons/bottom-nav/${prefix}subha.svg';
static String settings = 'assets/icons/bottom-nav/${prefix}settings.svg';
+ // Subha
+ static String subhaList = 'assets/icons/${prefix}subha_list.svg';
+ static String subhaReset = 'assets/icons/${prefix}subha_reset.svg';
+ static String subhaLock = 'assets/icons/${prefix}subha_lock.svg';
+
+ // Settings
static String fontType = 'assets/icons/settings/${prefix}font-type.svg';
static String fontSize = 'assets/icons/settings/${prefix}font-size.svg';
static String tashkeel = 'assets/icons/settings/${prefix}tashkeel.svg';
diff --git a/lib/constants/images.dart b/lib/constants/images.dart
index 8a4acd0..43dff83 100644
--- a/lib/constants/images.dart
+++ b/lib/constants/images.dart
@@ -1,6 +1,6 @@
import 'package:noor/env_config.dart';
-class Images {
+abstract class Images {
static LightAppImages get light => LightAppImages();
static DarkAppImages get dark => DarkAppImages();
@@ -21,6 +21,7 @@ class Images {
final String igButton = '';
final String myAd3yahBg = '';
final String addMyAd3yah = '';
+ final String subhaBg = '';
// Bellow images aren't tied to theme mode
// So they can be static and accessed directly
@@ -73,60 +74,98 @@ class Images {
}
}
-class LightAppImages extends Images {
- final String logo = 'assets/images/${prefix}logo-light.svg';
+class LightAppImages implements Images {
+ @override
+ String get logo => 'assets/images/${prefix}logo-light.svg';
// Categories icons
- final String athkarTitleIcon = 'assets/icons/titles/${prefix}athkar.png';
- final String quraanTitleIcon = 'assets/icons/titles/${prefix}quraan.png';
- final String sunnahTitleIcon = 'assets/icons/titles/${prefix}sunnah.png';
- final String ruqyaTitleIcon = 'assets/icons/titles/${prefix}ruqiya.png';
- final String myAd3yahTitleIcon = 'assets/icons/titles/${prefix}myAd3yah.png';
- final String allahNamesTitleIcon =
+ @override
+ String get athkarTitleIcon => 'assets/icons/titles/${prefix}athkar.png';
+ @override
+ String get quraanTitleIcon => 'assets/icons/titles/${prefix}quraan.png';
+ @override
+ String get sunnahTitleIcon => 'assets/icons/titles/${prefix}sunnah.png';
+ @override
+ String get ruqyaTitleIcon => 'assets/icons/titles/${prefix}ruqiya.png';
+ @override
+ String get myAd3yahTitleIcon => 'assets/icons/titles/${prefix}myAd3yah.png';
+ @override
+ String get allahNamesTitleIcon =>
'assets/icons/titles/${prefix}allah-names.png';
// Home assets
- final String homeHeader = 'assets/images/home-header/header-light.png';
- final String athkarCard =
- 'assets/images/home-cards/light/${prefix}Athkar.png';
- final String ad3yahCard =
- 'assets/images/home-cards/light/${prefix}Ad3yah.png';
- final String allahNamesCard =
+ @override
+ String get homeHeader => 'assets/images/home-header/header-light.png';
+ @override
+ String get athkarCard => 'assets/images/home-cards/light/${prefix}Athkar.png';
+ @override
+ String get ad3yahCard => 'assets/images/home-cards/light/${prefix}Ad3yah.png';
+ @override
+ String get allahNamesCard =>
'assets/images/home-cards/light/${prefix}AllahNames.png';
// Backgrounds
- final String noAd3yah = 'assets/images/backgrounds/NoAd3yah.png';
- final String noAd3yahFav = 'assets/images/backgrounds/NoAd3yahFav.png';
- final String myAd3yahBg = 'assets/images/backgrounds/${prefix}myAd3yahBg.svg';
+ @override
+ String get noAd3yah => 'assets/images/backgrounds/NoAd3yah.png';
+ @override
+ String get noAd3yahFav => 'assets/images/backgrounds/NoAd3yahFav.png';
+ @override
+ String get myAd3yahBg => 'assets/images/backgrounds/${prefix}myAd3yahBg.svg';
// Buttons
- final String twitterButton = 'assets/images/social-buttons/twitter-light.png';
- final String igButton = 'assets/images/social-buttons/ig-light.png';
- final String addMyAd3yah = 'assets/icons/${prefix}addDo3aa.png';
+ @override
+ String get twitterButton => 'assets/images/social-buttons/twitter-light.png';
+ @override
+ String get igButton => 'assets/images/social-buttons/ig-light.png';
+ @override
+ String get addMyAd3yah => 'assets/icons/${prefix}addDo3aa.png';
+
+ @override
+ String get subhaBg => 'assets/images/backgrounds/SubhaLightBg.svg';
}
-class DarkAppImages extends Images {
- final String logo = 'assets/images/${prefix}logo-dark.svg';
+class DarkAppImages implements Images {
+ @override
+ String get logo => 'assets/images/${prefix}logo-dark.svg';
// Categories icons
- final String athkarTitleIcon = 'assets/icons/titles/${prefix}athkar-dark.png';
- final String quraanTitleIcon = 'assets/icons/titles/${prefix}quraan-dark.png';
- final String sunnahTitleIcon = 'assets/icons/titles/${prefix}sunnah-dark.png';
- final String ruqyaTitleIcon = 'assets/icons/titles/${prefix}ruqiya-dark.png';
- final String myAd3yahTitleIcon =
+ @override
+ String get athkarTitleIcon => 'assets/icons/titles/${prefix}athkar-dark.png';
+ @override
+ String get quraanTitleIcon => 'assets/icons/titles/${prefix}quraan-dark.png';
+ @override
+ String get sunnahTitleIcon => 'assets/icons/titles/${prefix}sunnah-dark.png';
+ @override
+ String get ruqyaTitleIcon => 'assets/icons/titles/${prefix}ruqiya-dark.png';
+ @override
+ String get myAd3yahTitleIcon =>
'assets/icons/titles/${prefix}myAd3yah-dark.png';
- final String allahNamesTitleIcon =
+ @override
+ String get allahNamesTitleIcon =>
'assets/icons/titles/${prefix}allah-names-dark.png';
// Home assets
- final String homeHeader = 'assets/images/home-header/header-dark.png';
- final String athkarCard = 'assets/images/home-cards/dark/${prefix}Athkar.png';
- final String ad3yahCard = 'assets/images/home-cards/dark/${prefix}Ad3yah.png';
- final String allahNamesCard =
+ @override
+ String get homeHeader => 'assets/images/home-header/header-dark.png';
+ @override
+ String get athkarCard => 'assets/images/home-cards/dark/${prefix}Athkar.png';
+ @override
+ String get ad3yahCard => 'assets/images/home-cards/dark/${prefix}Ad3yah.png';
+ @override
+ String get allahNamesCard =>
'assets/images/home-cards/dark/${prefix}AllahNames.png';
// Backgrounds
- final String noAd3yah = 'assets/images/backgrounds/NoAd3yahNight.png';
- final String noAd3yahFav = 'assets/images/backgrounds/NoAd3yahFavNight.png';
- final String myAd3yahBg =
+ @override
+ String get noAd3yah => 'assets/images/backgrounds/NoAd3yahNight.png';
+ @override
+ String get noAd3yahFav => 'assets/images/backgrounds/NoAd3yahFavNight.png';
+ @override
+ String get myAd3yahBg =>
'assets/images/backgrounds/${prefix}myAd3yahBgDark.svg';
// Buttons
- final String twitterButton = 'assets/images/social-buttons/twitter-dark.png';
- final String igButton = 'assets/images/social-buttons/ig-dark.png';
- final String addMyAd3yah = 'assets/icons/${prefix}addDo3aa.png';
+ @override
+ String get twitterButton => 'assets/images/social-buttons/twitter-dark.png';
+ @override
+ String get igButton => 'assets/images/social-buttons/ig-dark.png';
+ @override
+ String get addMyAd3yah => 'assets/icons/${prefix}addDo3aa.png';
+
+ @override
+ String get subhaBg => 'assets/images/backgrounds/SubhaDarkBg.svg';
}
diff --git a/lib/constants/strings.dart b/lib/constants/strings.dart
new file mode 100644
index 0000000..a5ddbaa
--- /dev/null
+++ b/lib/constants/strings.dart
@@ -0,0 +1,11 @@
+class Strings {
+ static const shareText =
+ 'يضمُّ تطبيق نُور العديد من الأذكار والأدعية الواردة في كتاب حصن المسلم.'
+ ' كما يحتوي التطبيق على أدعية من القرآن الكريم والسنة النبوية. والعديد من المميزات. '
+ '\n https://play.google.com/store/apps/details?id=com.noor.sa';
+ static const shareSubject = 'تطبيق نُور';
+ static const noorThekrDefault =
+ 'قال تعالى: ﴿فَاذكُروني أَذكُركُم ﴾ [البقرة: ١٥٢]';
+ static const confirmDeleteContent = 'هل أنت مُتأكد من رغبتك في الحذف؟';
+ static const confirmDeleteTitle = 'تأكيد الحذف';
+}
diff --git a/lib/constants/theme.dart b/lib/constants/theme.dart
index 9e509aa..4e3d215 100644
--- a/lib/constants/theme.dart
+++ b/lib/constants/theme.dart
@@ -1,13 +1,17 @@
import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'package:noor/constants/colors.dart';
-const double kContentFontSize = 16.0;
+const kContentFontSize = 16.0;
+const viewPadding = 15.0;
ThemeData lightTheme() => ThemeData(
brightness: Brightness.light,
- appBarTheme: AppBarTheme(brightness: Brightness.light),
+ appBarTheme:
+ const AppBarTheme(systemOverlayStyle: SystemUiOverlayStyle.light),
fontFamily: 'SST Arabic',
- primaryColor: Color(0xff6db7e5),
- pageTransitionsTheme: PageTransitionsTheme(
+ primaryColor: Color(NoorColors.light.primary),
+ pageTransitionsTheme: const PageTransitionsTheme(
builders: {
TargetPlatform.android: FadeUpwardsPageTransitionsBuilder(),
},
@@ -15,73 +19,114 @@ ThemeData lightTheme() => ThemeData(
unselectedWidgetColor: Colors.grey[300],
canvasColor: Colors.white,
dividerColor: Colors.grey[300],
- accentColor: Color(0xff6f85d5),
- dialogTheme: DialogTheme(backgroundColor: Colors.white),
+ dialogTheme: const DialogTheme(backgroundColor: Colors.white),
highlightColor: Colors.black.withOpacity(0.1),
splashColor: Colors.black.withOpacity(0.1),
+ selectedRowColor: const Color(0xffB3B3FF),
textTheme: TextTheme(
- bodyText1: TextStyle(
+ bodyText1: const TextStyle(
fontSize: 16,
height: 1.6,
color: Colors.black,
fontWeight: FontWeight.normal,
),
- subtitle1: TextStyle(
+ subtitle1: const TextStyle(
color: Color(0xff6f85d5),
fontWeight: FontWeight.bold,
fontSize: 14,
),
- headline1: TextStyle(
+ subtitle2: TextStyle(
+ fontSize: 16,
+ height: 1.5,
+ color: Colors.lightBlue[100],
+ fontWeight: FontWeight.bold,
+ ),
+ headline1: const TextStyle(
fontSize: 16,
height: 1.5,
color: Color(0xff6f85d5),
fontWeight: FontWeight.bold,
),
- headline2: TextStyle(
+ headline2: const TextStyle(
fontSize: 16,
height: 1.5,
color: Colors.white,
),
- button: TextStyle(
+ button: const TextStyle(
fontSize: 14,
color: Color(0xff6f85d5),
height: 1,
),
),
+ elevatedButtonTheme: ElevatedButtonThemeData(
+ style: ButtonStyle(
+ elevation: MaterialStateProperty.all(0.0),
+ backgroundColor: MaterialStateProperty.resolveWith(
+ (Set states) {
+ if (states.contains(MaterialState.disabled)) {
+ return const Color(0xff6f85d5).withOpacity(0.7);
+ }
+ return const Color(0xff6f85d5);
+ },
+ ),
+ foregroundColor: MaterialStateProperty.resolveWith(
+ (Set states) {
+ return (states.contains(MaterialState.disabled))
+ ? Colors.white30
+ : Colors.lightBlue[100];
+ },
+ ),
+ textStyle: MaterialStateProperty.all(
+ const TextStyle(
+ fontFamily: 'SST Arabic',
+ fontWeight: FontWeight.w600,
+ fontSize: 12,
+ height: 1,
+ ),
+ ),
+ overlayColor: MaterialStateProperty.all(Colors.white24),
+ ),
+ ),
scrollbarTheme: ScrollbarThemeData(
- radius: Radius.circular(5),
+ radius: const Radius.circular(5),
thumbColor: MaterialStateProperty.all(Colors.grey[300]),
),
iconTheme: IconThemeData(color: Colors.grey[400], size: 30),
inputDecorationTheme: InputDecorationTheme(
fillColor: Colors.grey[300],
filled: true,
- hintStyle: TextStyle(color: Colors.grey),
+ hintStyle: const TextStyle(color: Colors.grey),
),
- buttonColor: Color(0xff6f85d5),
cardColor: Colors.grey[200],
+ colorScheme: ColorScheme.fromSwatch().copyWith(
+ secondary: const Color(0xff6f85d5),
+ brightness: Brightness.light,
+ outline: const Color(0xff6f85d5),
+ ),
);
ThemeData darkTheme() => ThemeData(
brightness: Brightness.dark,
- appBarTheme: AppBarTheme(brightness: Brightness.dark),
+ appBarTheme:
+ const AppBarTheme(systemOverlayStyle: SystemUiOverlayStyle.dark),
fontFamily: 'SST Arabic',
- primaryColor: Color(0xff6db7e5),
- pageTransitionsTheme: PageTransitionsTheme(
+ primaryColor: Color(NoorColors.dark.primary),
+ selectedRowColor: const Color(0xff33477F),
+ pageTransitionsTheme: const PageTransitionsTheme(
builders: {
TargetPlatform.android: FadeUpwardsPageTransitionsBuilder(),
},
),
- canvasColor: Color(0xff10122C),
- dividerColor: Color(0xff3C387B),
- iconTheme: IconThemeData(color: Color(0xff3C387B), size: 30),
+ canvasColor: const Color(0xff10122C),
+ dividerColor: const Color(0xff3C387B),
+ iconTheme: const IconThemeData(color: Color(0xff3C387B), size: 30),
unselectedWidgetColor: Colors.grey[300],
- inputDecorationTheme: InputDecorationTheme(
+ inputDecorationTheme: const InputDecorationTheme(
fillColor: Colors.white24,
filled: true,
hintStyle: TextStyle(color: Colors.white38),
),
- textTheme: TextTheme(
+ textTheme: const TextTheme(
bodyText1: TextStyle(
fontSize: 16,
height: 1.6,
@@ -93,6 +138,12 @@ ThemeData darkTheme() => ThemeData(
fontWeight: FontWeight.bold,
fontSize: 14,
),
+ subtitle2: TextStyle(
+ fontSize: 16,
+ height: 1.5,
+ color: Color(0xff6f85d5),
+ fontWeight: FontWeight.bold,
+ ),
headline1: TextStyle(
fontSize: 16,
height: 1.5,
@@ -110,16 +161,48 @@ ThemeData darkTheme() => ThemeData(
height: 1,
),
),
- accentColor: Colors.white,
- buttonColor: Color(0xff6f85d5),
+ elevatedButtonTheme: ElevatedButtonThemeData(
+ style: ButtonStyle(
+ elevation: MaterialStateProperty.all(0.0),
+ backgroundColor: MaterialStateProperty.resolveWith(
+ (Set states) {
+ if (states.contains(MaterialState.disabled)) {
+ return const Color(0xff6f85d5).withOpacity(0.6);
+ }
+ return const Color(0xff6f85d5);
+ },
+ ),
+ foregroundColor: MaterialStateProperty.resolveWith(
+ (Set states) {
+ return (states.contains(MaterialState.disabled))
+ ? Colors.white30
+ : Colors.lightBlue[100];
+ },
+ ),
+ textStyle: MaterialStateProperty.all(
+ const TextStyle(
+ fontFamily: 'SST Arabic',
+ fontWeight: FontWeight.w600,
+ fontSize: 12,
+ height: 1,
+ ),
+ ),
+ overlayColor: MaterialStateProperty.all(Colors.white10),
+ ),
+ ),
splashColor: Colors.black.withOpacity(0.1),
- highlightColor: Color(0xff3C387B).withOpacity(0.5),
- dialogTheme: DialogTheme(backgroundColor: Color(0xff1B2349)),
- cardColor: Color(0xff10122C),
+ highlightColor: const Color(0xff3C387B).withOpacity(0.5),
+ dialogTheme: const DialogTheme(backgroundColor: Color(0xff1B2349)),
+ cardColor: const Color(0xff10122C),
scrollbarTheme: ScrollbarThemeData(
- radius: Radius.circular(5),
+ radius: const Radius.circular(5),
thumbColor: MaterialStateProperty.all(
- Color(0xff3C387B).withOpacity(0.5),
+ const Color(0xff3C387B).withOpacity(0.5),
),
),
+ colorScheme: ColorScheme.fromSwatch().copyWith(
+ secondary: Colors.white,
+ brightness: Brightness.dark,
+ outline: const Color(0xff6f85d5),
+ ),
);
diff --git a/lib/constants/titles.dart b/lib/constants/titles.dart
index ca61193..aba9cad 100644
--- a/lib/constants/titles.dart
+++ b/lib/constants/titles.dart
@@ -4,5 +4,3 @@ class Titles {
static const String ruqya = 'الرقية الشرعية';
static const String myAd3yah = 'أدعيتي';
}
-
-
diff --git a/lib/controllers/data_controller.dart b/lib/controllers/data_controller.dart
index b54b746..b1382e6 100644
--- a/lib/controllers/data_controller.dart
+++ b/lib/controllers/data_controller.dart
@@ -10,7 +10,7 @@ import 'package:noor/exports/services.dart'
class DataController {
static Future init() async {
- final List data = await JsonService.init();
+ final List data = await JsonService.instance.init();
final DataModel dataModel = GetIt.I();
if (dataModel.athkar.isEmpty) {
int section = 0;
@@ -44,9 +44,9 @@ class DataController {
if (dataModel.quraan.isEmpty) {
dataModel.quraan = data[1]
.map((dynamic e) {
- e['category'] = NoorCategory.QURAAN;
+ e['category'] = NoorCategory.quraan;
e['ribbon'] = Ribbon.ribbon2;
- e['sectionName'] = categoryTitle[NoorCategory.QURAAN];
+ e['sectionName'] = categoryTitle[NoorCategory.quraan];
return Doaa.fromMap(e);
})
@@ -56,9 +56,9 @@ class DataController {
if (dataModel.sunnah.isEmpty) {
dataModel.sunnah = data[2]
.map((dynamic e) {
- e['category'] = NoorCategory.SUNNAH;
+ e['category'] = NoorCategory.sunnah;
e['ribbon'] = Ribbon.ribbon3;
- e['sectionName'] = categoryTitle[NoorCategory.SUNNAH];
+ e['sectionName'] = categoryTitle[NoorCategory.sunnah];
return Doaa.fromMap(e);
})
@@ -69,8 +69,8 @@ class DataController {
dataModel.ruqiya = data[3]
.map((dynamic e) {
e['ribbon'] = Ribbon.ribbon4;
- e['category'] = NoorCategory.RUQIYA;
- e['sectionName'] = categoryTitle[NoorCategory.RUQIYA];
+ e['category'] = NoorCategory.ruqiya;
+ e['sectionName'] = categoryTitle[NoorCategory.ruqiya];
return Doaa.fromMap(e);
})
@@ -101,7 +101,7 @@ class DataController {
updateFavList();
}
- await Future.delayed(Duration(seconds: 1));
+ await Future.delayed(const Duration(seconds: 1));
return DataController();
}
@@ -178,7 +178,7 @@ class DataController {
// Update underlying fav prefs list for persistency
SharedPrefsService.putStringList('fav', favPrefs);
- if (element.category == NoorCategory.MYAD3YAH) {
+ if (element.category == NoorCategory.myad3yah) {
await DBService.db.update(element);
}
@@ -195,7 +195,7 @@ class DataController {
// Update underlying fav prefs list for persistency
SharedPrefsService.putStringList('fav', favPrefs);
- if (element.category == NoorCategory.MYAD3YAH) {
+ if (element.category == NoorCategory.myad3yah) {
await DBService.db.update(element);
}
diff --git a/lib/exports/components.dart b/lib/exports/components.dart
index bf3941d..ffe5632 100644
--- a/lib/exports/components.dart
+++ b/lib/exports/components.dart
@@ -3,7 +3,7 @@ export 'package:noor/components/allah_names_title.dart';
export 'package:noor/components/athkar_card.dart';
export 'package:noor/components/athkar_title.dart';
export 'package:noor/components/bottom_nav.dart';
-export 'package:noor/components/home-card.dart';
+export 'package:noor/components/home_card.dart';
export 'package:noor/components/close_button.dart';
export 'package:noor/components/delete_dialog.dart';
export 'package:noor/components/custom_scroll_bhaviour.dart';
diff --git a/lib/exports/constants.dart b/lib/exports/constants.dart
index 5e7674e..aeb300b 100644
--- a/lib/exports/constants.dart
+++ b/lib/exports/constants.dart
@@ -6,3 +6,4 @@ export 'package:noor/constants/theme.dart';
export 'package:noor/constants/titles.dart';
export 'package:noor/constants/categories.dart';
export 'package:noor/constants/icons.dart';
+export 'package:noor/constants/strings.dart';
diff --git a/lib/exports/controllers.dart b/lib/exports/controllers.dart
index c1d4217..b8498f9 100644
--- a/lib/exports/controllers.dart
+++ b/lib/exports/controllers.dart
@@ -1,3 +1,3 @@
export 'package:noor/controllers/data_controller.dart';
export 'package:noor/models/settings.dart';
-export 'package:noor/models/theme_model.dart';
+export 'package:noor/models/theme.dart';
diff --git a/lib/exports/pages.dart b/lib/exports/pages.dart
index 9e96db4..8aa0af3 100644
--- a/lib/exports/pages.dart
+++ b/lib/exports/pages.dart
@@ -1,19 +1,21 @@
export 'package:noor/pages/root.dart';
export 'package:noor/pages/splash.dart';
-export 'package:noor/pages/tabs/1_home/home.dart';
+export 'package:noor/pages/tabs/page_1_home/home.dart';
-export 'package:noor/pages/tabs/1_home/athkar.dart';
-export 'package:noor/pages/tabs/1_home/athkar_expanded.dart';
+export 'package:noor/pages/tabs/page_1_home/athkar.dart';
+export 'package:noor/pages/tabs/page_1_home/athkar_expanded.dart';
-export 'package:noor/pages/tabs/1_home/ad3yah.dart';
-export 'package:noor/pages/tabs/1_home/ad3yah_expanded.dart';
+export 'package:noor/pages/tabs/page_1_home/ad3yah.dart';
+export 'package:noor/pages/tabs/page_1_home/ad3yah_expanded.dart';
-export 'package:noor/pages/tabs/1_home/allah_names.dart';
-export 'package:noor/pages/tabs/1_home/allah_names_expanded.dart';
+export 'package:noor/pages/tabs/page_1_home/allah_names.dart';
+export 'package:noor/pages/tabs/page_1_home/allah_names_expanded.dart';
-export 'package:noor/pages/tabs/1_home/my_ad3yah.dart';
+export 'package:noor/pages/tabs/page_1_home/my_ad3yah.dart';
-export 'package:noor/pages/tabs/2_fav.dart';
-export 'package:noor/pages/tabs/3_counter.dart';
-export 'package:noor/pages/tabs/4_settings.dart';
\ No newline at end of file
+export 'package:noor/pages/tabs/page_2_fav.dart';
+
+export 'package:noor/pages/tabs/page_3_counter/counter_main_view.dart';
+
+export 'package:noor/pages/tabs/page_4_settings.dart';
diff --git a/lib/exports/services.dart b/lib/exports/services.dart
index 824859f..34e4008 100644
--- a/lib/exports/services.dart
+++ b/lib/exports/services.dart
@@ -1,4 +1,4 @@
export 'package:noor/services/db.dart';
export 'package:noor/services/fcm.dart';
export 'package:noor/services/json.dart';
-export 'package:noor/services/prefs.dart';
\ No newline at end of file
+export 'package:noor/services/prefs.dart';
diff --git a/lib/main.dart b/lib/main.dart
index fdec655..cd04f7f 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -8,6 +8,7 @@ import 'package:noor/exports/models.dart' show DataModel;
import 'package:noor/exports/services.dart'
show DBService, SharedPrefsService, FCMService;
import 'package:noor/exports/models.dart' show SettingsModel;
+import 'package:noor/pages/tabs/page_3_counter/counter_view_model.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
@@ -20,6 +21,8 @@ void main() async {
GetIt.I.registerSingleton(DataModel());
GetIt.I.registerSingleton(SettingsModel());
GetIt.I.registerSingletonAsync(() => DataController.init());
+ GetIt.I
+ .registerSingletonAsync(() => CounterViewModel.init());
- runApp(NoorApp());
+ runApp(const NoorApp());
}
diff --git a/lib/models/allah_name.dart b/lib/models/allah_name.dart
index d77e0a7..54906d0 100644
--- a/lib/models/allah_name.dart
+++ b/lib/models/allah_name.dart
@@ -6,7 +6,7 @@ class AllahName {
late final String text;
final String sectionName = 'أسماء الله الحسنى';
final String ribbon = Ribbon.ribbon6;
- final NoorCategory category = NoorCategory.ALLAHNAME;
+ final NoorCategory category = NoorCategory.allahname;
late bool isFav;
late final int section;
late final bool inApp;
diff --git a/lib/models/data.dart b/lib/models/data.dart
index e02785f..bd8028b 100644
--- a/lib/models/data.dart
+++ b/lib/models/data.dart
@@ -4,7 +4,6 @@ import 'package:noor/models/doaa.dart';
import 'package:noor/models/thekr.dart';
class DataModel extends ChangeNotifier {
-
List _athkar = [];
List _quraan = [];
List _sunnah = [];
diff --git a/lib/models/thekr.dart b/lib/models/thekr.dart
index a96f4f7..e3307b7 100644
--- a/lib/models/thekr.dart
+++ b/lib/models/thekr.dart
@@ -11,7 +11,7 @@ class Thekr {
late final int counter;
- final NoorCategory category = NoorCategory.ATHKAR;
+ final NoorCategory category = NoorCategory.athkar;
final String ribbon = Ribbon.ribbon1;
Thekr._(
diff --git a/lib/models/theme_model.dart b/lib/models/theme.dart
similarity index 71%
rename from lib/models/theme_model.dart
rename to lib/models/theme.dart
index fc14cf1..e506942 100644
--- a/lib/models/theme_model.dart
+++ b/lib/models/theme.dart
@@ -2,6 +2,8 @@ import 'package:flutter/material.dart';
import 'package:noor/exports/constants.dart' show Images;
import 'package:noor/exports/services.dart' show SharedPrefsService;
+import '../constants/colors.dart';
+
class ThemeModel with ChangeNotifier {
String _userTheme = SharedPrefsService.getString('theme');
@@ -42,4 +44,22 @@ class ThemeModel with ChangeNotifier {
}
}
}
+
+ NoorColors get colors {
+ switch (userTheme) {
+ case 'dark_theme':
+ return NoorColors.dark;
+ case 'light_theme':
+ return NoorColors.light;
+ default:
+ {
+ switch (brightness) {
+ case Brightness.dark:
+ return NoorColors.dark;
+ default:
+ return NoorColors.light;
+ }
+ }
+ }
+ }
}
diff --git a/lib/pages/root.dart b/lib/pages/root.dart
index 3afd4e0..8b9f18c 100644
--- a/lib/pages/root.dart
+++ b/lib/pages/root.dart
@@ -4,27 +4,28 @@ import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:noor/exports/components.dart' show BottomNav;
import 'package:noor/exports/pages.dart'
- show Home, Favorite, CounterPage, Settings, AthkarList;
+ show Home, Favorite, CounterView, Settings, AthkarList;
class RootHome extends StatefulWidget {
- RootHome({Key? key}) : super(key: key);
+ const RootHome({Key? key}) : super(key: key);
+ @override
_RootHomeState createState() => _RootHomeState();
}
class _RootHomeState extends State
with TickerProviderStateMixin, WidgetsBindingObserver {
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
- new FlutterLocalNotificationsPlugin();
+ FlutterLocalNotificationsPlugin();
String? payload;
@override
void initState() {
super.initState();
AndroidInitializationSettings initializationSettingsAndroid =
- new AndroidInitializationSettings('ic_notification');
+ const AndroidInitializationSettings('ic_notification');
IOSInitializationSettings initializationSettingsIOS =
- IOSInitializationSettings();
+ const IOSInitializationSettings();
InitializationSettings initializationSettings = InitializationSettings(
android: initializationSettingsAndroid, iOS: initializationSettingsIOS);
flutterLocalNotificationsPlugin.initialize(initializationSettings,
@@ -35,11 +36,11 @@ class _RootHomeState extends State
setState(() {
this.payload = payload;
});
- print(payload);
+
Navigator.push(
context,
- new MaterialPageRoute(
- builder: (BuildContext context) => new AthkarList(
+ MaterialPageRoute(
+ builder: (BuildContext context) => AthkarList(
index: payload == 'الصباح' ? 0 : 26,
),
),
@@ -57,12 +58,12 @@ class _RootHomeState extends State
},
),
body: PageView(
- physics: NeverScrollableScrollPhysics(),
+ physics: const NeverScrollableScrollPhysics(),
controller: controller,
- children: [
+ children: const [
Home(),
Favorite(),
- CounterPage(),
+ CounterView(),
Settings(),
],
),
diff --git a/lib/pages/splash.dart b/lib/pages/splash.dart
index 824ec11..6c129e5 100644
--- a/lib/pages/splash.dart
+++ b/lib/pages/splash.dart
@@ -5,7 +5,7 @@ import 'package:noor/exports/pages.dart' show RootHome;
import 'package:noor/exports/components.dart' show NoorLogo;
class SplashScreen extends StatefulWidget {
- SplashScreen({Key? key}) : super(key: key);
+ const SplashScreen({Key? key}) : super(key: key);
@override
_SplashScreenState createState() => _SplashScreenState();
@@ -15,7 +15,7 @@ class _SplashScreenState extends State {
double logoOpacity = 0.0;
@override
void initState() {
- Future.delayed(Duration(milliseconds: 300), () {
+ Future.delayed(const Duration(milliseconds: 300), () {
setState(() {
logoOpacity = 1.0;
});
@@ -26,10 +26,10 @@ class _SplashScreenState extends State {
@override
void didChangeDependencies() async {
await Future.value(GetIt.I.allReady());
- await Future.delayed(Duration(milliseconds: 500));
+ await Future.delayed(const Duration(milliseconds: 500));
Navigator.of(context).pushReplacement(
MaterialPageRoute(
- builder: (_) => RootHome(),
+ builder: (_) => const RootHome(),
),
);
@@ -41,9 +41,9 @@ class _SplashScreenState extends State {
return Material(
child: Center(
child: AnimatedOpacity(
- duration: Duration(milliseconds: 500),
+ duration: const Duration(milliseconds: 500),
opacity: logoOpacity,
- child: NoorLogo(80),
+ child: const NoorLogo(size: 80),
),
),
);
diff --git a/lib/pages/tabs/3_counter.dart b/lib/pages/tabs/3_counter.dart
deleted file mode 100644
index baabf47..0000000
--- a/lib/pages/tabs/3_counter.dart
+++ /dev/null
@@ -1,136 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:flutter/services.dart';
-import 'package:provider/provider.dart';
-
-import 'package:noor/exports/components.dart' show NoorIcons;
-import 'package:noor/exports/services.dart' show SharedPrefsService;
-import 'package:noor/exports/utils.dart' show ToArabicNumbers;
-import 'package:noor/exports/controllers.dart' show SettingsModel;
-
-class CounterPage extends StatefulWidget {
- const CounterPage({Key? key}) : super(key: key);
- @override
- _CounterPageState createState() => _CounterPageState();
-}
-
-class _CounterPageState extends State {
- int counter = SharedPrefsService.getInt('counter');
-
- void incrementCounter() {
- final SettingsModel settings = context.read();
-
- setState(() {
- counter++;
- });
-
- SharedPrefsService.putInt('counter', counter);
-
- if (settings.vibrateCounter) {
- if (counter % 100 == 0) {
- switch (settings.vibrationHunderds) {
- case 'strong':
- HapticFeedback.lightImpact();
- break;
- case 'light':
- HapticFeedback.heavyImpact();
- break;
- case 'none':
- break;
- default:
- HapticFeedback.lightImpact();
- }
- } else {
- switch (settings.vibrationClickCounter) {
- case 'strong':
- HapticFeedback.lightImpact();
- break;
- case 'light':
- HapticFeedback.heavyImpact();
- break;
- case 'none':
- break;
- default:
- HapticFeedback.lightImpact();
- }
- }
- }
- }
-
- void resetCounter() {
- setState(() {
- counter = 0;
- });
- SharedPrefsService.putInt('counter', counter);
- }
-
- LinearGradient lightModeBG = LinearGradient(
- colors: [
- Color(0xff5554B0),
- Color(0xff6F86D6),
- ],
- stops: [0.1, 0.9],
- begin: Alignment.bottomRight,
- end: Alignment.topLeft,
- );
-
- LinearGradient darkModeBG = LinearGradient(
- colors: [
- Color(0xff161A3A),
- Color(0xff161A3A),
- ],
- stops: [0.7, 0.3],
- begin: Alignment.bottomRight,
- end: Alignment.topLeft,
- );
- @override
- Widget build(BuildContext context) {
- return Scaffold(
- body: GestureDetector(
- onTap: incrementCounter,
- child: Container(
- width: MediaQuery.of(context).size.width,
- height: MediaQuery.of(context).size.height,
- decoration: BoxDecoration(
- gradient: Theme.of(context).brightness == Brightness.dark
- ? darkModeBG
- : lightModeBG),
- child: Stack(
- children: [
- Positioned(
- top: 40,
- left: 20,
- child: IconButton(
- icon: Icon(
- NoorIcons.erase_counter,
- color: Colors.white,
- size: 40,
- ),
- onPressed: resetCounter,
- ),
- ),
- Align(
- alignment: Alignment.center,
- child: AnimatedSwitcher(
- transitionBuilder:
- (Widget child, Animation animation) {
- return FadeTransition(child: child, opacity: animation);
- },
- duration: Duration(milliseconds: 250),
- child: Text(
- '$counter'.arabicDigit(),
- key: ValueKey(counter),
- style: TextStyle(
- color: Colors.white,
- fontSize: 55,
- fontWeight: FontWeight.bold,
- ),
- ),
- ),
- )
- ],
- ),
- ),
- ),
- );
- }
-}
diff --git a/lib/pages/tabs/1_home/ad3yah.dart b/lib/pages/tabs/page_1_home/ad3yah.dart
similarity index 87%
rename from lib/pages/tabs/1_home/ad3yah.dart
rename to lib/pages/tabs/page_1_home/ad3yah.dart
index c84126e..d62e49e 100644
--- a/lib/pages/tabs/1_home/ad3yah.dart
+++ b/lib/pages/tabs/page_1_home/ad3yah.dart
@@ -1,5 +1,4 @@
import 'package:flutter/material.dart';
-import 'package:flutter/rendering.dart';
import 'package:provider/provider.dart';
import 'package:noor/exports/pages.dart' show Ad3yahList, MyAd3yah;
@@ -8,18 +7,20 @@ import 'package:noor/exports/components.dart' show NoorCloseButton, ListItem;
import 'package:noor/exports/controllers.dart' show ThemeModel;
class Ad3yah extends StatefulWidget {
- const Ad3yah();
+ const Ad3yah({Key? key}) : super(key: key);
+ @override
_Ad3yahState createState() => _Ad3yahState();
}
class _Ad3yahState extends State with SingleTickerProviderStateMixin {
- ScrollController scrollController = new ScrollController();
+ ScrollController scrollController = ScrollController();
int index = 0;
double currentScroll = 0;
double maxHeight = 180;
late Animation animation;
late AnimationController controller;
+ @override
initState() {
super.initState();
@@ -67,7 +68,7 @@ class _Ad3yahState extends State with SingleTickerProviderStateMixin {
},
),
),
- Positioned(
+ const Positioned(
left: 10.0, top: 40.0, child: NoorCloseButton(size: 35)),
],
),
@@ -75,29 +76,29 @@ class _Ad3yahState extends State with SingleTickerProviderStateMixin {
builder: (_, ThemeModel theme, __) {
return Expanded(
child: ListView(
- padding: EdgeInsets.only(top: 15.0),
- physics: AlwaysScrollableScrollPhysics(),
+ padding: const EdgeInsets.only(top: 15.0),
+ physics: const AlwaysScrollableScrollPhysics(),
controller: scrollController,
children: [
Ad3yahTitleCard(
title: Titles.quraan,
icon: theme.images.quraanTitleIcon,
- category: NoorCategory.QURAAN,
+ category: NoorCategory.quraan,
),
Ad3yahTitleCard(
title: Titles.sunnah,
icon: theme.images.sunnahTitleIcon,
- category: NoorCategory.SUNNAH,
+ category: NoorCategory.sunnah,
),
Ad3yahTitleCard(
title: Titles.ruqya,
icon: theme.images.ruqyaTitleIcon,
- category: NoorCategory.RUQIYA,
+ category: NoorCategory.ruqiya,
),
Ad3yahTitleCard(
title: Titles.myAd3yah,
icon: theme.images.myAd3yahTitleIcon,
- category: NoorCategory.MYAD3YAH,
+ category: NoorCategory.myad3yah,
),
],
),
@@ -128,10 +129,10 @@ class Ad3yahTitleCard extends StatelessWidget {
icon: icon,
title: title,
onTap: () {
- if (category == NoorCategory.MYAD3YAH) {
+ if (category == NoorCategory.myad3yah) {
Navigator.of(context).push(
MaterialPageRoute(
- builder: (_) => MyAd3yah(),
+ builder: (_) => const MyAd3yah(),
fullscreenDialog: true,
),
);
diff --git a/lib/pages/tabs/1_home/ad3yah_expanded.dart b/lib/pages/tabs/page_1_home/ad3yah_expanded.dart
similarity index 91%
rename from lib/pages/tabs/1_home/ad3yah_expanded.dart
rename to lib/pages/tabs/page_1_home/ad3yah_expanded.dart
index ef06df3..aa8d9fd 100644
--- a/lib/pages/tabs/1_home/ad3yah_expanded.dart
+++ b/lib/pages/tabs/page_1_home/ad3yah_expanded.dart
@@ -15,6 +15,7 @@ class Ad3yahList extends StatefulWidget {
}) : super(key: key);
final int index;
final NoorCategory category;
+ @override
_Ad3yahListState createState() => _Ad3yahListState();
}
@@ -45,7 +46,7 @@ class _Ad3yahListState extends State {
bottom: false,
child: Container(
width: double.infinity,
- margin: EdgeInsets.symmetric(horizontal: 20, vertical: 10),
+ margin: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
@@ -55,7 +56,8 @@ class _Ad3yahListState extends State {
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.headline1,
),
- NoorCloseButton(color: Theme.of(context).accentColor),
+ NoorCloseButton(
+ color: Theme.of(context).colorScheme.secondary),
],
),
),
@@ -63,7 +65,7 @@ class _Ad3yahListState extends State {
Expanded(
child: Scrollbar(
child: ScrollablePositionedList.builder(
- physics: AlwaysScrollableScrollPhysics(),
+ physics: const AlwaysScrollableScrollPhysics(),
itemCount: data[widget.category.index - 1].length,
initialScrollIndex: widget.index,
itemScrollController: controller,
diff --git a/lib/pages/tabs/1_home/allah_names.dart b/lib/pages/tabs/page_1_home/allah_names.dart
similarity index 92%
rename from lib/pages/tabs/1_home/allah_names.dart
rename to lib/pages/tabs/page_1_home/allah_names.dart
index 36396ab..1d5c361 100644
--- a/lib/pages/tabs/1_home/allah_names.dart
+++ b/lib/pages/tabs/page_1_home/allah_names.dart
@@ -16,7 +16,7 @@ class AllahNames extends StatefulWidget {
class _AllahNamesState extends State
with SingleTickerProviderStateMixin {
- ScrollController scrollController = new ScrollController();
+ final scrollController = ScrollController();
double currentScroll = 0;
double maxHeight = 180;
@@ -25,6 +25,7 @@ class _AllahNamesState extends State
int index = 0;
+ @override
initState() {
super.initState();
@@ -73,7 +74,7 @@ class _AllahNamesState extends State
},
),
),
- Positioned(
+ const Positioned(
left: 10.0, top: 40.0, child: NoorCloseButton(size: 35)),
],
),
@@ -83,14 +84,14 @@ class _AllahNamesState extends State
return Expanded(
child: Scrollbar(
child: ListView.builder(
- padding: EdgeInsets.symmetric(vertical: 10),
- physics: AlwaysScrollableScrollPhysics(),
+ padding: const EdgeInsets.symmetric(vertical: 10),
+ physics: const AlwaysScrollableScrollPhysics(),
itemCount: allahNames.length,
controller: scrollController,
itemBuilder: (BuildContext context, int index) {
final AllahName title = allahNames[index];
return ListItem(
- title: '${title.name}',
+ title: title.name,
icon: images.allahNamesTitleIcon,
onTap: () {
Navigator.of(context).push(
diff --git a/lib/pages/tabs/1_home/allah_names_expanded.dart b/lib/pages/tabs/page_1_home/allah_names_expanded.dart
similarity index 91%
rename from lib/pages/tabs/1_home/allah_names_expanded.dart
rename to lib/pages/tabs/page_1_home/allah_names_expanded.dart
index f8ed7ce..31e3cc3 100644
--- a/lib/pages/tabs/1_home/allah_names_expanded.dart
+++ b/lib/pages/tabs/page_1_home/allah_names_expanded.dart
@@ -8,7 +8,6 @@ import 'package:noor/exports/components.dart'
show
NoorCloseButton,
CardTemplate,
- NoorIcons,
NameTitleCard,
FavAction,
CopyAction,
@@ -20,6 +19,7 @@ class AllahNamesList extends StatefulWidget {
this.index = 0,
}) : super(key: key);
final int index;
+ @override
_AllahNamesListState createState() => _AllahNamesListState();
}
@@ -41,11 +41,11 @@ class _AllahNamesListState extends State
listener.itemPositions.addListener(changeAppBar);
});
- animationController = new AnimationController(vsync: this);
+ animationController = AnimationController(vsync: this);
animation = Tween(begin: 0.0, end: 0.1).animate(
CurvedAnimation(parent: animationController, curve: Curves.elasticIn),
);
- controller = new ItemScrollController();
+ controller = ItemScrollController();
}
@override
@@ -94,11 +94,11 @@ class _AllahNamesListState extends State
bottom: false,
child: Container(
width: double.infinity,
- margin: EdgeInsets.symmetric(horizontal: 20, vertical: 10),
+ margin: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
- SizedBox(width: 45),
+ const SizedBox(width: 45),
ChangeNotifierProvider>.value(
value: pagePosition,
child: Consumer>(
@@ -118,7 +118,8 @@ class _AllahNamesListState extends State
},
),
),
- NoorCloseButton(color: Theme.of(context).accentColor),
+ NoorCloseButton(
+ color: Theme.of(context).colorScheme.secondary),
],
),
),
@@ -126,13 +127,13 @@ class _AllahNamesListState extends State
Expanded(
child: Scrollbar(
child: ScrollablePositionedList.builder(
- physics: AlwaysScrollableScrollPhysics(),
+ physics: const AlwaysScrollableScrollPhysics(),
itemScrollController: controller,
itemPositionsListener: listener,
itemCount: allahNames.length,
addAutomaticKeepAlives: true,
initialScrollIndex: widget.index,
- padding: EdgeInsets.only(bottom: 20),
+ padding: const EdgeInsets.only(bottom: 20),
itemBuilder: (_, int index) {
final AllahName name = allahNames[index];
@@ -150,7 +151,7 @@ class _AllahNamesListState extends State
crossAxisAlignment: CrossAxisAlignment.start,
children: [
CardText(text: textList[0] + '.'),
- SizedBox(height: 10),
+ const SizedBox(height: 10),
CardText(text: textList[1] + '.'),
],
),
@@ -213,17 +214,18 @@ class ReferenceList extends StatelessWidget {
bottom: false,
child: Container(
width: double.infinity,
- margin: EdgeInsets.symmetric(horizontal: 20, vertical: 10),
+ margin: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
- SizedBox(width: 45),
+ const SizedBox(width: 45),
Text(
name.name,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.headline1,
),
- NoorCloseButton(color: Theme.of(context).accentColor),
+ NoorCloseButton(
+ color: Theme.of(context).colorScheme.secondary),
],
),
),
diff --git a/lib/pages/tabs/1_home/athkar.dart b/lib/pages/tabs/page_1_home/athkar.dart
similarity index 90%
rename from lib/pages/tabs/1_home/athkar.dart
rename to lib/pages/tabs/page_1_home/athkar.dart
index 66568a9..da07cf0 100644
--- a/lib/pages/tabs/1_home/athkar.dart
+++ b/lib/pages/tabs/page_1_home/athkar.dart
@@ -9,18 +9,21 @@ import 'package:noor/exports/pages.dart' show AthkarList;
import 'package:noor/exports/components.dart' show ListItem, NoorCloseButton;
class AthkarPage extends StatefulWidget {
- const AthkarPage();
+ const AthkarPage({Key? key}) : super(key: key);
+
+ @override
_AthkarPageState createState() => _AthkarPageState();
}
class _AthkarPageState extends State
with SingleTickerProviderStateMixin {
- ScrollController scrollController = new ScrollController();
+ ScrollController scrollController = ScrollController();
double currentScroll = 0;
double maxHeight = 180;
late Animation animation;
late AnimationController controller;
+ @override
initState() {
super.initState();
DBService.db.initDB();
@@ -70,7 +73,8 @@ class _AthkarPageState extends State
},
),
),
- Positioned(left: 10.0, top: 40.0, child: NoorCloseButton(size: 35)),
+ const Positioned(
+ left: 10.0, top: 40.0, child: NoorCloseButton(size: 35)),
],
),
Expanded(
@@ -83,17 +87,17 @@ class _AthkarPageState extends State
return Scrollbar(
controller: scrollController,
child: ListView.builder(
- physics: AlwaysScrollableScrollPhysics(),
+ physics: const AlwaysScrollableScrollPhysics(),
itemCount: athkarTitles.length,
controller: scrollController,
- padding: EdgeInsets.only(top: 10),
+ padding: const EdgeInsets.only(top: 10),
itemBuilder: (BuildContext context, int index) {
final Thekr title = athkarTitles[index];
final int position = model.athkar.indexOf(title);
return title.isTitle
? ListItem(
- title: '${title.text}',
+ title: title.text,
icon: images.athkarTitleIcon,
onTap: () {
Navigator.push(
diff --git a/lib/pages/tabs/1_home/athkar_expanded.dart b/lib/pages/tabs/page_1_home/athkar_expanded.dart
similarity index 91%
rename from lib/pages/tabs/1_home/athkar_expanded.dart
rename to lib/pages/tabs/page_1_home/athkar_expanded.dart
index 2ec78bd..54957de 100644
--- a/lib/pages/tabs/1_home/athkar_expanded.dart
+++ b/lib/pages/tabs/page_1_home/athkar_expanded.dart
@@ -11,6 +11,7 @@ import 'package:noor/exports/components.dart'
class AthkarList extends StatefulWidget {
const AthkarList({Key? key, required this.index}) : super(key: key);
final int index;
+ @override
_AthkarListState createState() => _AthkarListState();
}
@@ -30,14 +31,14 @@ class _AthkarListState extends State
void initState() {
super.initState();
pagePosition = widget.index;
- animationController = new AnimationController(vsync: this);
+ animationController = AnimationController(vsync: this);
animation = Tween(begin: 0.0, end: 0.1).animate(
CurvedAnimation(
parent: animationController,
curve: Curves.elasticIn,
),
);
- controller = new ItemScrollController();
+ controller = ItemScrollController();
WidgetsBinding.instance!.addPostFrameCallback((_) {
listener.itemPositions.addListener(changeAppBar);
});
@@ -90,10 +91,10 @@ class _AthkarListState extends State
settings.autoJump &&
counter.position == 0 &&
!context.read().athkar[index + 1].isTitle) {
- Future.delayed(Duration(milliseconds: 500)).then(
+ Future.delayed(const Duration(milliseconds: 500)).then(
(_) {
controller.scrollTo(
- duration: Duration(milliseconds: 800),
+ duration: const Duration(milliseconds: 800),
curve: Curves.easeInOutCubic,
index: index + 1);
},
@@ -112,7 +113,7 @@ class _AthkarListState extends State
bottom: false,
child: Container(
width: double.infinity,
- margin: EdgeInsets.symmetric(horizontal: 20, vertical: 10),
+ margin: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
@@ -134,7 +135,8 @@ class _AthkarListState extends State
},
),
),
- NoorCloseButton(color: Theme.of(context).accentColor),
+ NoorCloseButton(
+ color: Theme.of(context).colorScheme.secondary),
],
),
),
@@ -155,15 +157,15 @@ class _AthkarListState extends State
builder: (_, List countersList, __) {
return Scrollbar(
child: ScrollablePositionedList.builder(
- key: ValueKey('list'),
- physics: AlwaysScrollableScrollPhysics(),
+ key: const ValueKey('list'),
+ physics: const AlwaysScrollableScrollPhysics(),
itemScrollController: controller,
itemPositionsListener: listener,
itemCount: athkar.length,
addAutomaticKeepAlives: true,
initialScrollIndex: widget.index,
minCacheExtent: 900,
- padding: EdgeInsets.only(bottom: 20),
+ padding: const EdgeInsets.only(bottom: 20),
itemBuilder: (_, int index) {
final Thekr thekr = athkar[index];
if (thekr.isTitle) {
diff --git a/lib/pages/tabs/1_home/home.dart b/lib/pages/tabs/page_1_home/home.dart
similarity index 60%
rename from lib/pages/tabs/1_home/home.dart
rename to lib/pages/tabs/page_1_home/home.dart
index ef2c5a7..d363eb1 100644
--- a/lib/pages/tabs/1_home/home.dart
+++ b/lib/pages/tabs/page_1_home/home.dart
@@ -17,19 +17,24 @@ import 'package:noor/exports/controllers.dart' show ThemeModel;
import 'package:noor/exports/services.dart' show SharedPrefsService;
import 'package:noor/exports/models.dart' show AllahName, DataModel;
+export 'package:noor/pages/tabs/page_1_home/ad3yah_expanded.dart';
+export 'package:noor/pages/tabs/page_1_home/allah_names_expanded.dart';
+export 'package:noor/pages/tabs/page_1_home/athkar_expanded.dart';
+export 'package:noor/pages/tabs/page_1_home/my_ad3yah.dart';
+
class Home extends StatefulWidget {
- Home({
+ const Home({
Key? key,
}) : super(key: key);
+ @override
_HomeState createState() => _HomeState();
}
-class _HomeState extends State
- with TickerProviderStateMixin, AutomaticKeepAliveClientMixin {
+class _HomeState extends State with AutomaticKeepAliveClientMixin {
bool isWriting = false;
- FocusNode _focusNode = new FocusNode();
- TextEditingController _searchController = new TextEditingController();
+ final _focusNode = FocusNode();
+ final _searchController = TextEditingController();
List results = [];
List title = [];
@@ -53,12 +58,11 @@ class _HomeState extends State
Future displayNotification(
String title, String body, String payload) async {
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
- new FlutterLocalNotificationsPlugin();
+ FlutterLocalNotificationsPlugin();
AndroidNotificationDetails androidPlatformChannelSpecifics =
- AndroidNotificationDetails(
+ const AndroidNotificationDetails(
'RC',
'RC notification',
- 'RC channel',
importance: Importance.max,
priority: Priority.high,
);
@@ -144,86 +148,83 @@ class _HomeState extends State
},
child: Scaffold(
resizeToAvoidBottomInset: false,
- body: SafeArea(
- top: false,
- child: Column(
- children: [
- AnimatedHeader(
- focusNode: _focusNode,
- isWriting: isWriting,
- ),
- Expanded(
- flex: isWriting ? 0 : 1,
- child: SingleChildScrollView(
- child: Column(
- children: [
- if (_focusNode.hasFocus) const SizedBox(height: 10),
- searchBar(),
- const SizedBox(height: 10),
- if (!isWriting)
- Stack(
- children: [
- if (!isWriting)
- Column(
- children: [
- HomeCard(
- page: const AthkarPage(),
- image: images.athkarCard,
- tag: 'athkar',
- ),
- HomeCard(
- page: const Ad3yah(),
- image: images.ad3yahCard,
- tag: 'ad3yah',
- ),
- HomeCard(
- page: const AllahNames(),
- image: images.allahNamesCard,
- tag: 'allah names',
- ),
- ],
- ),
- Visibility(
- visible: !isWriting && _focusNode.hasFocus,
- child: AnimatedOpacity(
- duration: Duration(milliseconds: 400),
- opacity: _focusNode.hasFocus ? 1.0 : 0.0,
- child: GestureDetector(
- onTap: () {
- if (_focusNode.hasFocus) {
- _searchController.clear();
- FocusScope.of(context)
- .requestFocus(new FocusNode());
- setState(() {
- isWriting = false;
- });
- }
- },
- child: Container(
- color: Colors.transparent,
- height: _focusNode.hasFocus && !isWriting
- ? MediaQuery.of(context).size.height
- : 0,
- ),
+ body: Column(
+ children: [
+ AnimatedHeader(
+ focusNode: _focusNode,
+ isWriting: isWriting,
+ ),
+ Expanded(
+ flex: isWriting ? 0 : 1,
+ child: SingleChildScrollView(
+ child: Column(
+ children: [
+ if (_focusNode.hasFocus) const SizedBox(height: 10),
+ searchBar(),
+ const SizedBox(height: 10),
+ if (!isWriting)
+ Stack(
+ children: [
+ if (!isWriting)
+ Column(
+ children: [
+ HomeCard(
+ page: const AthkarPage(),
+ image: images.athkarCard,
+ tag: 'athkar',
+ ),
+ HomeCard(
+ page: const Ad3yah(),
+ image: images.ad3yahCard,
+ tag: 'ad3yah',
+ ),
+ HomeCard(
+ page: const AllahNames(),
+ image: images.allahNamesCard,
+ tag: 'allah names',
+ ),
+ ],
+ ),
+ Visibility(
+ visible: !isWriting && _focusNode.hasFocus,
+ child: AnimatedOpacity(
+ duration: const Duration(milliseconds: 400),
+ opacity: _focusNode.hasFocus ? 1.0 : 0.0,
+ child: GestureDetector(
+ onTap: () {
+ if (_focusNode.hasFocus) {
+ _searchController.clear();
+ FocusScope.of(context)
+ .requestFocus(FocusNode());
+ setState(() {
+ isWriting = false;
+ });
+ }
+ },
+ child: Container(
+ color: Colors.transparent,
+ height: _focusNode.hasFocus && !isWriting
+ ? MediaQuery.of(context).size.height
+ : 0,
),
),
),
- ],
- ),
- ],
- ),
+ ),
+ ],
+ ),
+ ],
),
),
- if (isWriting)
- Expanded(
- child: SearchResults(
- query: searchWord,
- results: results,
- title: title,
- ),
+ ),
+ if (isWriting)
+ Expanded(
+ child: SearchResults(
+ query: searchWord,
+ results: results,
+ title: title,
),
- ],
- ),
+ ),
+ ],
),
),
);
@@ -231,65 +232,64 @@ class _HomeState extends State
/// Build the search bar widget
Widget searchBar() {
- return SafeArea(
- child: Container(
- padding: EdgeInsets.only(right: 25.0, left: 25.0),
- child: TextField(
- controller: _searchController,
- focusNode: _focusNode,
- onTap: () {
- if (!_focusNode.hasFocus) {
- setState(() {});
- }
- },
- style: TextStyle(
- fontSize: 14,
- color: Theme.of(context).textTheme.bodyText1!.color,
+ return Container(
+ padding: const EdgeInsets.only(right: 25.0, left: 25.0),
+ child: TextField(
+ controller: _searchController,
+ focusNode: _focusNode,
+ onTap: () {
+ if (!_focusNode.hasFocus) {
+ setState(() {});
+ }
+ },
+ style: TextStyle(
+ fontSize: 14,
+ color: Theme.of(context).textTheme.bodyText1!.color,
+ fontWeight: FontWeight.normal,
+ ),
+ decoration: InputDecoration(
+ contentPadding:
+ const EdgeInsets.symmetric(vertical: 0, horizontal: 15),
+ hintText: 'ابحث عن ذكر أو دعاء',
+ hintStyle: const TextStyle(
+ color: Colors.grey,
fontWeight: FontWeight.normal,
),
- decoration: InputDecoration(
- contentPadding: EdgeInsets.symmetric(vertical: 0, horizontal: 15),
- hintText: 'ابحث عن ذكر أو دعاء',
- hintStyle: TextStyle(
- color: Colors.grey,
- fontWeight: FontWeight.normal,
- ),
- prefixIcon: Icon(
- Icons.search,
- color: Theme.of(context).brightness == Brightness.light
- ? Colors.grey
- : Colors.white,
- ),
- suffixIcon: isWriting
- ? IconButton(
- icon: Icon(
- Icons.close,
- color: Theme.of(context).brightness == Brightness.light
- ? Colors.grey
- : Colors.white,
- ),
- onPressed: () {
- _searchController.clear();
- //FocusScope.of(context).requestFocus(new FocusNode());
- // setState(() {
- // isWriting = false;
- // });
- },
- )
- : null,
- focusedBorder: OutlineInputBorder(
- borderSide: BorderSide(color: Colors.transparent, width: 2.0),
- borderRadius: BorderRadius.circular(16.0),
- ),
- filled: true,
- fillColor: Theme.of(context).brightness == Brightness.light
- ? Colors.grey[100]
- : Colors.white12,
- enabledBorder: OutlineInputBorder(
- borderRadius: BorderRadius.circular(16.0),
- borderSide: BorderSide(
- color: Colors.transparent,
- ),
+ prefixIcon: Icon(
+ Icons.search,
+ color: Theme.of(context).brightness == Brightness.light
+ ? Colors.grey
+ : Colors.white,
+ ),
+ suffixIcon: isWriting
+ ? IconButton(
+ icon: Icon(
+ Icons.close,
+ color: Theme.of(context).brightness == Brightness.light
+ ? Colors.grey
+ : Colors.white,
+ ),
+ onPressed: () {
+ _searchController.clear();
+ //FocusScope.of(context).requestFocus(new FocusNode());
+ // setState(() {
+ // isWriting = false;
+ // });
+ },
+ )
+ : null,
+ focusedBorder: OutlineInputBorder(
+ borderSide: const BorderSide(color: Colors.transparent, width: 2.0),
+ borderRadius: BorderRadius.circular(16.0),
+ ),
+ filled: true,
+ fillColor: Theme.of(context).brightness == Brightness.light
+ ? Colors.grey[100]
+ : Colors.white12,
+ enabledBorder: OutlineInputBorder(
+ borderRadius: BorderRadius.circular(16.0),
+ borderSide: const BorderSide(
+ color: Colors.transparent,
),
),
),
@@ -301,13 +301,11 @@ class _HomeState extends State
class AnimatedHeader extends StatefulWidget {
const AnimatedHeader({
Key? key,
- required FocusNode focusNode,
required this.isWriting,
- }) : focusNode = focusNode,
- super(key: key);
+ required this.focusNode,
+ }) : super(key: key);
final FocusNode focusNode;
-
final bool isWriting;
@override
@@ -340,17 +338,17 @@ class _AnimatedHeaderState extends State
_setupCloudAnimation() {
cloudController =
- AnimationController(duration: Duration(seconds: 15), vsync: this)
+ AnimationController(duration: const Duration(seconds: 15), vsync: this)
..forward()
..reverse()
..repeat();
- _topCloudAnim =
- Tween(begin: Offset(3.0, 0.0), end: Offset(-5.5, 0.0))
- .animate(cloudController);
- _bottomCloudAnim =
- Tween(begin: Offset(-5.5, 0.0), end: Offset(3.0, 0.0))
- .animate(cloudController);
+ _topCloudAnim = Tween(
+ begin: const Offset(3.0, 0.0), end: const Offset(-5.5, 0.0))
+ .animate(cloudController);
+ _bottomCloudAnim = Tween(
+ begin: const Offset(-5.5, 0.0), end: const Offset(3.0, 0.0))
+ .animate(cloudController);
}
Future _loadRemoteConfig() async {
@@ -371,8 +369,7 @@ class _AnimatedHeaderState extends State
Provider.of(context, listen: false).images;
return AnimatedSize(
curve: Curves.easeInOutCirc,
- duration: Duration(milliseconds: 300),
- vsync: this,
+ duration: const Duration(milliseconds: 300),
child: Container(
decoration: BoxDecoration(
image: DecorationImage(
@@ -384,7 +381,12 @@ class _AnimatedHeaderState extends State
width: MediaQuery.of(context).size.width,
height: widget.focusNode.hasFocus || widget.isWriting ? 0 : 170,
padding: const EdgeInsets.symmetric(horizontal: 20),
+ margin: EdgeInsets.only(
+ bottom: widget.focusNode.hasFocus
+ ? MediaQuery.of(context).viewPadding.top
+ : 15.0),
child: Stack(
+ alignment: Alignment.center,
children: [
if (Theme.of(context).brightness == Brightness.light)
Positioned(
@@ -407,49 +409,47 @@ class _AnimatedHeaderState extends State
),
),
if (Theme.of(context).brightness == Brightness.dark)
- Align(
+ const Align(
alignment: Alignment.center,
child: GlowingStars(),
),
SafeArea(
- child: Align(
- alignment: Alignment.topCenter,
- child: SizedBox(
- width: MediaQuery.of(context).size.width,
- child: SingleChildScrollView(
- child: Column(
- children: [
- const SizedBox(height: 5),
- SvgPicture.asset(
- 'assets/images/${prefix}logo-dark.svg',
- width: 60,
- ),
- const SizedBox(height: 15),
- ValueListenableBuilder(
- valueListenable: remoteConfigNotifier,
- builder: (_, String value, Widget? child) {
- return AnimatedSwitcher(
- duration: Duration(milliseconds: 500),
- transitionBuilder:
- (Widget child, Animation animation) {
- return FadeTransition(
- child: child, opacity: animation);
- },
- child: Text(
- value,
- key: ValueKey(value),
- textAlign: TextAlign.center,
- style: TextStyle(
- color: Colors.white,
- fontSize: 15,
- height: 1.5,
- ),
+ child: SizedBox(
+ width: MediaQuery.of(context).size.width,
+ height: 120,
+ child: SingleChildScrollView(
+ child: Column(
+ children: [
+ const SizedBox(height: 5),
+ SvgPicture.asset(
+ 'assets/images/${prefix}logo-dark.svg',
+ width: 60,
+ ),
+ const SizedBox(height: 15),
+ ValueListenableBuilder(
+ valueListenable: remoteConfigNotifier,
+ builder: (_, String value, Widget? child) {
+ return AnimatedSwitcher(
+ duration: const Duration(milliseconds: 500),
+ transitionBuilder:
+ (Widget child, Animation animation) {
+ return FadeTransition(
+ child: child, opacity: animation);
+ },
+ child: Text(
+ value,
+ key: ValueKey(value),
+ textAlign: TextAlign.center,
+ style: const TextStyle(
+ color: Colors.white,
+ fontSize: 15,
+ height: 1.5,
),
- );
- },
- ),
- ],
- ),
+ ),
+ );
+ },
+ ),
+ ],
),
),
),
@@ -476,7 +476,7 @@ class SearchResults extends StatefulWidget {
}
String mask(string) {
- var tmp;
+ String tmp;
// for each أ، إ، آ in string, replace with ا
tmp = string.replaceAll(
RegExp(
@@ -548,10 +548,10 @@ class _SearchResultsState extends State {
@override
Widget build(BuildContext context) {
return SizedBox(
- child: widget.results.length == 0
- ? Text('لا توجد نتائج')
+ child: widget.results.isEmpty
+ ? const Text('لا توجد نتائج')
: ListView.builder(
- physics: AlwaysScrollableScrollPhysics(),
+ physics: const AlwaysScrollableScrollPhysics(),
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom),
itemCount: widget.results.length,
@@ -583,7 +583,7 @@ class _SearchResultsState extends State {
),
],
),
- padding: EdgeInsets.symmetric(
+ padding: const EdgeInsets.symmetric(
horizontal: 30.0,
),
),
@@ -601,11 +601,11 @@ class _SearchResultsState extends State {
fontWeight: FontWeight.bold,
fontSize: 12),
),
- padding: EdgeInsets.symmetric(
+ padding: const EdgeInsets.symmetric(
horizontal: 30.0,
),
),
- Divider(),
+ const Divider(),
],
),
);
diff --git a/lib/pages/tabs/1_home/my_ad3yah.dart b/lib/pages/tabs/page_1_home/my_ad3yah.dart
similarity index 84%
rename from lib/pages/tabs/1_home/my_ad3yah.dart
rename to lib/pages/tabs/page_1_home/my_ad3yah.dart
index df6aad5..d6b4784 100644
--- a/lib/pages/tabs/1_home/my_ad3yah.dart
+++ b/lib/pages/tabs/page_1_home/my_ad3yah.dart
@@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';
+import 'package:noor/components/dialog_button.dart';
import 'package:provider/provider.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:reorderables/reorderables.dart';
@@ -18,18 +19,20 @@ import 'package:noor/exports/components.dart'
FavAction;
class MyAd3yah extends StatefulWidget {
- MyAd3yah({Key? key, this.index = 0}) : super(key: key);
+ const MyAd3yah({Key? key, this.index = 0}) : super(key: key);
final int index;
+ @override
_MyAd3yahState createState() => _MyAd3yahState();
}
class _MyAd3yahState extends State with TickerProviderStateMixin {
- TextEditingController _firstController = new TextEditingController();
- TextEditingController _secondController = new TextEditingController();
+ final _firstController = TextEditingController();
+ final _secondController = TextEditingController();
ScrollController? controller;
Widget? animatedWidget;
final GlobalKey listKey = GlobalKey();
+ @override
void initState() {
super.initState();
controller = ScrollController(initialScrollOffset: widget.index * 380.0);
@@ -50,11 +53,11 @@ class _MyAd3yahState extends State with TickerProviderStateMixin {
child: SingleChildScrollView(
child: TextField(
controller: controller,
- style: Theme.of(context).textTheme.body1,
+ style: Theme.of(context).textTheme.bodyText1,
decoration: InputDecoration(
filled: false,
contentPadding:
- EdgeInsets.symmetric(vertical: 12, horizontal: 10.0),
+ const EdgeInsets.symmetric(vertical: 12, horizontal: 10.0),
border: InputBorder.none,
hintText: text,
),
@@ -67,30 +70,13 @@ class _MyAd3yahState extends State with TickerProviderStateMixin {
}
//button design (used in dialoges)
- button({required text, border, required radius, textColor, onPress}) {
- return Expanded(
- flex: 1,
- child: Container(
- decoration: BoxDecoration(border: border),
- child: RaisedButton(
- shape: RoundedRectangleBorder(borderRadius: radius),
- elevation: 0.0,
- focusElevation: 0.0,
- highlightElevation: 0.0,
- hoverElevation: 0.0,
- splashColor: Colors.white24,
- highlightColor: Colors.white24,
- onPressed: onPress,
- child: Text(
- text,
- style: TextStyle(
- color: textColor,
- fontWeight: FontWeight.w300,
- fontSize: 12,
- ),
- ),
- ),
- ),
+ button({required text, border, required radius, textColor, onPressed}) {
+ return DialogButton(
+ label: text,
+ border: border,
+ onPressed: onPressed,
+ radius: radius,
+ textColor: textColor,
);
}
@@ -101,7 +87,7 @@ class _MyAd3yahState extends State with TickerProviderStateMixin {
_secondController.text = data.info;
}
showGeneralDialog(
- transitionDuration: Duration(milliseconds: 600),
+ transitionDuration: const Duration(milliseconds: 600),
barrierDismissible: false,
barrierColor: Colors.black.withOpacity(0.75),
barrierLabel: '',
@@ -116,9 +102,9 @@ class _MyAd3yahState extends State with TickerProviderStateMixin {
decoration: BoxDecoration(
color: Theme.of(context).brightness == Brightness.light
? Colors.white
- : Color(0xff1B2349),
+ : const Color(0xff1B2349),
borderRadius: BorderRadius.circular(15.0)),
- constraints: BoxConstraints(maxHeight: 360),
+ constraints: const BoxConstraints(maxHeight: 360),
child: Stack(
children: [
SingleChildScrollView(
@@ -134,30 +120,30 @@ class _MyAd3yahState extends State with TickerProviderStateMixin {
Align(
alignment: Alignment.bottomCenter,
child: Container(
- constraints: BoxConstraints.expand(height: 40),
+ constraints: const BoxConstraints.expand(height: 40),
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.center,
children: [
button(
text: 'حفظ',
- border: Border(
+ border: const Border(
left: BorderSide(
width: 0.5, color: Colors.white)),
- radius: BorderRadius.only(
+ radius: const BorderRadius.only(
bottomRight: Radius.circular(15)),
textColor: Colors.lightBlue[100],
- onPress: () => onSave(prevDoaa: data),
+ onPressed: () => onSave(prevDoaa: data),
),
button(
text: 'إلغاء',
- border: Border(
+ border: const Border(
right: BorderSide(
width: 0.5, color: Colors.white)),
- radius: BorderRadius.only(
+ radius: const BorderRadius.only(
bottomLeft: Radius.circular(15)),
textColor: Colors.white,
- onPress: onCancel,
+ onPressed: onCancel,
),
],
),
@@ -170,7 +156,7 @@ class _MyAd3yahState extends State with TickerProviderStateMixin {
),
);
},
- pageBuilder: (_, __, ___) => SizedBox(),
+ pageBuilder: (_, __, ___) => const SizedBox(),
);
}
@@ -218,7 +204,7 @@ class _MyAd3yahState extends State with TickerProviderStateMixin {
width: 45,
height: 45,
),
- Text(
+ const Text(
'أدعيتي',
style: TextStyle(
color: Colors.white,
@@ -226,14 +212,14 @@ class _MyAd3yahState extends State with TickerProviderStateMixin {
fontSize: 20,
),
),
- NoorCloseButton(size: 35)
+ const NoorCloseButton(size: 35)
],
),
),
const SizedBox(height: 35),
Expanded(
child: AnimatedSwitcher(
- duration: Duration(milliseconds: 400),
+ duration: const Duration(milliseconds: 400),
child: myAd3yah.isNotEmpty
? Scrollbar(
controller: controller,
@@ -241,7 +227,7 @@ class _MyAd3yahState extends State with TickerProviderStateMixin {
controller: controller,
slivers: [
ReorderableSliverList(
- key: ValueKey('list'),
+ key: const ValueKey('list'),
controller: controller,
buildDraggableFeedback: (_,
BoxConstraints constraints,
diff --git a/lib/pages/tabs/2_fav.dart b/lib/pages/tabs/page_2_fav.dart
similarity index 93%
rename from lib/pages/tabs/2_fav.dart
rename to lib/pages/tabs/page_2_fav.dart
index 0c00f3a..fd65f49 100644
--- a/lib/pages/tabs/2_fav.dart
+++ b/lib/pages/tabs/page_2_fav.dart
@@ -1,18 +1,11 @@
-import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';
import 'package:noor/models/data.dart';
import 'package:provider/provider.dart';
import 'package:reorderables/reorderables.dart';
-import 'package:noor/main.dart';
import 'package:noor/exports/components.dart'
- show
- CardTemplate,
- DeleteConfirmationDialog,
- ImageButton,
- NoorIcons,
- NoorSettingsIcons;
+ show CardTemplate, DeleteConfirmationDialog, ImageButton;
import 'package:noor/exports/models.dart' show AllahName;
import 'package:noor/exports/constants.dart' show Images, NoorCategory;
import 'package:noor/exports/pages.dart'
@@ -22,9 +15,11 @@ import 'package:noor/exports/utils.dart' show backToExactLocation;
import 'package:noor/exports/components.dart' show CardText;
class Favorite extends StatefulWidget {
- Favorite({
+ const Favorite({
Key? key,
}) : super(key: key);
+
+ @override
_FavoriteState createState() => _FavoriteState();
}
@@ -33,7 +28,7 @@ class _FavoriteState extends State
@override
bool get wantKeepAlive => true;
- ScrollController _scrollController = ScrollController();
+ final _scrollController = ScrollController();
List sectionList = [];
List favList = [];
@@ -98,24 +93,24 @@ class _FavoriteState extends State
final int index = tmpList.indexWhere(
(dynamic element) => element.sectionName == item.sectionName);
switch (item.category) {
- case NoorCategory.ATHKAR:
+ case NoorCategory.athkar:
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => AthkarList(index: index),
),
);
break;
- case NoorCategory.MYAD3YAH:
+ case NoorCategory.myad3yah:
Navigator.of(context).push(
MaterialPageRoute(
- builder: (_) => MyAd3yah(),
+ builder: (_) => const MyAd3yah(),
),
);
break;
- case NoorCategory.ALLAHNAME:
+ case NoorCategory.allahname:
Navigator.of(context).push(
MaterialPageRoute(
- builder: (_) => AllahNamesList(),
+ builder: (_) => const AllahNamesList(),
),
);
break;
@@ -161,7 +156,7 @@ class _FavoriteState extends State
margin: const EdgeInsets.symmetric(vertical: 22),
height: 45,
child: ListView.separated(
- padding: EdgeInsets.symmetric(horizontal: 20.0),
+ padding: const EdgeInsets.symmetric(horizontal: 20.0),
separatorBuilder: (_, __) => const SizedBox(width: 10.0),
scrollDirection: Axis.horizontal,
itemCount: Images.favButtonsList.length,
@@ -176,7 +171,7 @@ class _FavoriteState extends State
),
Expanded(
child: AnimatedSwitcher(
- duration: Duration(milliseconds: 300),
+ duration: const Duration(milliseconds: 300),
child: sectionList.isEmpty
? Container(
key: ValueKey(images.noAd3yahFav),
@@ -194,7 +189,7 @@ class _FavoriteState extends State
controller: _scrollController,
slivers: [
ReorderableSliverList(
- key: ValueKey('List'),
+ key: const ValueKey('List'),
controller: _scrollController,
buildDraggableFeedback: (_,
BoxConstraints constraints,
@@ -273,7 +268,7 @@ class _FavoriteState extends State
}
class FavCard extends StatelessWidget {
- FavCard({
+ const FavCard({
Key? key,
required this.item,
required this.icon,
@@ -320,7 +315,7 @@ class FavCard extends StatelessWidget {
onTap: remove,
),
],
- additionalContent: item.category == NoorCategory.MYAD3YAH
+ additionalContent: item.category == NoorCategory.myad3yah
? CardText(
text: item.info,
color: Theme.of(context).primaryColor,
@@ -336,7 +331,7 @@ class FavCard extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
CardText(text: textList[0].trim()),
- SizedBox(height: 10),
+ const SizedBox(height: 10),
CardText(text: textList[1].trim()),
],
);
diff --git a/lib/pages/tabs/page_3_counter/counter_list_view.dart b/lib/pages/tabs/page_3_counter/counter_list_view.dart
new file mode 100644
index 0000000..6a5cdab
--- /dev/null
+++ b/lib/pages/tabs/page_3_counter/counter_list_view.dart
@@ -0,0 +1,316 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_svg/svg.dart';
+import 'package:noor/components/add_dialog.dart';
+import 'package:noor/components/alert_dialog.dart';
+import 'package:noor/components/delete_dialog.dart';
+import 'package:noor/exports/constants.dart';
+import 'package:noor/exports/controllers.dart';
+import 'package:noor/exports/pages.dart';
+import 'package:noor/pages/tabs/page_3_counter/counter_view_model.dart';
+import 'package:provider/provider.dart';
+import 'package:noor/utils/to_arabic.dart';
+
+const kMaxLength = 75;
+
+LinearGradient lightModeCounterBG = const LinearGradient(
+ colors: [
+ Color(0xff9AE2F6),
+ Color(0xff48C6EF),
+ ],
+ begin: Alignment.bottomRight,
+ end: Alignment.topLeft,
+);
+
+LinearGradient darkModeCounterBG = const LinearGradient(
+ colors: [
+ Color(0xff9FB6FF),
+ Color(0xff6C6CD3),
+ ],
+ begin: Alignment.bottomRight,
+ end: Alignment.topLeft,
+);
+
+class CounterListView extends StatefulWidget {
+ const CounterListView({Key? key}) : super(key: key);
+
+ @override
+ _CounterListViewState createState() => _CounterListViewState();
+}
+
+class _CounterListViewState extends State {
+ bool isEditMode = false;
+ final scrollController = ScrollController();
+
+ addDialog() async {
+ final counterModel = context.read();
+
+ await AddDialog.of(context).show(
+ enableSecondaryContent: false,
+ mainContentMaxLength: kMaxLength,
+ onSave: (content) {
+ counterModel.addSubhaItem(
+ SubhaItem(counter: 0, key: content, selected: false),
+ );
+
+ Navigator.of(context).pop();
+
+ scrollController.animateTo(0.0,
+ duration: const Duration(milliseconds: 200),
+ curve: Curves.easeInOut);
+ },
+ onCancel: () {
+ Navigator.of(context).pop();
+ },
+ );
+ }
+
+ onTap(SubhaItem item) {
+ final counterModel = context.read();
+ counterModel.setSelectedItem = item;
+
+ Navigator.of(context).pop();
+ }
+
+ onDelete(SubhaItem item) async {
+ final counterModel = context.read();
+
+ if (!item.locked && isEditMode) {
+ final confirm = await DeleteConfirmationDialog.of(context).show();
+ if (confirm ?? false) {
+ counterModel.deleteSubhaItem(item);
+ }
+ } else if (item.locked) {
+ NoorAlertDialog.of(context)
+ .show(title: 'عُــذراً', content: 'لا يمكن حذف الأذكار المُقترحة');
+ }
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ final counterModel = context.watch();
+ return Scaffold(
+ body: Stack(
+ children: [
+ SvgPicture.asset(
+ context.read().images.subhaBg,
+ fit: BoxFit.fill,
+ ),
+ Column(
+ children: [
+ appBar(),
+ Expanded(
+ child: ListView.separated(
+ controller: scrollController,
+ separatorBuilder: (_, __) => const SizedBox(height: 10),
+ padding: const EdgeInsets.symmetric(
+ horizontal: 20.0,
+ vertical: 10.0,
+ ),
+ itemCount: counterModel.subhaList.length,
+ itemBuilder: (_, int index) {
+ SubhaItem item = counterModel.subhaList[index];
+ return SubhaListItem(
+ item: item,
+ isEditMode: isEditMode,
+ onDelete: onDelete,
+ onTap: onTap,
+ );
+ },
+ ),
+ )
+ ],
+ ),
+ ],
+ ),
+ );
+ }
+
+ Widget appBar() {
+ return SafeArea(
+ bottom: false,
+ child: Padding(
+ padding: const EdgeInsets.symmetric(
+ horizontal: viewPadding,
+ vertical: 10.0,
+ ),
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ AnimatedSwitcher(
+ duration: const Duration(milliseconds: 200),
+ child: isEditMode
+ ? NoorIconButton(
+ key: ValueKey(isEditMode),
+ icon: context.read().images.addMyAd3yah,
+ onPressed: addDialog,
+ )
+ : NoorIconButton(
+ key: ValueKey(isEditMode),
+ icon: Images.editeIcon,
+ onPressed: () {
+ setState(() {
+ isEditMode = true;
+ });
+ },
+ ),
+ ),
+ Text(
+ 'قائمة الأذكار',
+ style: Theme.of(context)
+ .textTheme
+ .headline2!
+ .copyWith(fontWeight: FontWeight.bold),
+ ),
+ NoorIconButton(
+ icon: Icons.close_rounded,
+ onPressed: () {
+ if (isEditMode) {
+ setState(() {
+ isEditMode = false;
+ });
+ } else {
+ Navigator.of(context).pop();
+ }
+ },
+ )
+ ],
+ ),
+ ),
+ );
+ }
+}
+
+class SubhaListItem extends StatelessWidget {
+ const SubhaListItem({
+ Key? key,
+ required this.item,
+ required this.onTap,
+ required this.onDelete,
+ this.isEditMode = false,
+ }) : super(key: key);
+
+ final SubhaItem item;
+ final bool isEditMode;
+ final Function(SubhaItem) onTap;
+ final Function(SubhaItem) onDelete;
+
+ @override
+ Widget build(BuildContext context) {
+ final borderRadius = BorderRadius.circular(50);
+ final settings = context.watch