Skip to content
Open
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
41 changes: 21 additions & 20 deletions lib/app/modules/timer/controllers/timer_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,23 @@ import 'package:ultimate_alarm_clock/app/data/models/timer_model.dart';
import 'package:ultimate_alarm_clock/app/data/providers/isar_provider.dart';
import 'package:ultimate_alarm_clock/app/utils/utils.dart';


class LimitRange extends TextInputFormatter {
LimitRange(this.minRange, this.maxRange) : assert(minRange < maxRange);
final int minRange;
final int maxRange;

@override
TextEditingValue formatEditUpdate(TextEditingValue oldValue, TextEditingValue newValue) {
TextEditingValue formatEditUpdate(
TextEditingValue oldValue, TextEditingValue newValue) {
try {
if (newValue.text.isEmpty) {
return newValue;
}
int value = int.parse(newValue.text);
if (value < minRange) return TextEditingValue(text: minRange.toString());
else if (value > maxRange) return TextEditingValue(text: maxRange.toString());
if (value < minRange)
return TextEditingValue(text: minRange.toString());
else if (value > maxRange)
return TextEditingValue(text: maxRange.toString());
return newValue;
} catch (e) {
debugPrint(e.toString());
Expand All @@ -40,21 +42,20 @@ class TimerController extends FullLifeCycleController with FullLifeCycleMixin {
ScrollController scrollController = ScrollController();
RxList timers = [].obs;
RxList isRinging = [].obs;


final TextEditingController inputHoursControllerTimer = TextEditingController(text: '0');
final TextEditingController inputMinutesControllerTimer = TextEditingController(text: '1');
final TextEditingController inputSecondsControllerTimer = TextEditingController(text: '0');



final TextEditingController inputHoursControllerTimer =
TextEditingController(text: '0');
final TextEditingController inputMinutesControllerTimer =
TextEditingController(text: '1');
final TextEditingController inputSecondsControllerTimer =
TextEditingController(text: '0');

final isTimePickerTimer = false.obs;



void changeTimePickerTimer() {
isTimePickerTimer.value = !isTimePickerTimer.value;
}



void setTimerTime() {
try {
int hours = int.parse(inputHoursControllerTimer.text);
Expand All @@ -68,7 +69,6 @@ class TimerController extends FullLifeCycleController with FullLifeCycleMixin {
}
}


void setTextFieldTimerTime() {
inputHoursControllerTimer.text = hours.value.toString();
inputMinutesControllerTimer.text = minutes.value.toString();
Expand Down Expand Up @@ -162,7 +162,7 @@ class TimerController extends FullLifeCycleController with FullLifeCycleMixin {
}

cancelTimer() async {
await timerChannel.invokeMethod('cancelTimer');
await timerChannel.invokeMethod('clearTimerNotif');
}

@override
Expand Down Expand Up @@ -195,8 +195,9 @@ class TimerController extends FullLifeCycleController with FullLifeCycleMixin {
Get.back();
}
}

Future<void> setPresetTimer(Duration presetDuration) async {
remainingTime.value = presetDuration;
await createTimer();
}
remainingTime.value = presetDuration;
await createTimer();
}
}
23 changes: 18 additions & 5 deletions lib/app/modules/timerRing/controllers/timer_ring_controller.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'dart:async';

import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:flutter_fgbg/flutter_fgbg.dart';
import 'package:get/get.dart';
Expand All @@ -10,20 +11,22 @@ import 'package:vibration/vibration.dart';

class TimerRingController extends GetxController {
MethodChannel timerChannel = const MethodChannel('timer');
MethodChannel alarmChannel = const MethodChannel('ulticlock');
Timer? vibrationTimer;
late StreamSubscription<FGBGType> _subscription;
getFakeTimerModel()async {
TimerModel fakeTimer = await Utils.genFakeTimerModel();
return fakeTimer;
getFakeTimerModel() async {
TimerModel fakeTimer = await Utils.genFakeTimerModel();
return fakeTimer;
}

@override
void onInit() async {
super.onInit();

// Preventing app from being minimized!
_subscription = FGBGEvents.stream.listen((event) {
if (event == FGBGType.background) {
timerChannel.invokeMethod('bringAppToForeground');
bringAppToForegroundForTest();
}
});
vibrationTimer =
Expand All @@ -32,7 +35,17 @@ class TimerRingController extends GetxController {
});
AudioUtils.playTimer(alarmRecord: await getFakeTimerModel().value);

await timerChannel.invokeMethod('cancelTimer');
await clearTimerNotificationForTest();
}

@visibleForTesting
Future<void> bringAppToForegroundForTest() async {
await alarmChannel.invokeMethod('bringAppToForeground');
}

@visibleForTesting
Future<void> clearTimerNotificationForTest() async {
await timerChannel.invokeMethod('clearTimerNotif');
}

@override
Expand Down
80 changes: 80 additions & 0 deletions test/app/modules/timer/timer_channel_contract_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:ultimate_alarm_clock/app/modules/timer/controllers/timer_controller.dart';
import 'package:ultimate_alarm_clock/app/modules/timerRing/controllers/timer_ring_controller.dart';

void main() {
TestWidgetsFlutterBinding.ensureInitialized();

const timerChannel = MethodChannel('timer');
const alarmChannel = MethodChannel('ulticlock');

setUp(() {
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
.setMockMethodCallHandler(timerChannel, (_) async => null);
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
.setMockMethodCallHandler(alarmChannel, (_) async => null);
});

tearDown(() {
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
.setMockMethodCallHandler(timerChannel, null);
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
.setMockMethodCallHandler(alarmChannel, null);
});

test(
'TimerController cancelTimer uses the implemented timer notification clear method',
() async {
MethodCall? capturedCall;
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
.setMockMethodCallHandler(timerChannel, (call) async {
capturedCall = call;
return null;
});

final controller = TimerController();
await controller.cancelTimer();

expect(capturedCall?.method, 'clearTimerNotif');
});

test('TimerRingController foreground recovery uses the alarm channel',
() async {
MethodCall? timerCall;
MethodCall? alarmCall;

TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
.setMockMethodCallHandler(timerChannel, (call) async {
timerCall = call;
return null;
});
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
.setMockMethodCallHandler(alarmChannel, (call) async {
alarmCall = call;
return null;
});

final controller = TimerRingController();
await controller.bringAppToForegroundForTest();

expect(timerCall, isNull);
expect(alarmCall?.method, 'bringAppToForeground');
});

test(
'TimerRingController clears timer notifications through the timer channel',
() async {
MethodCall? timerCall;
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
.setMockMethodCallHandler(timerChannel, (call) async {
timerCall = call;
return null;
});

final controller = TimerRingController();
await controller.clearTimerNotificationForTest();

expect(timerCall?.method, 'clearTimerNotif');
});
}