diff --git a/android/app/src/main/kotlin/com/ccextractor/ultimate_alarm_clock/ultimate_alarm_clock/MainActivity.kt b/android/app/src/main/kotlin/com/ccextractor/ultimate_alarm_clock/ultimate_alarm_clock/MainActivity.kt index 4aa789b3..7c2f9346 100644 --- a/android/app/src/main/kotlin/com/ccextractor/ultimate_alarm_clock/ultimate_alarm_clock/MainActivity.kt +++ b/android/app/src/main/kotlin/com/ccextractor/ultimate_alarm_clock/ultimate_alarm_clock/MainActivity.kt @@ -12,7 +12,6 @@ import android.media.Ringtone import android.media.RingtoneManager import android.net.Uri import android.os.Bundle -import android.os.SystemClock import android.provider.Settings import android.util.Log import android.view.WindowManager @@ -32,6 +31,8 @@ class MainActivity : FlutterActivity() { private var isAlarm: String? = "true" val alarmConfig = hashMapOf("shouldAlarmRing" to false, "alarmIgnore" to false) private var ringtone: Ringtone? = null + lateinit var methodChannel1: MethodChannel + lateinit var methodChannel2: MethodChannel } override fun onCreate(savedInstanceState: Bundle?) { @@ -46,8 +47,8 @@ class MainActivity : FlutterActivity() { override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) { super.configureFlutterEngine(flutterEngine) window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON or WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON) - var methodChannel1 = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL1) - var methodChannel2 = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL2) + methodChannel1 = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL1) + methodChannel2 = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL2) val intent = intent @@ -89,6 +90,14 @@ class MainActivity : FlutterActivity() { var notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager notificationManager.cancel(1) + notificationManager.cancel(2) + } else if (call.method == "dismissTimer"){ + val arguments = call.arguments as? Map<*, *> + val timerId = arguments?.get("timerId") as? Int ?: 0 + val timerName = arguments?.get("timerName") as? String ?: "Unnamed" + val timerValue = arguments?.get("timerValue") as? Int ?: 0 + + TimerNotification().showDismissNotification(timerValue, timerId, context) } else { result.notImplemented() } diff --git a/android/app/src/main/kotlin/com/ccextractor/ultimate_alarm_clock/ultimate_alarm_clock/TimerBroadcasts/TimerNotification.kt b/android/app/src/main/kotlin/com/ccextractor/ultimate_alarm_clock/ultimate_alarm_clock/TimerBroadcasts/TimerNotification.kt index e2de3ffd..d7aee328 100644 --- a/android/app/src/main/kotlin/com/ccextractor/ultimate_alarm_clock/ultimate_alarm_clock/TimerBroadcasts/TimerNotification.kt +++ b/android/app/src/main/kotlin/com/ccextractor/ultimate_alarm_clock/ultimate_alarm_clock/TimerBroadcasts/TimerNotification.kt @@ -7,7 +7,6 @@ import android.content.Context import android.content.Intent import android.os.Build import androidx.core.app.NotificationCompat -import com.ccextractor.ultimate_alarm_clock.getLatestTimer class TimerNotification : BroadcastReceiver() { @@ -28,6 +27,13 @@ class TimerNotification : BroadcastReceiver() { } }) + if (intent.action == "com.ccextractor.ultimate_alarm_clock.DISMISS_TIMER"){ + val timerID: Int = intent.getIntExtra("timerID", 0) + val args = hashMapOf("timerID" to timerID) + MainActivity.methodChannel2.invokeMethod("dismissTimer", args) + notificationManager.cancel(2) + } + if (intent.action == "com.ccextractor.ultimate_alarm_clock.START_TIMERNOTIF" || intent.action == Intent.ACTION_BOOT_COMPLETED) { createNotificationChannel(context) @@ -84,6 +90,29 @@ class TimerNotification : BroadcastReceiver() { notificationManager.notify(1, notification) } + fun showDismissNotification(milliseconds: Int, timerID: Int, context: Context) { + var notificationManager = + context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + val dismissIntent = Intent(context, TimerNotification::class.java).apply { + action = "com.ccextractor.ultimate_alarm_clock.DISMISS_TIMER" + putExtra("timerID", timerID) + } + val dismissPendingIntent = PendingIntent.getBroadcast( + context, System.currentTimeMillis().toInt(), dismissIntent, + PendingIntent.FLAG_IMMUTABLE + ) + + val notification = NotificationCompat.Builder(context, TimerService.TIMER_CHANNEL_ID) + .setSmallIcon(R.mipmap.launcher_icon) + .setContentTitle("Dismiss Timer") + .setContentText(formatDuration(milliseconds.toLong())) + .setPriority(NotificationCompat.PRIORITY_HIGH) + .setOnlyAlertOnce(true) + .addAction(R.mipmap.launcher_icon, "Dismiss", dismissPendingIntent) + .build() + notificationManager.notify(2, notification) + } + private fun formatDuration(milliseconds: Long): String { val seconds = (milliseconds / 1000) % 60 val minutes = (milliseconds / (1000 * 60)) % 60 diff --git a/android/app/src/main/kotlin/com/ccextractor/ultimate_alarm_clock/ultimate_alarm_clock/TimerDatabaseHelper.kt b/android/app/src/main/kotlin/com/ccextractor/ultimate_alarm_clock/ultimate_alarm_clock/TimerDatabaseHelper.kt index 7b103b99..44fa162c 100644 --- a/android/app/src/main/kotlin/com/ccextractor/ultimate_alarm_clock/ultimate_alarm_clock/TimerDatabaseHelper.kt +++ b/android/app/src/main/kotlin/com/ccextractor/ultimate_alarm_clock/ultimate_alarm_clock/TimerDatabaseHelper.kt @@ -11,7 +11,19 @@ class TimerDatabaseHelper(context: Context) : SQLiteOpenHelper(context, DATABASE } override fun onCreate(db: SQLiteDatabase) { + val createTableQuery = """ + CREATE TABLE timers ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + startedOn TEXT NOT NULL, + timerValue INTEGER NOT NULL, + timeElapsed INTEGER NOT NULL, + ringtoneName TEXT NOT NULL, + timerName TEXT NOT NULL, + isPaused INTEGER NOT NULL + ); + """.trimIndent() + db.execSQL(createTableQuery) } override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) { diff --git a/lib/app/modules/timer/views/timer_animation.dart b/lib/app/modules/timer/views/timer_animation.dart index 828c44c8..66d7ef55 100644 --- a/lib/app/modules/timer/views/timer_animation.dart +++ b/lib/app/modules/timer/views/timer_animation.dart @@ -1,5 +1,6 @@ import 'dart:async'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:get/get.dart'; import 'package:ultimate_alarm_clock/app/data/models/timer_model.dart'; import 'package:ultimate_alarm_clock/app/data/providers/isar_provider.dart'; @@ -26,6 +27,7 @@ class _TimerAnimatedCardState extends State with SingleTickerProviderStateMixin, AutomaticKeepAliveClientMixin { TimerController controller = Get.find(); ThemeController themeController = Get.find(); + MethodChannel timerChannel = const MethodChannel('timer'); var width = Get.width; var height = Get.height; @@ -40,6 +42,11 @@ class _TimerAnimatedCardState extends State }); } else { stopTimer(); + timerChannel.invokeMethod('dismissTimer', { + 'timerId': widget.timer.timerId, + 'timerName': widget.timer.timerName, + 'timerValue': widget.timer.timerValue, + }); controller.startRinger(widget.timer.timerId); } }); @@ -49,9 +56,46 @@ class _TimerAnimatedCardState extends State _timerCounter!.cancel(); } + void dismissTimer(int id) { + print('timer id: $id'); + + if(id != widget.timer.timerId){ + return; + } + setState(() { + if (widget.timer.isPaused == 0) { + stopTimer(); + } else { + startTimer(); + } + widget.timer.isPaused = + widget.timer.isPaused == 0 ? 1 : 0; + IsarDb.updateTimerPauseStatus(widget.timer); + }); + if (widget.timer.timeElapsed >= + widget.timer.timerValue) { + controller.stopRinger(widget.timer.timerId); + setState(() { + widget.timer.timeElapsed = 0; + IsarDb.updateTimerTick(widget.timer) + .then((value) => + IsarDb.updateTimerPauseStatus( + widget.timer)); + widget.timer.isPaused = 1; + }); + } + } + @override void initState() { super.initState(); + timerChannel.setMethodCallHandler((call) async { + if (call.method == 'dismissTimer') { + int timerID = call.arguments['timerID']; + print(timerID); + dismissTimer(timerID); + } + }); if (Utils.getDifferenceMillisFromNow( widget.timer.startedOn, widget.timer.timerValue) <= 0 && @@ -202,28 +246,7 @@ class _TimerAnimatedCardState extends State children: [ GestureDetector( onTap: () { - setState(() { - if (widget.timer.isPaused == 0) { - stopTimer(); - } else { - startTimer(); - } - widget.timer.isPaused = - widget.timer.isPaused == 0 ? 1 : 0; - IsarDb.updateTimerPauseStatus(widget.timer); - }); - if (widget.timer.timeElapsed >= - widget.timer.timerValue) { - controller.stopRinger(widget.timer.timerId); - setState(() { - widget.timer.timeElapsed = 0; - IsarDb.updateTimerTick(widget.timer) - .then((value) => - IsarDb.updateTimerPauseStatus( - widget.timer)); - widget.timer.isPaused = 1; - }); - } + dismissTimer(widget.timer.timerId); }, child: Container( decoration: BoxDecoration(