diff --git a/README.md b/README.md index 2d72740..4b4ceaf 100644 --- a/README.md +++ b/README.md @@ -2,23 +2,21 @@ # StndApp – macOS Menubar App -Current release: [StndApp (Version 0.1.0)](https://github.com/WasAlexHere/stndApp/releases/tag/0.1.0) +Current release: [StndApp (Version 1.0.0)](https://github.com/WasAlexHere/stndApp/releases/tag/1.0.0) ![Screenshot](screenshots/screenshot.png) Menubar app to control stand/sit routine. It will inform you when you need to sit or stand during your work day. Just hit 'Start' button and pay attention to notifications. If you need to take a brake, just hit 'Pause' button and resume when you're ready. -Stand/Sit intervals are 45 and 15 minutes by default, but you can modify them by clicking Edit button. +Stand/Sit intervals are 30 and 30 minutes by default, but you can modify them by clicking 'Edit' button. +If you'ver reached the limit for standing work per a day, the app will tell you to take a rest and continue tomorrow. ## Features - Continuous alerts to stand up (for standing work) and sit down (for sitting work) during a work day. - Start/Pause/Stop functionality. - Displaying time for each routine with corresponding icon. - Modification of sit/stand intervals. - - -## Upcoming ideas - Allow to stand for 4 hours a day. -- Support dark mode. \ No newline at end of file +- Support dark mode. diff --git a/app.py b/app.py index b6f23ea..85c7d02 100644 --- a/app.py +++ b/app.py @@ -1,10 +1,12 @@ import rumps +from datetime import datetime main_icon = "main.png" up_icon = "up.png" down_icon = "down.png" trophy_icon = "trophy.png" edit_icon = "edit.png" +rest_icon = "rest.png" class LessThanAnHour(Exception): @@ -14,8 +16,9 @@ class LessThanAnHour(Exception): class StndApp(rumps.App): def __init__(self): self._seconds = 60 - self._stand_interval = 45 - self._sit_interval = 15 + self._stand_interval = 30 + self._sit_interval = 30 + self._stand_mins_amount = 0 self.config = { "stand": "Alright, alright, alright!", @@ -24,10 +27,15 @@ def __init__(self): "sit_message": f"Sit down for {self._sit_interval} minutes", "failed_value": "Unfortunately, you can only enter integer numbers!", "failed_less": "Unfortunately, you can only enter numbers less than 61!", + "rest": "Hold on, tiger!", + "rest_message": f"You've reached the limit for standing work (4 hours a day). \n" + f"(You're standing hours are {self._stand_mins_amount // 60}). \n" + f"Take a rest and continue tomorrow!", } + self.last_timer = {"last": "stand"} - super(StndApp, self).__init__("stndApp", icon=main_icon) + super(StndApp, self).__init__("stndApp", icon=main_icon, template=True) self.menu = ["Start", "Stop", "Edit", None] # rumps.debug_mode(True) @@ -35,27 +43,33 @@ def __init__(self): self.stand_timer = rumps.Timer(self.countdown_stand, 1) self.sit_timer = rumps.Timer(self.countdown_sit, 1) + self.check_date = rumps.Timer(self.date_validation, 4 * 3600) + self.check_date.start() + self.n = self._stand_interval * self._seconds @rumps.clicked("Start") def start_button(self, sender): - if sender.title == "Start": - if self.last_timer.get("last") == "stand": - self.stand_timer.start() - self.icon = up_icon - self.last_timer["last"] = "stand" + if self._stand_mins_amount / 60 < 4: + if sender.title == "Start": + if self.last_timer.get("last") == "stand": + self.stand_timer.start() + self.icon = up_icon + self.last_timer["last"] = "stand" + else: + self.sit_timer.start() + self.icon = down_icon + self.last_timer["last"] = "sit" + sender.title = "Pause" + self.menu["Edit"].hidden = True else: - self.sit_timer.start() - self.icon = down_icon - self.last_timer["last"] = "sit" - sender.title = "Pause" - self.menu["Edit"].hidden = True + sender.title = "Start" + if self.stand_timer.is_alive(): + self.stand_timer.stop() + if self.sit_timer.is_alive(): + self.sit_timer.stop() else: - sender.title = "Start" - if self.stand_timer.is_alive(): - self.stand_timer.stop() - if self.sit_timer.is_alive(): - self.sit_timer.stop() + self.rest_alert() @rumps.clicked("Stop") def stop_button(self, _): @@ -69,7 +83,7 @@ def stop_button(self, _): self.n = self._stand_interval * self._seconds self.last_timer["last"] = "stand" self.menu["Edit"].hidden = False - self.icon = "main.png" + self.icon = main_icon @rumps.clicked("Edit") def edit_button(self, _): @@ -82,6 +96,7 @@ def edit_button(self, _): if 0 < new < 61: self._stand_interval = new self._sit_interval = 60 - self._stand_interval + self.n = self._stand_interval * self._seconds self.successful_notification() else: self.failed_notification( @@ -114,6 +129,7 @@ def countdown_stand(self, _): "sit", down_icon, ) + self._stand_mins_amount += self._stand_interval if response.clicked == 2: self.stop_button(_) @@ -127,13 +143,17 @@ def countdown_sit(self, _): else: response = self.stand_alert() if response.clicked == 1: - self.change_interval( - self.sit_timer, - self.stand_timer, - self._stand_interval * self._seconds, - "stand", - up_icon, - ) + if self._stand_mins_amount / 60 < 4: + self.change_interval( + self.sit_timer, + self.stand_timer, + self._stand_interval * self._seconds, + "stand", + up_icon, + ) + else: + self.rest_alert() + self.stop_button(_) if response.clicked == 2: self.stop_button(_) @@ -144,7 +164,7 @@ def stand_alert(self): ok="Stand Up", dimensions=(0, 0), ) - window.icon = "trophy.png" + window.icon = trophy_icon window.add_button("Stop") return window.run() @@ -156,7 +176,7 @@ def sit_alert(self): ok="Sit Down", dimensions=(0, 0), ) - window.icon = "trophy.png" + window.icon = trophy_icon window.add_button("Stop") return window.run() @@ -194,6 +214,25 @@ def change_interval(self, func1, func2, num, action, new): self.last_timer["last"] = action self.icon = new + def date_validation(self, _): + current_date = datetime.now() + year = datetime.now().year + month = datetime.now().month + day = datetime.now().day + 1 + + if current_date >= datetime(year, month, day): + self._stand_mins_amount = 0 + + def rest_alert(self): + window = rumps.Window( + title=self.config["rest"], + message=self.config["rest_message"], + dimensions=(0, 0), + ) + window.icon = rest_icon + + return window.run() + if __name__ == "__main__": StndApp().run() diff --git a/down.png b/down.png index 3acf175..da2378e 100644 Binary files a/down.png and b/down.png differ diff --git a/main.png b/main.png index 5d6fed0..aecf69d 100644 Binary files a/main.png and b/main.png differ diff --git a/rest.png b/rest.png new file mode 100644 index 0000000..d33a7e9 Binary files /dev/null and b/rest.png differ diff --git a/setup.py b/setup.py index 213f630..6f440f7 100644 --- a/setup.py +++ b/setup.py @@ -1,12 +1,12 @@ from setuptools import setup APP = ["app.py"] -DATA_FILES = ["main.png", "up.png", "down.png", "trophy.png", "edit.png"] +DATA_FILES = ["main.png", "up.png", "down.png", "trophy.png", "edit.png", "rest.png"] OPTIONS = { 'argv_emulation': True, 'iconfile': 'icon.icns', 'plist': { - 'CFBundleShortVersionString': '0.1.0', + 'CFBundleShortVersionString': '1.0.0', 'LSUIElement': True, }, 'packages': ['rumps'], diff --git a/up.png b/up.png index a4d03a1..ab5ae05 100644 Binary files a/up.png and b/up.png differ