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

Feat/on off for tablet #1464

Merged
merged 10 commits into from
Dec 12, 2024
26 changes: 26 additions & 0 deletions android/app/src/main/kotlin/com/flyweb/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ class MainActivity : FlutterActivity() {
"checkRoot" -> result.success(checkRoot())
"toggleBoxScreenOff" -> toggleBoxScreenOff(call, result)
"toggleBoxScreenOn" -> toggleBoxScreenOn(call, result)
"toggleTabletScreenOff" -> toggleTabletScreenOff(call, result)
"toggleTabletScreenOn" -> toggleTabletScreenOn(call, result)
"connectToNetworkWPA" -> connectToNetworkWPA(call, result)
"addLocationPermission" -> addLocationPermission(call, result)
"grantFineLocationPermission" -> grantFineLocationPermission(call, result)
Expand Down Expand Up @@ -255,6 +257,30 @@ fun connectToNetworkWPA(call: MethodCall, result: MethodChannel.Result) {
}
}
}
private fun toggleTabletScreenOff(call: MethodCall, result: MethodChannel.Result) {
AsyncTask.execute {
try {
val commands = listOf(
"input keyevent 26"
)
executeCommand(commands, result) // Lock the device
} catch (e: Exception) {
handleCommandException(e, result)
}
}
}
private fun toggleTabletScreenOn(call: MethodCall, result: MethodChannel.Result) {
AsyncTask.execute {
try {
val commands = listOf(
"input keyevent 82"
)
executeCommand(commands, result) // Lock the device
} catch (e: Exception) {
handleCommandException(e, result)
}
}
}
private fun grantFineLocationPermission(call: MethodCall, result: MethodChannel.Result) {
AsyncTask.execute {
try {
Expand Down
6 changes: 5 additions & 1 deletion lib/l10n/intl_ar.arb
Original file line number Diff line number Diff line change
Expand Up @@ -394,5 +394,9 @@
"example": "604"
}
}
}
},
"ishaAndFajrOnly": "فقط صلاتي الفجر و العشاء",
"minutesBeforeFajrPrayer": "دقائق قبل وقت صلاة الفجر",
"minutesAfterIshaPrayer": "دقائق بعد وقت صلاة العشاء"

}
27 changes: 15 additions & 12 deletions lib/l10n/intl_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -365,17 +365,17 @@
"installingUpdate": "Installing update...",
"updateCompletedSuccessfully": "Update completed successfully",
"updateFailed": "Update failed",
"save":"Save",
"enterRtspUrl":"Enter RTSP or Youtube Live URL",
"addRtspUrl":"Add your camera stream URL below",
"enableRtspCamera":"Enable Camera Streaming",
"rtspCameraSettings":"Camera Settings",
"invalidRtspUrl":"Invalid URL. Please check the URL and try again.",
"validRtspUrl":"URL validated and saved successfully.",
"rtspCameraSettingTitle":"Live camera connection",
"rtspCameraSettingDesc":"Connect to your local camera and display jumua prayer stream on the TV screen.",
"rtspCameraSettingScreenDesc":"If you enter a URL here, your screen will automatically switch to video streaming when Jumua time arrives",
"validatingStream":"Validating Stream...",
"save": "Save",
"enterRtspUrl": "Enter RTSP or Youtube Live URL",
"addRtspUrl": "Add your camera stream URL below",
"enableRtspCamera": "Enable Camera Streaming",
"rtspCameraSettings": "Camera Settings",
"invalidRtspUrl": "Invalid URL. Please check the URL and try again.",
"validRtspUrl": "URL validated and saved successfully.",
"rtspCameraSettingTitle": "Live camera connection",
"rtspCameraSettingDesc": "Connect to your local camera and display jumua prayer stream on the TV screen.",
"rtspCameraSettingScreenDesc": "If you enter a URL here, your screen will automatically switch to video streaming when Jumua time arrives",
"validatingStream": "Validating Stream...",
"checkInternetLiveCamera": "You must connect to internet to setup the live camera",
"somethingWentWrong": "Something went wrong! please try again",
"somethingWrong": "Something went wrong",
Expand Down Expand Up @@ -409,5 +409,8 @@
"example": "2.0"
}
}
}
},
"ishaAndFajrOnly": "Fajr and Isha prayers only",
"minutesBeforeFajrPrayer": "minutes before fajr prayer time",
"minutesAfterIshaPrayer": "minutes afer isha prayer time"
}
6 changes: 5 additions & 1 deletion lib/l10n/intl_fr.arb
Original file line number Diff line number Diff line change
Expand Up @@ -396,5 +396,9 @@
"example": "604"
}
}
}
},
"ishaAndFajrOnly": "Seulement les prières Fajr et d'Isha",
"minutesBeforeFajrPrayer": "minutes avant l'heure de la prière de Fajr",
"minutesAfterIshaPrayer": "minutes après l'heure de la prière d'Isha"

}
4 changes: 3 additions & 1 deletion lib/src/const/constants.dart
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@ class TurnOnOffTvConstant {
static const String kCheckRoot = "checkRoot";
static const String kToggleBoxScreenOff = "toggleBoxScreenOff";
static const String kToggleBoxScreenOn = "toggleBoxScreenOn";

static const String kToggleTabletScreenOn = "toggleTabletScreenOn";
static const String kToggleTabletScreenOff = "toggleTabletScreenOff";
static const String kisFajrIshaOnly = "isIshaFajrOnly";
Comment on lines +54 to +56
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// After
static const String kIsFajrIshaOnly = "isIshaFajrOnly";

static const String kMinuteBeforeKey = 'selectedMinuteBefore';
static const String kMinuteAfterKey = 'selectedMinuteAfter';
}
Expand Down
24 changes: 11 additions & 13 deletions lib/src/pages/SettingScreen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -416,19 +416,17 @@ class _SettingScreenState extends ConsumerState<SettingScreen> {
style: theme.textTheme.headlineSmall,
textAlign: TextAlign.center,
),
timeShiftManager.isLauncherInstalled
? _SettingItem(
title: S.of(context).screenLock,
subtitle: S.of(context).screenLockDesc,
icon: Icon(Icons.power_settings_new, size: 35),
onTap: () => showDialog(
context: context,
builder: (context) => ScreenLockModal(
timeShiftManager: timeShiftManager,
),
),
)
: SizedBox(),
_SettingItem(
title: S.of(context).screenLock,
subtitle: S.of(context).screenLockDesc,
icon: Icon(Icons.power_settings_new, size: 35),
onTap: () => showDialog(
context: context,
builder: (context) => ScreenLockModal(
timeShiftManager: timeShiftManager,
),
),
),
_SettingItem(
title: S.of(context).appTimezone,
subtitle: S.of(context).descTimezone,
Expand Down
9 changes: 8 additions & 1 deletion lib/src/services/mosque_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ class MosqueManager extends ChangeNotifier with WeatherMixin, AudioMixin, Mosque
bool isToggleScreenActivated = false;
int minuteBefore = 0;
int minuteAfter = 0;
bool isIshaFajrOnly = false;

/// get current home url
String buildUrl(String languageCode) {
Expand All @@ -102,6 +103,11 @@ class MosqueManager extends ChangeNotifier with WeatherMixin, AudioMixin, Mosque
return prefs.getInt(_minuteAfterKey) ?? 10;
}

static Future<bool> getisIshaFajr() async {
final prefs = await SharedPreferences.getInstance();
return prefs.getBool(TurnOnOffTvConstant.kisFajrIshaOnly) ?? false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't forget to fix the typo

}

static Future<bool> checkRoot() async {
try {
final result = await MethodChannel(TurnOnOffTvConstant.kNativeMethodsChannel).invokeMethod(
Expand All @@ -123,7 +129,7 @@ class MosqueManager extends ChangeNotifier with WeatherMixin, AudioMixin, Mosque
isEventsSet = await ToggleScreenFeature.checkEventsScheduled();
minuteBefore = await getMinuteBefore();
minuteAfter = await getMinuteAfter();

isIshaFajrOnly = await getisIshaFajr();
notifyListeners();
}

Expand Down Expand Up @@ -220,6 +226,7 @@ class MosqueManager extends ChangeNotifier with WeatherMixin, AudioMixin, Mosque
ToggleScreenFeature.checkEventsScheduled().then((_) {
if (!isEventsSet) {
ToggleScreenFeature.scheduleToggleScreen(
isIshaFajrOnly,
e.dayTimesStrings(today, salahOnly: false),
minuteBefore,
minuteAfter,
Expand Down
93 changes: 80 additions & 13 deletions lib/src/services/toggle_screen_feature_manager.dart
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before scheduling a new timer, cancel any existing timers for that prayer time.

Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:flutter/services.dart';
import 'package:mawaqit/main.dart';
import 'package:mawaqit/src/const/constants.dart';
import 'package:mawaqit/src/helpers/AppDate.dart';
import 'package:mawaqit/src/helpers/TimeShiftManager.dart';
import 'package:shared_preferences/shared_preferences.dart';

class ToggleScreenFeature {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue: Multiple calls to SharedPreferences.getInstance() in can be inefficient.

Recommendation: Cache the SharedPreferences instance.

  static SharedPreferences? _prefs;

  static Future<SharedPreferences> get _sharedPrefs async {
    if (_prefs == null) {
      _prefs = await SharedPreferences.getInstance();
    }
    return _prefs!;
  }

Expand All @@ -18,11 +19,14 @@ class ToggleScreenFeature {
static final Map<String, List<Timer>> _scheduledTimers = {};

static Future<void> scheduleToggleScreen(
List<String> timeStrings, int beforeDelayMinutes, int afterDelayMinutes) async {
for (String timeString in timeStrings) {
final parts = timeString.split(':');
final hour = int.parse(parts[0]);
final minute = int.parse(parts[1]);
bool isfajrIshaonly, List<String> timeStrings, int beforeDelayMinutes, int afterDelayMinutes) async {
final timeShiftManager = TimeShiftManager();

if (isfajrIshaonly) {
String fajrTime = timeStrings[0];
List<String> parts = fajrTime.split(':');
int hour = int.parse(parts[0]);
int minute = int.parse(parts[1]);

final now = AppDateTime.now();
DateTime scheduledDateTime = DateTime(now.year, now.month, now.day, hour, minute);
Expand All @@ -32,19 +36,60 @@ class ToggleScreenFeature {
}

final beforeDelay = scheduledDateTime.difference(now) - Duration(minutes: beforeDelayMinutes);
if (beforeDelay.isNegative) {
continue;

if (!beforeDelay.isNegative) {
final beforeTimer = Timer(beforeDelay, () {
timeShiftManager.isLauncherInstalled ? _toggleBoxScreenOn() : _toggleTabletScreenOn();
});
_scheduledTimers[fajrTime] = [beforeTimer];
}

String ishaTime = timeStrings[5];
parts = ishaTime.split(':');
hour = int.parse(parts[0]);
minute = int.parse(parts[1]);

scheduledDateTime = DateTime(now.year, now.month, now.day, hour, minute);

if (scheduledDateTime.isBefore(now)) {
scheduledDateTime = scheduledDateTime.add(Duration(days: 1));
}
final beforeTimer = Timer(beforeDelay, () {
_toggleBoxScreenOn();
});

final afterDelay = scheduledDateTime.difference(now) + Duration(minutes: afterDelayMinutes);

final afterTimer = Timer(afterDelay, () {
_toggleBoxScreenOff();
timeShiftManager.isLauncherInstalled ? _toggleBoxScreenOff() : _toggleTabletScreenOff();
});
_scheduledTimers[ishaTime] = [afterTimer];
} else {
// Original logic for all prayer times
for (String timeString in timeStrings) {
final parts = timeString.split(':');
final hour = int.parse(parts[0]);
final minute = int.parse(parts[1]);

final now = AppDateTime.now();
DateTime scheduledDateTime = DateTime(now.year, now.month, now.day, hour, minute);

if (scheduledDateTime.isBefore(now)) {
scheduledDateTime = scheduledDateTime.add(Duration(days: 1));
}

_scheduledTimers[timeString] = [beforeTimer, afterTimer];
final beforeDelay = scheduledDateTime.difference(now) - Duration(minutes: beforeDelayMinutes);
if (beforeDelay.isNegative) {
continue;
}
final beforeTimer = Timer(beforeDelay, () {
_toggleBoxScreenOn();
});

final afterDelay = scheduledDateTime.difference(now) + Duration(minutes: afterDelayMinutes);
final afterTimer = Timer(afterDelay, () {
_toggleBoxScreenOff();
});

_scheduledTimers[timeString] = [beforeTimer, afterTimer];
}
}
await _saveScheduledTimersToPrefs();
}
Expand Down Expand Up @@ -76,7 +121,6 @@ class ToggleScreenFeature {
}).toList(),
);
});

await prefs.setString(_scheduledTimersKey, json.encode(timersMap));
}

Expand All @@ -90,6 +134,11 @@ class ToggleScreenFeature {
return prefs.getBool(TurnOnOffTvConstant.kActivateToggleFeature) ?? false;
}

static Future<bool> getToggleFeatureishaFajrState() async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
return prefs.getBool(TurnOnOffTvConstant.kisFajrIshaOnly) ?? false;
}

static Future<void> cancelAllScheduledTimers() async {
_scheduledTimers.forEach((timeString, timers) {
for (final timer in timers) {
Expand Down Expand Up @@ -120,6 +169,24 @@ class ToggleScreenFeature {
}
}

static Future<void> _toggleTabletScreenOn() async {
try {
await MethodChannel(TurnOnOffTvConstant.kNativeMethodsChannel)
.invokeMethod(TurnOnOffTvConstant.kToggleTabletScreenOn);
} on PlatformException catch (e) {
logger.e(e);
}
}

static Future<void> _toggleTabletScreenOff() async {
try {
await MethodChannel(TurnOnOffTvConstant.kNativeMethodsChannel)
.invokeMethod(TurnOnOffTvConstant.kToggleTabletScreenOff);
} on PlatformException catch (e) {
logger.e(e);
}
}

static Future<bool> checkEventsScheduled() async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
logger.d("value${prefs.getBool("isEventsSet")}");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class ScreenLockNotifier extends AsyncNotifier<ScreenLockState> {
return ScreenLockState(
selectedTime:
DateTime.now().add(Duration(hours: timeShiftManager.shift, minutes: timeShiftManager.shiftInMinutes)),
isfajrIshaonly: prefs.getBool(TurnOnOffTvConstant.kisFajrIshaOnly) ?? false,
isActive: isActive,
selectedMinuteBefore: prefs.getInt(TurnOnOffTvConstant.kMinuteBeforeKey) ?? 10,
selectedMinuteAfter: prefs.getInt(TurnOnOffTvConstant.kMinuteAfterKey) ?? 30,
Expand Down Expand Up @@ -63,9 +64,10 @@ class ScreenLockNotifier extends AsyncNotifier<ScreenLockState> {
state = AsyncValue.data(state.value!.copyWith(selectedMinuteAfter: newMinute < 10 ? 59 : newMinute));
}

Future<void> saveSettings(List<String> times) async {
Future<void> saveSettings(List<String> times, bool isIshaFajrOnly) async {
await ToggleScreenFeature.cancelAllScheduledTimers();
ToggleScreenFeature.scheduleToggleScreen(
isIshaFajrOnly,
times,
state.value!.selectedMinuteBefore,
state.value!.selectedMinuteAfter,
Expand All @@ -75,6 +77,7 @@ class ScreenLockNotifier extends AsyncNotifier<ScreenLockState> {
final prefs = await SharedPreferences.getInstance();
prefs.setInt(TurnOnOffTvConstant.kMinuteBeforeKey, state.value!.selectedMinuteBefore);
prefs.setInt(TurnOnOffTvConstant.kMinuteAfterKey, state.value!.selectedMinuteAfter);
prefs.setBool(TurnOnOffTvConstant.kisFajrIshaOnly, isIshaFajrOnly);
}
}

Expand Down
5 changes: 5 additions & 0 deletions lib/src/state_management/screen_lock/screen_lock_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,29 @@ class ScreenLockState extends Equatable {
final bool isActive;
final int selectedMinuteBefore;
final int selectedMinuteAfter;
final bool isfajrIshaonly;

ScreenLockState({
required this.selectedTime,
required this.isActive,
required this.selectedMinuteBefore,
required this.selectedMinuteAfter,
required this.isfajrIshaonly,
});

ScreenLockState copyWith({
DateTime? selectedTime,
bool? isActive,
int? selectedMinuteBefore,
int? selectedMinuteAfter,
bool? isfajrIshaonly,
}) {
return ScreenLockState(
selectedTime: selectedTime ?? this.selectedTime,
isActive: isActive ?? this.isActive,
selectedMinuteBefore: selectedMinuteBefore ?? this.selectedMinuteBefore,
selectedMinuteAfter: selectedMinuteAfter ?? this.selectedMinuteAfter,
isfajrIshaonly: isfajrIshaonly ?? this.isfajrIshaonly,
);
}

Expand All @@ -32,5 +36,6 @@ class ScreenLockState extends Equatable {
isActive,
selectedMinuteBefore,
selectedMinuteAfter,
isfajrIshaonly,
];
}
Loading
Loading