diff --git a/.metadata b/.metadata
index a3e76dd..b5d435a 100644
--- a/.metadata
+++ b/.metadata
@@ -4,8 +4,8 @@
# This file should be version controlled and should not be manually edited.
version:
- revision: "ff5b5b5fa6f35b717667719ddfdb1521d8bdd05a"
- channel: "stable"
+ revision: "58ba6c295d8ccf125366b7e871b1c41fe2255f75"
+ channel: "master"
project_type: app
@@ -13,17 +13,26 @@ project_type: app
migration:
platforms:
- platform: root
- create_revision: ff5b5b5fa6f35b717667719ddfdb1521d8bdd05a
- base_revision: ff5b5b5fa6f35b717667719ddfdb1521d8bdd05a
+ create_revision: 58ba6c295d8ccf125366b7e871b1c41fe2255f75
+ base_revision: 58ba6c295d8ccf125366b7e871b1c41fe2255f75
+ - platform: android
+ create_revision: 58ba6c295d8ccf125366b7e871b1c41fe2255f75
+ base_revision: 58ba6c295d8ccf125366b7e871b1c41fe2255f75
+ - platform: ios
+ create_revision: 58ba6c295d8ccf125366b7e871b1c41fe2255f75
+ base_revision: 58ba6c295d8ccf125366b7e871b1c41fe2255f75
- platform: linux
- create_revision: ff5b5b5fa6f35b717667719ddfdb1521d8bdd05a
- base_revision: ff5b5b5fa6f35b717667719ddfdb1521d8bdd05a
+ create_revision: 58ba6c295d8ccf125366b7e871b1c41fe2255f75
+ base_revision: 58ba6c295d8ccf125366b7e871b1c41fe2255f75
- platform: macos
- create_revision: ff5b5b5fa6f35b717667719ddfdb1521d8bdd05a
- base_revision: ff5b5b5fa6f35b717667719ddfdb1521d8bdd05a
+ create_revision: 58ba6c295d8ccf125366b7e871b1c41fe2255f75
+ base_revision: 58ba6c295d8ccf125366b7e871b1c41fe2255f75
+ - platform: web
+ create_revision: 58ba6c295d8ccf125366b7e871b1c41fe2255f75
+ base_revision: 58ba6c295d8ccf125366b7e871b1c41fe2255f75
- platform: windows
- create_revision: ff5b5b5fa6f35b717667719ddfdb1521d8bdd05a
- base_revision: ff5b5b5fa6f35b717667719ddfdb1521d8bdd05a
+ create_revision: 58ba6c295d8ccf125366b7e871b1c41fe2255f75
+ base_revision: 58ba6c295d8ccf125366b7e871b1c41fe2255f75
# User provided section
diff --git a/.vs/CMakeWorkspaceSettings.json b/.vs/CMakeWorkspaceSettings.json
new file mode 100644
index 0000000..d3e1057
--- /dev/null
+++ b/.vs/CMakeWorkspaceSettings.json
@@ -0,0 +1,3 @@
+{
+ "enableCMake": false
+}
\ No newline at end of file
diff --git a/.vs/ProjectSettings.json b/.vs/ProjectSettings.json
new file mode 100644
index 0000000..0cf5ea5
--- /dev/null
+++ b/.vs/ProjectSettings.json
@@ -0,0 +1,3 @@
+{
+ "CurrentProjectSetting": "No Configurations"
+}
\ No newline at end of file
diff --git a/.vs/VSWorkspaceState.json b/.vs/VSWorkspaceState.json
new file mode 100644
index 0000000..6648b61
--- /dev/null
+++ b/.vs/VSWorkspaceState.json
@@ -0,0 +1,9 @@
+{
+ "ExpandedNodes": [
+ "",
+ "\\lib",
+ "\\lib\\screens"
+ ],
+ "SelectedNode": "\\lib\\screens\\detail_doa_screen.dart",
+ "PreviewInSolutionExplorer": false
+}
\ No newline at end of file
diff --git a/.vs/quran/FileContentIndex/9f612705-2a03-4eca-9969-5fc81d26e92f.vsidx b/.vs/quran/FileContentIndex/9f612705-2a03-4eca-9969-5fc81d26e92f.vsidx
new file mode 100644
index 0000000..ab132a0
Binary files /dev/null and b/.vs/quran/FileContentIndex/9f612705-2a03-4eca-9969-5fc81d26e92f.vsidx differ
diff --git a/.vs/quran/v17/.wsuo b/.vs/quran/v17/.wsuo
new file mode 100644
index 0000000..0296ef4
Binary files /dev/null and b/.vs/quran/v17/.wsuo differ
diff --git a/.vs/quran/v17/Browse.VC.db b/.vs/quran/v17/Browse.VC.db
new file mode 100644
index 0000000..bc5a138
Binary files /dev/null and b/.vs/quran/v17/Browse.VC.db differ
diff --git a/.vs/slnx.sqlite b/.vs/slnx.sqlite
new file mode 100644
index 0000000..0e1233d
Binary files /dev/null and b/.vs/slnx.sqlite differ
diff --git a/android/app/src/main/res/drawable/icon.png b/android/app/src/main/res/drawable/icon.png
new file mode 100644
index 0000000..3917205
Binary files /dev/null and b/android/app/src/main/res/drawable/icon.png differ
diff --git a/android/app/src/main/res/raw/adzan.mp3 b/android/app/src/main/res/raw/adzan.mp3
new file mode 100644
index 0000000..581d32d
Binary files /dev/null and b/android/app/src/main/res/raw/adzan.mp3 differ
diff --git a/android/app/src/main/res/raw/keep.xml b/android/app/src/main/res/raw/keep.xml
new file mode 100644
index 0000000..149f705
--- /dev/null
+++ b/android/app/src/main/res/raw/keep.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/assets/sound/adzan.mp3 b/assets/sound/adzan.mp3
new file mode 100644
index 0000000..581d32d
Binary files /dev/null and b/assets/sound/adzan.mp3 differ
diff --git a/ios/RunnerTests/RunnerTests.swift b/ios/RunnerTests/RunnerTests.swift
new file mode 100644
index 0000000..86a7c3b
--- /dev/null
+++ b/ios/RunnerTests/RunnerTests.swift
@@ -0,0 +1,12 @@
+import Flutter
+import UIKit
+import XCTest
+
+class RunnerTests: XCTestCase {
+
+ func testExample() {
+ // If you add code to the Runner application, consider adding tests here.
+ // See https://developer.apple.com/documentation/xctest for more information about using XCTest.
+ }
+
+}
diff --git a/lib/main.dart b/lib/main.dart
index e1d0904..3fbb625 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -3,6 +3,8 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:quran/screens/home_screen.dart';
import 'package:google_fonts/google_fonts.dart';
+import 'services/notification.dart';
+import 'package:timezone/data/latest.dart' as tz;
final colorScheme = ColorScheme.fromSeed(
brightness: Brightness.light,
@@ -16,6 +18,9 @@ final theme = ThemeData().copyWith(
textTheme: GoogleFonts.poppinsTextTheme());
void main() {
+ WidgetsFlutterBinding.ensureInitialized();
+ NotificationService().initNotification();
+ tz.initializeTimeZones();
runApp(
const ProviderScope(child: MyApp()),
);
diff --git a/lib/screens/jadwal_sholat_screen.dart b/lib/screens/jadwal_sholat_screen.dart
index 29cde3b..01446e0 100644
--- a/lib/screens/jadwal_sholat_screen.dart
+++ b/lib/screens/jadwal_sholat_screen.dart
@@ -22,7 +22,6 @@ class _JadwalScreenState extends ConsumerState {
bool isLoading = false;
bool isMocked = false;
bool errorLocation = false;
- bool delay = true;
Future _determinePosition() async {
LocationPermission permission;
@@ -33,9 +32,6 @@ class _JadwalScreenState extends ConsumerState {
permission = await Geolocator.checkPermission();
if (permission == LocationPermission.denied) {
permission = await Geolocator.requestPermission();
- setState(() {
- errorLocation = true;
- });
if (permission == LocationPermission.denied) {
// Permissions are denied, next time you could try
@@ -44,6 +40,9 @@ class _JadwalScreenState extends ConsumerState {
// returned true. According to Android guidelines
// your App should show an explanatory UI now.
+ setState(() {
+ errorLocation = true;
+ });
return Future.error('Acceses denied');
}
}
@@ -57,6 +56,7 @@ class _JadwalScreenState extends ConsumerState {
setState(() {
isLoading = true;
});
+
final getPosition = await Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.high);
@@ -72,7 +72,9 @@ class _JadwalScreenState extends ConsumerState {
position = getPosition;
userPlace = '${place.subAdministrativeArea}';
});
- } catch (e) {}
+ } catch (e) {
+ print(e);
+ }
setState(() {
isLoading = false;
});
@@ -82,17 +84,8 @@ class _JadwalScreenState extends ConsumerState {
@override
void initState() {
- super.initState();
- Future.delayed(
- Duration(seconds: 2),
- () {
- setState(() {
- delay = false;
- });
- },
- );
-
_determinePosition();
+ super.initState();
}
@override
@@ -121,7 +114,7 @@ class _JadwalScreenState extends ConsumerState {
))
],
)
- : delay == true
+ : isLoading == true
? Center(
child: CircularProgressIndicator(),
)
@@ -154,9 +147,8 @@ class _JadwalScreenState extends ConsumerState {
height: 18,
),
data.when(
- error: (error, stackTrace) => const Center(
- child: Text('No data'),
- ),
+ error: (error, stackTrace) =>
+ Text(error.toString()),
loading: () => const Center(
child: CircularProgressIndicator(),
),
diff --git a/lib/services/notification.dart b/lib/services/notification.dart
new file mode 100644
index 0000000..67cbe6f
--- /dev/null
+++ b/lib/services/notification.dart
@@ -0,0 +1,64 @@
+import 'package:flutter_local_notifications/flutter_local_notifications.dart';
+
+import 'package:timezone/timezone.dart' as tz;
+
+class NotificationService {
+ final FlutterLocalNotificationsPlugin notificationsPlugin =
+ FlutterLocalNotificationsPlugin();
+
+ final sound = 'adzan.mp3';
+
+ Future initNotification() async {
+ AndroidInitializationSettings initializationSettingsAndroid =
+ const AndroidInitializationSettings('icon');
+
+ var initializationSettingsIOS = DarwinInitializationSettings(
+ requestAlertPermission: true,
+ requestBadgePermission: true,
+ requestSoundPermission: true,
+ onDidReceiveLocalNotification:
+ (int id, String? title, String? body, String? payload) async {});
+
+ var initializationSettings = InitializationSettings(
+ android: initializationSettingsAndroid, iOS: initializationSettingsIOS);
+ await notificationsPlugin.initialize(initializationSettings,
+ onDidReceiveNotificationResponse:
+ (NotificationResponse notificationResponse) async {});
+ }
+
+ notificationDetails() {
+ return NotificationDetails(
+ android: AndroidNotificationDetails(
+ 'your_channel_id',
+ 'channelName',
+ playSound: true,
+ sound: RawResourceAndroidNotificationSound('adzan'),
+ importance: Importance.max,
+ priority: Priority.high,
+ ),
+ iOS: DarwinNotificationDetails());
+ }
+
+ Future showNotification(
+ {int id = 0, String? title, String? body, String? payLoad}) async {
+ return notificationsPlugin.show(
+ id, title, body, await notificationDetails());
+ }
+
+ Future scheduleNotification(
+ {int id = 0,
+ String? title,
+ String? body,
+ String? payLoad,
+ required DateTime scheduledNotificationDateTime}) async {
+ return notificationsPlugin.zonedSchedule(
+ id,
+ title,
+ body,
+ tz.TZDateTime.from(scheduledNotificationDateTime, tz.local),
+ await notificationDetails(),
+ androidScheduleMode: AndroidScheduleMode.exactAllowWhileIdle,
+ uiLocalNotificationDateInterpretation:
+ UILocalNotificationDateInterpretation.absoluteTime);
+ }
+}
diff --git a/lib/widgets/jadwal_sholat_list.dart b/lib/widgets/jadwal_sholat_list.dart
index 242a256..f044c43 100644
--- a/lib/widgets/jadwal_sholat_list.dart
+++ b/lib/widgets/jadwal_sholat_list.dart
@@ -1,5 +1,7 @@
import 'package:flutter/material.dart';
import 'package:quran/models/jadwal_sholat_model.dart';
+import 'package:quran/services/notification.dart';
+import 'package:intl/intl.dart';
class JadwalList extends StatelessWidget {
const JadwalList({super.key, required this.data});
@@ -20,56 +22,164 @@ class JadwalList extends StatelessWidget {
),
Padding(
padding: const EdgeInsets.all(8.0),
- child: ListTile(
- shape: Border.all(),
- title: const Text(
- 'Imsak :',
- style: TextStyle(fontSize: 18),
- ),
- trailing: Text(
- data.data.imsak,
- style: const TextStyle(fontSize: 18),
- )),
+ child: InkWell(
+ onTap: () {
+ NotificationService().showNotification(
+ title: 'Waktu Imsak',
+ body: 'Imsak',
+ );
+ },
+ child: ListTile(
+ shape: Border.all(),
+ title: const Text(
+ 'Imsak :',
+ style: TextStyle(fontSize: 18),
+ ),
+ trailing: Text(
+ data.data.imsak,
+ style: const TextStyle(fontSize: 18),
+ )),
+ ),
),
Padding(
padding: const EdgeInsets.all(8.0),
- child: ListTile(
- shape: Border.all(),
- title: const Text('Subuh :', style: TextStyle(fontSize: 18)),
- trailing:
- Text(data.data.subuh, style: const TextStyle(fontSize: 18))),
+ child: InkWell(
+ onTap: () {
+ List timeParts = data.data.subuh.split(':');
+ int hour = int.parse(timeParts[0]);
+ int minute = int.parse(timeParts[1]);
+
+ DateTime now = DateTime.now();
+ DateTime subuhTime =
+ DateTime(now.year, now.month, now.day, hour, minute);
+
+ if (subuhTime.isBefore(now)) {
+ subuhTime = subuhTime.add(Duration(days: 1));
+ }
+
+ NotificationService().scheduleNotification(
+ title: 'Waktu Dzuhur',
+ body: 'Sholat Dzuhur',
+ scheduledNotificationDateTime: subuhTime);
+ },
+ child: ListTile(
+ shape: Border.all(),
+ title: const Text('Subuh :', style: TextStyle(fontSize: 18)),
+ trailing: Text(data.data.subuh,
+ style: const TextStyle(fontSize: 18))),
+ ),
),
Padding(
padding: const EdgeInsets.all(8.0),
- child: ListTile(
- shape: Border.all(),
- title: const Text('Dzuhur :', style: TextStyle(fontSize: 18)),
- trailing:
- Text(data.data.dzuhur, style: const TextStyle(fontSize: 18))),
+ child: InkWell(
+ onTap: () {
+ List timeParts = data.data.dzuhur.split(':');
+ int hour = int.parse(timeParts[0]);
+ int minute = int.parse(timeParts[1]);
+
+ DateTime now = DateTime.now();
+ DateTime dzuhurTime =
+ DateTime(now.year, now.month, now.day, hour, minute);
+
+ if (dzuhurTime.isBefore(now)) {
+ dzuhurTime = dzuhurTime.add(Duration(days: 1));
+ }
+
+ NotificationService().scheduleNotification(
+ title: 'Waktu Dzuhur',
+ body: 'Sholat Dzuhur',
+ scheduledNotificationDateTime: dzuhurTime);
+ },
+ child: ListTile(
+ shape: Border.all(),
+ title: const Text('Dzuhur :', style: TextStyle(fontSize: 18)),
+ trailing: Text(data.data.dzuhur,
+ style: const TextStyle(fontSize: 18))),
+ ),
),
Padding(
padding: const EdgeInsets.all(8.0),
- child: ListTile(
- shape: Border.all(),
- title: const Text('Ashar :', style: TextStyle(fontSize: 18)),
- trailing:
- Text(data.data.ashar, style: const TextStyle(fontSize: 18))),
+ child: InkWell(
+ onTap: () {
+ List timeParts = data.data.ashar.split(':');
+ int hour = int.parse(timeParts[0]);
+ int minute = int.parse(timeParts[1]);
+
+ DateTime now = DateTime.now();
+ DateTime asharTime =
+ DateTime(now.year, now.month, now.day, hour, minute);
+
+ if (asharTime.isBefore(now)) {
+ asharTime = asharTime.add(Duration(days: 1));
+ }
+
+ NotificationService().scheduleNotification(
+ title: 'Waktu Ashar',
+ body: 'Sholat Ashar',
+ scheduledNotificationDateTime: asharTime);
+ },
+ child: ListTile(
+ shape: Border.all(),
+ title: const Text('Ashar :', style: TextStyle(fontSize: 18)),
+ trailing: Text(data.data.ashar,
+ style: const TextStyle(fontSize: 18))),
+ ),
),
Padding(
padding: const EdgeInsets.all(8.0),
- child: ListTile(
- shape: Border.all(),
- title: const Text('Maghrib :'),
- trailing: Text(data.data.maghrib,
- style: const TextStyle(fontSize: 18))),
+ child: InkWell(
+ onTap: () {
+ List timeParts = data.data.maghrib.split(':');
+ int hour = int.parse(timeParts[0]);
+ int minute = int.parse(timeParts[1]);
+
+ DateTime now = DateTime.now();
+ DateTime maghribTime =
+ DateTime(now.year, now.month, now.day, hour, minute);
+
+ if (maghribTime.isBefore(now)) {
+ maghribTime = maghribTime.add(Duration(days: 1));
+ }
+
+ NotificationService().scheduleNotification(
+ title: 'Waktu Maghrib',
+ body: 'Sholat Maghrib',
+ scheduledNotificationDateTime: maghribTime);
+ },
+ child: ListTile(
+ shape: Border.all(),
+ title: const Text('Maghrib :'),
+ trailing: Text(data.data.maghrib,
+ style: const TextStyle(fontSize: 18))),
+ ),
),
Padding(
padding: const EdgeInsets.all(8.0),
- child: ListTile(
- shape: Border.all(),
- title: const Text('Isya :', style: TextStyle(fontSize: 18)),
- trailing:
- Text(data.data.isya, style: const TextStyle(fontSize: 18))),
+ child: InkWell(
+ onTap: () {
+ List timeParts = data.data.isya.split(':');
+ int hour = int.parse(timeParts[0]);
+ int minute = int.parse(timeParts[1]);
+
+ DateTime now = DateTime.now();
+ DateTime isyaTime =
+ DateTime(now.year, now.month, now.day, hour, minute);
+
+ if (isyaTime.isBefore(now)) {
+ isyaTime = isyaTime.add(Duration(days: 1));
+ }
+
+ NotificationService().scheduleNotification(
+ title: 'Waktu Isya',
+ body: 'Sholat Isya',
+ scheduledNotificationDateTime: isyaTime);
+ },
+ child: ListTile(
+ shape: Border.all(),
+ title: const Text('Isya :', style: TextStyle(fontSize: 18)),
+ trailing:
+ Text(data.data.isya, style: const TextStyle(fontSize: 18))),
+ ),
),
],
);
diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift
index 32aadf6..fd45162 100644
--- a/macos/Flutter/GeneratedPluginRegistrant.swift
+++ b/macos/Flutter/GeneratedPluginRegistrant.swift
@@ -5,10 +5,12 @@
import FlutterMacOS
import Foundation
+import flutter_local_notifications
import geolocator_apple
import path_provider_foundation
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
+ FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin"))
GeolocatorPlugin.register(with: registry.registrar(forPlugin: "GeolocatorPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
}
diff --git a/pubspec.lock b/pubspec.lock
index d7d121d..94bbb74 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -5,10 +5,10 @@ packages:
dependency: transitive
description:
name: archive
- sha256: "49b1fad315e57ab0bbc15bcbb874e83116a1d78f77ebd500a4af6c9407d6b28e"
+ sha256: e0902a06f0e00414e4e3438a084580161279f137aeb862274710f29ec10cf01e
url: "https://pub.dev"
source: hosted
- version: "3.3.8"
+ version: "3.3.9"
args:
dependency: transitive
description:
@@ -73,6 +73,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.17.2"
+ console:
+ dependency: transitive
+ description:
+ name: console
+ sha256: e04e7824384c5b39389acdd6dc7d33f3efe6b232f6f16d7626f194f6a01ad69a
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.1.0"
convert:
dependency: transitive
description:
@@ -97,6 +105,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.6"
+ dbus:
+ dependency: transitive
+ description:
+ name: dbus
+ sha256: "6f07cba3f7b3448d42d015bfd3d53fe12e5b36da2423f23838efc1d5fb31a263"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.7.8"
fake_async:
dependency: transitive
description:
@@ -126,6 +142,30 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.13.1"
+ flutter_local_notifications:
+ dependency: "direct main"
+ description:
+ name: flutter_local_notifications
+ sha256: "3002092e5b8ce2f86c3361422e52e6db6776c23ee21e0b2f71b892bf4259ef04"
+ url: "https://pub.dev"
+ source: hosted
+ version: "15.1.1"
+ flutter_local_notifications_linux:
+ dependency: transitive
+ description:
+ name: flutter_local_notifications_linux
+ sha256: "33f741ef47b5f63cc7f78fe75eeeac7e19f171ff3c3df054d84c1e38bedb6a03"
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.0.0+1"
+ flutter_local_notifications_platform_interface:
+ dependency: transitive
+ description:
+ name: flutter_local_notifications_platform_interface
+ sha256: "7cf643d6d5022f3baed0be777b0662cce5919c0a7b86e700299f22dc4ae660ef"
+ url: "https://pub.dev"
+ source: hosted
+ version: "7.0.0+1"
flutter_riverpod:
dependency: "direct main"
description:
@@ -180,18 +220,18 @@ packages:
dependency: "direct main"
description:
name: geolocator
- sha256: "5c23f3613f50586c0bbb2b8f970240ae66b3bd992088cf60dd5ee2e6f7dde3a8"
+ sha256: "9f1c9a70dd25fc9d9574ff17ba714cf3bc7894258efd7d1ce0debfafe2f8e1d8"
url: "https://pub.dev"
source: hosted
- version: "9.0.2"
+ version: "10.0.1"
geolocator_android:
dependency: transitive
description:
name: geolocator_android
- sha256: "835ff5b4888a2f8eba128996494faf9c5d422785322a81dc0565b99e0f6c379d"
+ sha256: db75aacf93fcdc2c0ba20066019da30e3fde7b102cf579d4bd4ea542e8a8cf17
url: "https://pub.dev"
source: hosted
- version: "4.2.2"
+ version: "4.2.4"
geolocator_apple:
dependency: transitive
description:
@@ -204,10 +244,10 @@ packages:
dependency: transitive
description:
name: geolocator_platform_interface
- sha256: af4d69231452f9620718588f41acc4cb58312368716bfff2e92e770b46ce6386
+ sha256: b2a0c09d2cfe8ad6a8cc44fada5c1092c49286e8c30922914dfe2b23799a682f
url: "https://pub.dev"
source: hosted
- version: "4.0.7"
+ version: "4.0.8"
geolocator_web:
dependency: transitive
description:
@@ -220,26 +260,34 @@ packages:
dependency: transitive
description:
name: geolocator_windows
- sha256: "4f4218f122a6978d0ad655fa3541eea74c67417440b09f0657238810d5af6bdc"
+ sha256: "463045515b08bd83f73e014359c4ad063b902eb3899952cfb784497ae6c6583b"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.2.0"
+ get_it:
+ dependency: transitive
+ description:
+ name: get_it
+ sha256: f79870884de16d689cf9a7d15eedf31ed61d750e813c538a6efb92660fea83c3
url: "https://pub.dev"
source: hosted
- version: "0.1.3"
+ version: "7.6.4"
google_fonts:
dependency: "direct main"
description:
name: google_fonts
- sha256: "6b6f10f0ce3c42f6552d1c70d2c28d764cf22bb487f50f66cca31dcd5194f4d6"
+ sha256: e20ff62b158b96f392bfc8afe29dee1503c94fbea2cbe8186fd59b756b8ae982
url: "https://pub.dev"
source: hosted
- version: "4.0.4"
+ version: "5.1.0"
http:
dependency: "direct main"
description:
name: http
- sha256: "5895291c13fa8a3bd82e76d5627f69e0d85ca6a30dcac95c4ea19a5d555879c2"
+ sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525"
url: "https://pub.dev"
source: hosted
- version: "0.13.6"
+ version: "1.1.0"
http_parser:
dependency: transitive
description:
@@ -256,6 +304,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "4.0.17"
+ intl:
+ dependency: "direct main"
+ description:
+ name: intl
+ sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.18.1"
js:
dependency: transitive
description:
@@ -304,6 +360,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.9.1"
+ msix:
+ dependency: "direct dev"
+ description:
+ name: msix
+ sha256: "76c87b8207323803169626a55afd78bbb8413c984df349a76598b9fbf9224677"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.16.1"
+ package_config:
+ dependency: transitive
+ description:
+ name: package_config
+ sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.0"
path:
dependency: transitive
description:
@@ -392,6 +464,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.7.3"
+ pub_semver:
+ dependency: transitive
+ description:
+ name: pub_semver
+ sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.4"
riverpod:
dependency: transitive
description:
@@ -469,6 +549,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.6.0"
+ timezone:
+ dependency: transitive
+ description:
+ name: timezone
+ sha256: "1cfd8ddc2d1cfd836bc93e67b9be88c3adaeca6f40a00ca999104c30693cdca0"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.9.2"
typed_data:
dependency: transitive
description:
diff --git a/pubspec.yaml b/pubspec.yaml
index 70e410d..7744c3f 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -34,23 +34,30 @@ dependencies:
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.2
- google_fonts: ^4.0.4
+ google_fonts: ^5.1.0
lottie: ^2.3.2
- http: ^0.13.6
+ http: ^1.1.0
flutter_riverpod: ^2.3.6
search_page: ^2.3.0
- geolocator: ^9.0.2
- geocoding: ^2.1.0
+ geolocator: ^10.0.1
+ geocoding: ^2.0.6
+ flutter_local_notifications: ^15.1.1
+ intl: ^0.18.1
dev_dependencies:
flutter_test:
sdk: flutter
flutter_launcher_icons: "^0.13.1"
+ msix: ^3.16.1
flutter_launcher_icons:
android: "launcher_icon"
ios: true
image_path: "assets/icon/icon.png"
+ windows:
+ generate: true
+ image_path: "assets/icon/icon.png"
+ icon_size: 48
# The "flutter_lints" package below contains a set of recommended lints to
# encourage good coding practices. The lint set provided by the package is
@@ -73,6 +80,7 @@ flutter:
assets:
- assets/lottie/
- assets/image/
+ - assets/sound/
# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.dev/assets-and-images/#resolution-aware
diff --git a/test/widget_test.dart b/test/widget_test.dart
index 4e0461e..8b13789 100644
--- a/test/widget_test.dart
+++ b/test/widget_test.dart
@@ -1,31 +1 @@
-// This is a basic Flutter widget test.
-//
-// To perform an interaction with a widget in your test, use the WidgetTester
-// utility in the flutter_test package. For example, you can send tap and scroll
-// gestures. You can also use WidgetTester to find child widgets in the widget
-// tree, read text, and verify that the values of widget properties are correct.
-import 'dart:convert';
-
-import 'package:http/http.dart' as http;
-import 'package:quran/models/jadwal_sholat_model.dart';
-
-main() async {
- final url = Uri.parse(
- 'https://api.banghasan.com/sholat/format/json/kota/nama/kota serang');
- final response = await http.get(url);
-
- List data = (jsonDecode(response.body) as Map)['kota'];
- final dataId = data.map((e) => e['id']).toList();
-
- DateTime dateToday = DateTime.now();
- String date = dateToday.toString().substring(0, 10);
-
- final uri = Uri.parse(
- 'https://api.banghasan.com/sholat/format/json/jadwal/kota/${dataId[0]}/tanggal/$date');
-
- final responseData = await http.get(uri);
- Map jadwal =
- (jsonDecode(responseData.body) as Map)['jadwal'];
- JadwalSholat jadwalDataApi = JadwalSholat.fromJson(jadwal);
-}
diff --git a/windows/CMakeLists.txt b/windows/CMakeLists.txt
index b8098a5..070dad6 100644
--- a/windows/CMakeLists.txt
+++ b/windows/CMakeLists.txt
@@ -8,7 +8,7 @@ set(BINARY_NAME "quran")
# Explicitly opt in to modern CMake behaviors to avoid warnings with recent
# versions of CMake.
-cmake_policy(SET CMP0063 NEW)
+cmake_policy(VERSION 3.14...3.25)
# Define build configuration option.
get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
@@ -52,6 +52,7 @@ add_subdirectory(${FLUTTER_MANAGED_DIR})
# Application build; see runner/CMakeLists.txt.
add_subdirectory("runner")
+
# Generated plugin build rules, which manage building the plugins and adding
# them to the application.
include(flutter/generated_plugins.cmake)
diff --git a/windows/flutter/CMakeLists.txt b/windows/flutter/CMakeLists.txt
index 930d207..903f489 100644
--- a/windows/flutter/CMakeLists.txt
+++ b/windows/flutter/CMakeLists.txt
@@ -10,6 +10,11 @@ include(${EPHEMERAL_DIR}/generated_config.cmake)
# https://github.com/flutter/flutter/issues/57146.
set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper")
+# Set fallback configurations for older versions of the flutter tool.
+if (NOT DEFINED FLUTTER_TARGET_PLATFORM)
+ set(FLUTTER_TARGET_PLATFORM "windows-x64")
+endif()
+
# === Flutter Library ===
set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll")
@@ -92,7 +97,7 @@ add_custom_command(
COMMAND ${CMAKE_COMMAND} -E env
${FLUTTER_TOOL_ENVIRONMENT}
"${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat"
- windows-x64 $
+ ${FLUTTER_TARGET_PLATFORM} $
VERBATIM
)
add_custom_target(flutter_assemble DEPENDS
diff --git a/windows/runner/utils.cpp b/windows/runner/utils.cpp
index f5bf9fa..b2b0873 100644
--- a/windows/runner/utils.cpp
+++ b/windows/runner/utils.cpp
@@ -47,16 +47,17 @@ std::string Utf8FromUtf16(const wchar_t* utf16_string) {
}
int target_length = ::WideCharToMultiByte(
CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string,
- -1, nullptr, 0, nullptr, nullptr);
+ -1, nullptr, 0, nullptr, nullptr)
+ -1; // remove the trailing null character
+ int input_length = (int)wcslen(utf16_string);
std::string utf8_string;
- if (target_length == 0 || target_length > utf8_string.max_size()) {
+ if (target_length <= 0 || target_length > utf8_string.max_size()) {
return utf8_string;
}
utf8_string.resize(target_length);
int converted_length = ::WideCharToMultiByte(
CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string,
- -1, utf8_string.data(),
- target_length, nullptr, nullptr);
+ input_length, utf8_string.data(), target_length, nullptr, nullptr);
if (converted_length == 0) {
return std::string();
}
diff --git a/windows/runner/win32_window.cpp b/windows/runner/win32_window.cpp
index 041a385..60608d0 100644
--- a/windows/runner/win32_window.cpp
+++ b/windows/runner/win32_window.cpp
@@ -60,7 +60,7 @@ class WindowClassRegistrar {
public:
~WindowClassRegistrar() = default;
- // Returns the singleton registar instance.
+ // Returns the singleton registrar instance.
static WindowClassRegistrar* GetInstance() {
if (!instance_) {
instance_ = new WindowClassRegistrar();
diff --git a/windows/runner/win32_window.h b/windows/runner/win32_window.h
index c86632d..e901dde 100644
--- a/windows/runner/win32_window.h
+++ b/windows/runner/win32_window.h
@@ -77,7 +77,7 @@ class Win32Window {
// OS callback called by message pump. Handles the WM_NCCREATE message which
// is passed when the non-client area is being created and enables automatic
// non-client DPI scaling so that the non-client area automatically
- // responsponds to changes in DPI. All other messages are handled by
+ // responds to changes in DPI. All other messages are handled by
// MessageHandler.
static LRESULT CALLBACK WndProc(HWND const window,
UINT const message,