diff --git a/.gitignore b/.gitignore index e3ac803..c1c4d54 100644 --- a/.gitignore +++ b/.gitignore @@ -126,6 +126,9 @@ app.*.symbols # Gradle files .gradle/ build/ +android/app/release/* +android/build/* +android/app/build/* # Local configuration file (sdk path, etc) local.properties diff --git a/CHANGELOG.md b/CHANGELOG.md index 1744311..b164276 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog -## 1.1.0 (In Development) +## 1.2.0 (In Development) + +- Automatically enable next day's alarm when the current day's is activated. +- Add the alarm's date to the SwitchTile text for confirming it's truly set. + +## 1.1.0 (2026-11-01) Usability improvements. diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts index 37c461c..b697149 100644 --- a/android/app/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -55,7 +55,8 @@ android { isShrinkResources = true proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), - "proguard-rules.pro" + "proguard-rules.pro", + "flutter_proguard_rules.pro" ) /// 20260928 - With minifying, helped some, but also used diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index 6b23797..94c356a 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,9 @@ -#Sat Sep 12 19:36:23 MST 2026 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.8.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.9.0-bin.zip +networkTimeout=10000 +retries=0 +retryBackOffMs=500 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/android/settings.gradle.kts b/android/settings.gradle.kts index 94e510e..5858ba5 100644 --- a/android/settings.gradle.kts +++ b/android/settings.gradle.kts @@ -19,9 +19,9 @@ pluginManagement { plugins { id("dev.flutter.flutter-plugin-loader") version "1.0.0" - id("com.android.application") version "9.5.0" apply false + id("com.android.application") version "9.5.1" apply false - // This will need removed in Gradle/AGP 9. JK - needs to exist otherwiese: + // This will need removed in Gradle/AGP 9. JK - needs to exist otherwise: // "Error: Your project's Kotlin version (2.2.10) is lower than Flutter's minimum supported version of 2.2.20." id("org.jetbrains.kotlin.android") version "2.4.21" apply false } diff --git a/lib/main.dart b/lib/main.dart index e15ad51..8c487c3 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,6 +1,7 @@ import 'dart:io'; import 'dart:async'; +import 'package:alarm/utils/alarm_set.dart'; import 'package:flutter/material.dart'; import 'package:geolocator/geolocator.dart'; import 'package:shared_preferences/shared_preferences.dart'; @@ -29,6 +30,7 @@ void main() async { tz.initializeTimeZones(); await Alarm.init(); + runApp(const SunsetAlarmApp()); } @@ -61,6 +63,11 @@ class SunsetAlarmApp extends StatelessWidget { } } +int dateAsId(DateTime d) => d.year * 10000 + d.month * 100 + d.day; +int todayAsId() { + return dateAsId(DateTime.now()); +} + class HomeScreen extends StatefulWidget { const HomeScreen({super.key}); @@ -86,13 +93,23 @@ class _HomeScreenState extends State { String? _minuteErrorText; bool _validTime = false; - static const _alarmId = 1001; + int _alarmId = 20260000; @override void initState() { super.initState(); _initNotifications(); _loadPrefs(); + + // Reschedule alarm any time one goes off. + Alarm.ringing.listen((AlarmSet alarmSet) { + for (final alarm in alarmSet.alarms) { + if (alarm.id == todayAsId()) { + _scheduleAlarm(); + break; + } + } + }); } Future _initNotifications() async { @@ -240,6 +257,10 @@ class _HomeScreenState extends State { alarmTime = alarmTime.add(const Duration(days: 1)); } + _debug("_scheduleAlarm, alarmTime=${alarmTime.toIso8601String()}"); + _alarmId = dateAsId(alarmTime); + _debug("_alarmId=$_alarmId"); + if (Platform.isLinux) { // Linux: use a Timer (app must stay open) _alarmTimer?.cancel(); @@ -300,9 +321,9 @@ class _HomeScreenState extends State { androidScheduleMode: AndroidScheduleMode.alarmClock, ); _showSnack('Alarm scheduled!'); - debugPrint('DEBUG: Alarm time: ${tzAlarm.toString()}'); - debugPrint('DEBUG: Current time: ${DateTime.now().toUtc().toString()}'); - debugPrint('DEBUG: ${_notifications.toString()}'); + _debug('Alarm time: ${tzAlarm.toString()}'); + _debug('Current time: ${DateTime.now().toUtc().toString()}'); + _debug('${_notifications.toString()}'); } // End Notification Method ***/ @@ -326,7 +347,18 @@ class _HomeScreenState extends State { stopButton: 'Dismiss', icon: 'ic_notification', ), + androidStopAlarmOnTermination: false, ); + + // Skip if tomorrow's alarm already exists. + final existing = await Alarm.getAlarm(_alarmId); + if (existing == settings) { + _debug( + "Alarm already exists, skipping schedule. ${settings.toString()}", + ); + return; + } + await Alarm.set(alarmSettings: settings); } // End Alarm Method ***/ @@ -334,6 +366,10 @@ class _HomeScreenState extends State { } else { _showSnack('Platform Not Detected - Contact Developer'); } + // If we made it this far, refresh the alarm ID on the screen. + setState(() { + _alarmId = _alarmId; + }); } Future _toggleAlarm(bool value) async { @@ -352,11 +388,13 @@ class _HomeScreenState extends State { } else if (Platform.isAndroid) { // Notification Method if (ANDROID_USE_NOTIF) { - await _notifications.cancel(id: _alarmId); + //await _notifications.cancel(id: _alarmId); + await _notifications.cancelAll(); } // Alarm Method if (ANDROID_USE_ALARM) { - await Alarm.stop(_alarmId); + //await Alarm.stop(_alarmId); + await Alarm.stopAll(); } } _showSnack('Alarm Cancelled'); @@ -366,6 +404,14 @@ class _HomeScreenState extends State { ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(msg))); } + void _log(String tag, String msg) { + debugPrint(tag + ": " + msg); + } + + void _debug(String msg) { + _log("DEBUG", msg); + } + @override void dispose() { _savePrefs(); @@ -578,10 +624,11 @@ class _HomeScreenState extends State { child: Text( _validTime ? _alarmEnabled - ? "${_minutesBefore} Minute${_plural} Before @ $_alarmDisplayTime" + ? "Scheduled @ ${_alarmId.toString().replaceRange(4, 4, '-').replaceRange(7, 7, '-')} $_alarmDisplayTime" : "Sunset Alarm" : "Enter Valid Time", ), + // ), value: _validTime ? _alarmEnabled : false, onChanged: _validTime ? _toggleAlarm : null, diff --git a/pubspec.yaml b/pubspec.yaml index 8c5597d..5425037 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: sunset_alarm description: "Set an alarm to go off a specified time before sunset." publish_to: 'none' -version: 1.1.0 +version: 1.2.0 environment: sdk: ^3.7.2