Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update strings #301

Merged
merged 12 commits into from
Jun 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 12 additions & 5 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,19 @@
android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission
android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
<uses-permission
android:name="android.permission.USE_FULL_SCREEN_INTENT" />
<uses-permission
android:name="android.permission.VIBRATE" />
<uses-permission
android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
<uses-permission android:name="android.permission.USE_EXACT_ALARM" />

<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SYSTEM_EXEMPTED" />

<application
android:label="@string/app_name"
tools:replace="android:label"
Expand Down Expand Up @@ -101,12 +104,16 @@
android:permission="android.permission.BIND_JOB_SERVICE"
android:directBootAware="true"
/>
<service
android:name="com.pravera.flutter_foreground_task.service.ForegroundService"
android:foregroundServiceType="systemExempted"
android:exported="false" />
<!-- <service android:name="me.carda.awesome_notifications.core.services.ForegroundService" -->
<!-- android:enabled="true" -->
<!-- android:exported="false" -->
<!-- android:stopWithTask="true" -->
<!-- android:foregroundServiceType="phoneCall" -->
<!-- tools:replace="android:foregroundServiceType" -->
<!-- android:stopWithTask="false" -->
<!-- android:foregroundServiceType="systemExempted" -->
<!-- tools:replace="android:foregroundServiceType, android:stopWithTask" -->
<!-- ></service> -->
<receiver
android:enabled="true"
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions fastlane/metadata/android/en-US/changelogs/251.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
✨ Enhancements

* Added option to turn on foreground notification to keep app alive. Goto General > Display > Reliability > Show Foreground Notification
* Added current lap card for stopwatch. Now you can view the current lap time in real time.
* Added option to show next alarm in filters
* Updated translations

🐛 Fixes

* Fixed range schedule automatically getttin disabled


2 changes: 1 addition & 1 deletion lib/alarm/data/alarm_settings_schema.dart
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ SettingGroup alarmSettingsSchema = SettingGroup(
DateTimeSetting(
"Date Range",
(context) => AppLocalizations.of(context)!.alarmRangeSetting,
[],
[DateTime.now(), DateTime.now().add(const Duration(days: 2))],
rangeOnly: true,
enableConditions: [
ValueCondition(["Type"], (value) => value == RangeAlarmSchedule)
Expand Down
4 changes: 2 additions & 2 deletions lib/alarm/screens/alarm_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ class _AlarmScreenState extends State<AlarmScreen> {
_showNextAlarm.addListener(update);
_showSort.addListener(update);

ListenerManager.addOnChangeListener("alarms", update);
// ListenerManager.addOnChangeListener("alarms", update);

nextAlarm = getNextAlarm();

Expand All @@ -81,7 +81,7 @@ class _AlarmScreenState extends State<AlarmScreen> {
_showFilters.removeListener(update);
_showSort.removeListener(update);
_showNextAlarm.removeListener(update);
ListenerManager.removeOnChangeListener("alarms", update);
// ListenerManager.removeOnChangeListener("alarms", update);
super.dispose();
}

Expand Down
16 changes: 9 additions & 7 deletions lib/alarm/types/schedules/range_alarm_schedule.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class RangeAlarmSchedule extends AlarmSchedule {
late final AlarmRunner _alarmRunner;
late final DateTimeSetting _datesRangeSetting;
late final SelectSetting<RangeInterval> _intervalSetting;
bool _isFinished = true;
bool _isFinished = false;

RangeInterval get interval => _intervalSetting.value;
DateTime get startDate => _datesRangeSetting.value.first;
Expand Down Expand Up @@ -42,21 +42,23 @@ class RangeAlarmSchedule extends AlarmSchedule {
}

@override
Future<void> schedule(Time time,String description) async {
Future<void> schedule(Time time, String description) async {
// All the dates are not scheduled at once
// Instead we schedule the next date after the current one is finished

DateTime alarmDate = getDailyAlarmDate(time, scheduledDate: startDate);
if (alarmDate.day <= endDate.day) {
await _alarmRunner.schedule(alarmDate,description);
_isFinished = false;
} else {
print('$alarmDate $startDate $endDate');
if (alarmDate.isAfter(endDate)) {
_isFinished = true;
} else {
print("_____________");
await _alarmRunner.schedule(alarmDate, description);
_isFinished = false;
}
}

@override
Future<void> cancel()async {
Future<void> cancel() async {
await _alarmRunner.cancel();
}

Expand Down
1 change: 1 addition & 0 deletions lib/app.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import 'package:clock_app/widgets/logic/update_widgets.dart';
import 'package:dynamic_color/dynamic_color.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter_foreground_task/flutter_foreground_task.dart';
import 'package:get_storage/get_storage.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';

Expand Down
4 changes: 2 additions & 2 deletions lib/common/widgets/fields/date_picker_field.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ import 'package:intl/intl.dart';

class DatePickerField<T> extends StatefulWidget {
const DatePickerField({
Key? key,
super.key,
required this.title,
this.description,
required this.onChanged,
required this.value,
this.rangeOnly = false,
}) : super(key: key);
});

final List<DateTime> value;
final String title;
Expand Down
28 changes: 22 additions & 6 deletions lib/common/widgets/fields/switch_field.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ import 'package:flutter/material.dart';

class SwitchField extends StatefulWidget {
const SwitchField(
{Key? key,
{super.key,
required this.value,
required this.onChanged,
required this.name})
: super(key: key);
required this.name,
this.description = ""});

final String name;
final String description;
final bool value;
final void Function(bool value)? onChanged;

Expand All @@ -19,6 +20,9 @@ class SwitchField extends StatefulWidget {
class _SwitchFieldState extends State<SwitchField> {
@override
Widget build(BuildContext context) {
ThemeData theme = Theme.of(context);
TextTheme textTheme = theme.textTheme;

return Material(
color: Colors.transparent,
child: InkWell(
Expand All @@ -29,9 +33,21 @@ class _SwitchFieldState extends State<SwitchField> {
children: [
Expanded(
flex: 100,
child: Text(
widget.name,
style: Theme.of(context).textTheme.headlineMedium,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 12.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
widget.name,
style: textTheme.headlineMedium,
),
if (widget.description.isNotEmpty) ...[
const SizedBox(height: 4),
Text(widget.description, style: textTheme.bodyMedium)
],
],
),
),
),
const Spacer(),
Expand Down
10 changes: 9 additions & 1 deletion lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -704,5 +704,13 @@
"shortSecondsString": "{seconds}s",
"@shortSecondsString": {},
"showNextAlarm": "Show Next Alarm",
"@showNextAlarm": {}
"@showNextAlarm": {},
"showForegroundNotification": "Show Foreground Notification",
"@showForegroundNotification": {},
"showForegroundNotificationDescription": "Show a persistent notification to keep app alive",
"@showForegroundNotificationDescription": {},
"notificationPermissionDescription": "Allow notifications to be showed",
"@notificationPermissionDescription": {},
"extraAnimationSettingDescription": "Show animations that are not polished and might cause frame drops in low-end devices",
"@extraAnimationSettingDescription": {}
}
3 changes: 3 additions & 0 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'dart:isolate';
import 'dart:ui';

import 'package:android_alarm_manager_plus/android_alarm_manager_plus.dart';
import 'package:awesome_notifications/android_foreground_service.dart';
import 'package:clock_app/alarm/logic/alarm_isolate.dart';
import 'package:clock_app/alarm/logic/update_alarms.dart';
import 'package:clock_app/app.dart';
Expand All @@ -12,6 +13,7 @@ import 'package:clock_app/clock/logic/timezone_database.dart';
import 'package:clock_app/common/data/paths.dart';
import 'package:clock_app/common/utils/debug.dart';
import 'package:clock_app/navigation/types/app_visibility.dart';
import 'package:clock_app/notifications/logic/foreground_task.dart';
import 'package:clock_app/notifications/logic/notifications.dart';
import 'package:clock_app/settings/logic/initialize_settings.dart';
import 'package:clock_app/settings/types/listener_manager.dart';
Expand Down Expand Up @@ -46,6 +48,7 @@ void main() async {
await updateAlarms("Update Alarms on Start");
await updateTimers("Update Timers on Start");
AppVisibility.initialize();
initForegroundTask();

ReceivePort receivePort = ReceivePort();
IsolateNameServer.removePortNameMapping(updatePortName);
Expand Down
72 changes: 68 additions & 4 deletions lib/navigation/screens/nav_scaffold.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'dart:async';
import 'dart:isolate';

import 'package:clock_app/alarm/logic/new_alarm_snackbar.dart';
import 'package:clock_app/alarm/types/alarm.dart';
Expand All @@ -14,8 +15,40 @@ import 'package:clock_app/settings/types/setting.dart';
import 'package:clock_app/system/logic/handle_intents.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_foreground_task/flutter_foreground_task.dart';
import 'package:receive_intent/receive_intent.dart' as intent_handler;

// The callback function should always be a top-level function.
@pragma('vm:entry-point')
void startCallback() {
// The setTaskHandler function must be called to handle the task in the background.
FlutterForegroundTask.setTaskHandler(FirstTaskHandler());
}

class FirstTaskHandler extends TaskHandler {
SendPort? _sendPort;

// Called when the task is started.
@override
void onStart(DateTime timestamp, SendPort? sendPort) async {
_sendPort = sendPort;
}

@override
void onRepeatEvent(DateTime timestamp, SendPort? sendPort) async {}

@override
void onDestroy(DateTime timestamp, SendPort? sendPort) async {}

@override
void onNotificationButtonPressed(String id) {}

@override
void onNotificationPressed() {
FlutterForegroundTask.launchApp("/");
}
}

class NavScaffold extends StatefulWidget {
const NavScaffold({super.key, this.initialTabIndex = 0});

Expand All @@ -29,6 +62,7 @@ class _NavScaffoldState extends State<NavScaffold> {
late int _selectedTabIndex;
late Setting useMaterialNavBarSetting;
late Setting swipeActionSetting;
late Setting showForegroundSetting;
late StreamSubscription _sub;
late PageController _controller;

Expand Down Expand Up @@ -56,8 +90,10 @@ class _NavScaffoldState extends State<NavScaffold> {
ScaffoldMessenger.of(context).removeCurrentSnackBar();
DateTime? nextScheduleDateTime = alarm.currentScheduleDateTime;
if (nextScheduleDateTime == null) return;
ScaffoldMessenger.of(context).showSnackBar(
getSnackbar(getNewAlarmText(context, alarm), fab: true, navBar: true));
ScaffoldMessenger.of(context).showSnackBar(getSnackbar(
getNewAlarmText(context, alarm),
fab: true,
navBar: true));
});
}

Expand Down Expand Up @@ -86,6 +122,25 @@ class _NavScaffoldState extends State<NavScaffold> {
});
}

Future<bool> _updateForegroundNotification(dynamic value) async {
if (!value) {
return FlutterForegroundTask.stopService();
}
if (await FlutterForegroundTask.isRunningService) {
return FlutterForegroundTask.updateService(
notificationTitle: 'Foreground service is running',
notificationText: '',
callback: startCallback,
);
} else {
return FlutterForegroundTask.startService(
notificationTitle: 'Foreground service is running',
notificationText: '',
callback: startCallback,
);
}
}

@override
void initState() {
super.initState();
Expand All @@ -96,16 +151,24 @@ class _NavScaffoldState extends State<NavScaffold> {
.getSetting("Use Material Style");
swipeActionSetting =
appSettings.getGroup("General").getSetting("Swipe Action");
showForegroundSetting = appSettings
.getGroup("General")
.getGroup("Reliability")
.getSetting("Show Foreground Notification");
swipeActionSetting.addListener(update);
useMaterialNavBarSetting.addListener(update);
showForegroundSetting.addListener(_updateForegroundNotification);
_controller = PageController(initialPage: widget.initialTabIndex);
_selectedTabIndex = widget.initialTabIndex;

_updateForegroundNotification(showForegroundSetting.value);
}

@override
void dispose() {
useMaterialNavBarSetting.removeListener(update);
swipeActionSetting.removeListener(update);
showForegroundSetting.removeListener(_updateForegroundNotification);
_sub.cancel();
_controller.dispose();
super.dispose();
Expand All @@ -115,7 +178,8 @@ class _NavScaffoldState extends State<NavScaffold> {
Widget build(BuildContext context) {
Orientation orientation = MediaQuery.of(context).orientation;
final tabs = getTabs(context);
return Scaffold(
return WithForegroundTask(
child: Scaffold(
appBar: orientation == Orientation.portrait
? AppTopBar(
title: Text(
Expand Down Expand Up @@ -218,6 +282,6 @@ class _NavScaffoldState extends State<NavScaffold> {
onTabSelected: _onTabSelected,
)
: null,
);
));
}
}
Loading
Loading