-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Added shared pref methods * Added required packages * Implemented force mode and split widgets * Enabled windows and linux * config native for window manager package * bump app version * Revert rule value * fix minor issue on nodejs * Used minimize instead of hide window when 20s over * try fix dmg build issue * Improved force mode checkbox and split rule text as widget * updated readme * Split countDownscreen on separate file * Updated notification message base on case & enable fullscreen for 20s * Renamed handleWindowState method * Show message when take break on app * minor fix * Minor improve on force mode checkbox
- Loading branch information
1 parent
22a809f
commit aa5fdf4
Showing
42 changed files
with
1,934 additions
and
193 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -94,14 +94,9 @@ jobs: | |
working-directory: ${{ matrix.build_path }} | ||
- name: Setup Node.js environment | ||
uses: actions/setup-node@v2 | ||
with: | ||
node-version: '14' | ||
- name: Convert build to dmg for macOS | ||
if: matrix.target == 'macOS' | ||
run: | | ||
brew install [email protected] | ||
npm config set python /usr/local/bin/python3.9 | ||
npm install -g appdmg | ||
run: npm install -g appdmg | ||
- name: run appdmg | ||
if: matrix.target == 'macOS' | ||
run: appdmg installer/dmg_creator/config.json $GITHUB_WORKSPACE/EyesCare${{ matrix.target }}.dmg | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,190 @@ | ||
import 'package:eyes_care/main.dart'; | ||
import 'package:flutter/material.dart'; | ||
import 'package:rocket_timer/rocket_timer.dart'; | ||
import 'package:window_manager/window_manager.dart'; | ||
import 'package:eyes_care/shared_pref.dart'; | ||
import 'package:eyes_care/widgets/force_mode_check_box.dart'; | ||
import 'package:eyes_care/widgets/rule_text.dart'; | ||
import 'package:eyes_care/widgets/rule_timer.dart'; | ||
import 'package:local_notifier/local_notifier.dart'; | ||
|
||
class CountdownScreen extends StatefulWidget { | ||
const CountdownScreen({super.key}); | ||
|
||
@override | ||
CountdownScreenState createState() => CountdownScreenState(); | ||
} | ||
|
||
const int rule = 20; | ||
const duration = Duration(minutes: rule); | ||
const size = Size(400, 400); | ||
|
||
class CountdownScreenState extends State<CountdownScreen> with WindowListener { | ||
late RocketTimer _timer; | ||
bool inProgress = false; | ||
late ValueNotifier<bool> forceModeEnabled = ValueNotifier(false); | ||
int followed = 0; | ||
WindowOptions windowOptions = const WindowOptions( | ||
windowButtonVisibility: false, | ||
size: size, | ||
minimumSize: size, | ||
maximumSize: size, | ||
center: true, | ||
backgroundColor: Colors.transparent, | ||
skipTaskbar: false, | ||
titleBarStyle: TitleBarStyle.hidden, | ||
); | ||
|
||
@override | ||
void initState() { | ||
setUpForceMode(); | ||
windowManager.waitUntilReadyToShow(windowOptions, () async { | ||
await windowManager.show(); | ||
await windowManager.focus(); | ||
}); | ||
windowManager.addListener(this); | ||
localNotifier.setup( | ||
appName: 'CareYourEyes', | ||
shortcutPolicy: ShortcutPolicy.requireCreate, | ||
); | ||
super.initState(); | ||
initTimer(); | ||
} | ||
|
||
void initTimer() { | ||
_timer = RocketTimer(type: TimerType.countdown, duration: duration); | ||
_timer.addListener(() { | ||
if (_timer.kDuration == 0) { | ||
showNotification(); | ||
_timer.kDuration = inProgress ? duration.inSeconds : rule; | ||
inProgress = !inProgress; | ||
setState(() {}); | ||
} | ||
}); | ||
_timer.start(); | ||
} | ||
|
||
setUpForceMode() { | ||
PreferenceService.getBool(PreferenceService.forceModeKey).then((value) { | ||
forceModeEnabled.value = value ?? false; | ||
}); | ||
} | ||
|
||
@override | ||
Future<void> onWindowMinimize() async { | ||
if (forceModeEnabled.value) { | ||
await handleWindowState(); | ||
} | ||
super.onWindowMinimize(); | ||
} | ||
|
||
@override | ||
Future<void> onWindowBlur() async { | ||
if (forceModeEnabled.value) { | ||
await handleWindowState(); | ||
} | ||
super.onWindowBlur(); | ||
} | ||
|
||
Future<void> handleWindowState() async { | ||
if (inProgress) { | ||
await windowManager.show(); | ||
await windowManager.focus(); | ||
await windowManager.setFullScreen(true); | ||
} else { | ||
windowManager.minimize(); | ||
await windowManager.setFullScreen(false); | ||
} | ||
} | ||
|
||
@override | ||
void dispose() { | ||
_timer.dispose(); | ||
windowManager.removeListener(this); | ||
super.dispose(); | ||
} | ||
|
||
Future<void> showNotification() async { | ||
LocalNotification notification = LocalNotification( | ||
title: inProgress ? "Stay Focused 💪" : "Take a Moment 🌟", | ||
body: inProgress | ||
? "Keep your gaze on the screen. Remember, every 20 minutes, take a 20-second break looking at something 20 feet away." | ||
: "Step back from the screen and focus on something 20 feet away for 20 seconds. Your eyes will thank you!", | ||
); | ||
notification.onShow = _onShowNotification; | ||
notification.show(); | ||
} | ||
|
||
_onShowNotification() async { | ||
if (forceModeEnabled.value) { | ||
await handleWindowState(); | ||
} | ||
} | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return Scaffold( | ||
appBar: AppBar( | ||
title: const Text('Eyes Care'), | ||
centerTitle: true, | ||
actions: [ | ||
AnimatedBuilder( | ||
animation: _timer, | ||
builder: (context, _) { | ||
return IconButton( | ||
icon: Icon(_timer.status == TimerStatus.pause | ||
? Icons.play_arrow | ||
: Icons.pause), | ||
onPressed: () { | ||
if (_timer.status == TimerStatus.pause) { | ||
_timer.start(); | ||
} else { | ||
_timer.pause(); | ||
} | ||
}, | ||
); | ||
}), | ||
IconButton( | ||
onPressed: _timer.restart, icon: const Icon(Icons.restart_alt)), | ||
IconButton( | ||
onPressed: windowManager.minimize, | ||
icon: const Icon(Icons.minimize_rounded)), | ||
], | ||
leading: ValueListenableBuilder( | ||
valueListenable: themeNotifier, | ||
builder: (context, _, __) { | ||
final isLight = themeNotifier.value.index == 1; | ||
return IconButton( | ||
onPressed: () { | ||
themeNotifier.value = | ||
isLight ? ThemeMode.dark : ThemeMode.light; | ||
}, | ||
icon: Icon(isLight ? Icons.dark_mode : Icons.light_mode)); | ||
})), | ||
body: Container( | ||
padding: const EdgeInsets.all(8.0), | ||
child: Flex( | ||
direction: inProgress ? Axis.vertical : Axis.horizontal, | ||
mainAxisAlignment: MainAxisAlignment.center, | ||
crossAxisAlignment: CrossAxisAlignment.center, | ||
children: [ | ||
Expanded( | ||
child: Column( | ||
mainAxisAlignment: MainAxisAlignment.center, | ||
children: [ | ||
if (inProgress) | ||
Text( | ||
"look away from your screen and focus on something 20 feet away for 20 seconds.", | ||
style: Theme.of(context).textTheme.headlineMedium) | ||
else | ||
const RuleText(), | ||
ForceModeCheckBox(forceModeEnabled: forceModeEnabled) | ||
], | ||
), | ||
), | ||
RuleTimer(timer: _timer, inProgress: inProgress), | ||
], | ||
)), | ||
); | ||
} | ||
} |
Oops, something went wrong.