Giter Site home page Giter Site logo

bnobo / needabreak Goto Github PK

View Code? Open in Web Editor NEW
6.0 2.0 3.0 4.7 MB

NEED A BREAK! is an application intended to help you take care of your health while you work on a computer.

License: GNU General Public License v3.0

C# 100.00%
translations care health pinvoke system-events mutex-lock adorners wpf wpf-application csharp

needabreak's Introduction

NEED A BREAK!

Presentation

FOSSA Status

NEED A BREAK! is an open source application intended to help you take care of your health while you work on a computer. It will encourage you to regularly have a break in order to avoid health issues like musculoskeletal disorders, headaches or eye strain.

I have made it for my personal usage and personaly use it every day at work and it helps me to not sit for too long. So I decided to share it because maybe it could be useful to someone else.

You will be notified a minute before lockdown:

imminent lockdown

When it is time to have a break a countdown will appear. The screen will be locked when it reaches 0:

countdown

You can check that the application is running thanks to the task bar icon. Hover the mouse over the icon and you'll see useful information like time remaining before lockdown and today's screen time:

task bar icon

You can display the application menu by clicking on the coffee cup icon in the taskbar:

menu

The settings window let you choose how long the application will wait before lockdown:

settings

You can find this documentation on my github page: https://bnobo.github.io/needabreak/

Installation

You can install the latest version from the Microsoft Store

If you prefer, you can download the version you want to install from the Releases page

Starting with version 3.x you'll need Windows 10 minimum. If you have an older system, you should download a previous version from the Releases page. The latest version before 3.x was 2.3. Please note that previous versions won't benefit from new functionnalities and security updates. You should upgrade your system to benefit from the latest version.

Get started

The project is a WPF application targeting .NET 8. All you need is a copy of Visual Studio Community in order to build it. Once started, the application creates a coffee cup icon in the task bar to manifest its presence and permits user to interact with it. Just click on the coffee cup to open the application menu.

Contribute

I'm sure this application could be improved in many ways and I would be happy to receive some help in doing so. If you want to contribute to this project, please read contributing.md file.

Every kind of contribution is welcome, it includes, but is not limited to:

  • Add new functionalities
  • Improve translations
  • Improve design
  • Fix bugs
  • Test to find issues
  • Fix typos

Locate log file and user settings

The log file of the application can be found under %TEMP%\NeedABreak Logs folder.

Sometimes it is usefull to vary user settings values during debug. In order to easily locate the user settings file of the application, its path is logged when the app starts in debug mode. Open the log file and search for User settings path. You should see a line similar to:

2024-04-20 08:41:39,206 [1] DEBUG - NeedABreak.App User settings path = C:\Users\your_name\AppData\Local\NeedABreak\NeedABreak_Url_zfnovop1ow4emdxnmewxhry05gwrornw\3.0.3.0\user.config

Open the user.config file and change settings values as needed.

Be careful while editing this XML file. If you break it, the application won't start anymore. You should make a backup copy before editing it. In case you accidentally broke it, just delete the user.config file and restart the application. The file will be restored with default values.

Points of interest in code

P/Invoke

Use of P/Invoke to lock workstation:

[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool LockWorkStation();

Use of P/Invoke to check current user notification state in order to automatically suspend the application if a notification would not be appropriate:

[DllImport("shell32.dll")]
static extern int SHQueryUserNotificationStte(outUserNotificationStateuserNotificationState);

Use of P/Invoke to ensure user is idle before poping-up the countdown window:

[DllImport("user32.dll")]
static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);

[DllImport("user32.dll")]		
static extern ushort GetAsyncKeyState(ushort virtualKeyCode);

System events

Use of system events to detect session switch:

Microsoft.Win32.SystemEvents.SessionSwitch += SystemEvents_SessionSwitch;

Mutex

Use of Mutex class to prevent application from beeing launched twice:

mutex = new System.Threading.Mutex(false, "Local\\NeedABreakInstance");
if (!mutex.WaitOne(0, false))
{
    Logger.Info("Application already running");
    Current.Shutdown();
    return;
}

Translations

Use of custom markup extension to handle translations in XAML files like this:

<TextBlock Margin="0 210 0 0"
           Text="{utils:TextResource warranty}" />

Adorner

Use of Adorner class to surround selected tile on the settings window.

Startup Task

Use of StartupTask class in order to run the application at Windows Startup.

The manifest has to be manually edited to add the startup task extension:

[...]
xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10"
[...]
<Applications>
    <Application Id="App"
        [...]
        <Extensions>
            <!-- Desktop Bridge-->
            <desktop:Extension
              Category="windows.startupTask"
              Executable="NeedABreak\NeedABreak.exe"
              EntryPoint="Windows.FullTrustApplication">
              <desktop:StartupTask
                  TaskId="NeedABreak.StartupTask"
                  Enabled="true"
                  DisplayName="NEED A BREAK!" />
            </desktop:Extension>
        </Extensions>
    </Application>
</Applications>

The csproj file has to target Windows 10:

<TargetFramework>net8.0-windows10.0.18362.0</TargetFramework>

And then it is possible to make use of the StartupTask class:

StartupTask startupTask = await StartupTask.GetAsync("NeedABreak.StartupTask");
StartupTaskState newState = await startupTask.RequestEnableAsync();

License

FOSSA Status

needabreak's People

Contributors

armdt avatar bnobo avatar dependabot[bot] avatar fossabot avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

needabreak's Issues

Run at startup does not work with MSIX package

Describe the bug
It seems that access to windows registry is sandboxed when the application is installed using MSIX Package (UWP app). So it is not anymore possible to create a registry key under HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Run in order to automatically run the app at startup.

To Reproduce
Steps to reproduce the behavior:

  1. Check "run at startup"
  2. Reboot
  3. NEED A BREAK! is not started after reboot

Expected behavior
NEED A BREAK! should run at startup when the option is checked

Desktop (please complete the following information):

  • Windows version: 10
  • Application version [e.g. 2.0.0]: 3.0.0

Countdown sometimes start twice [BUG]

Describe the bug
Sometimes the countdown start twice and it causes the progress bar to go back and forth. This bug exists since version 2.1.0 so it is probably related to #62

To Reproduce
The reproduction scenario is not clear.

Desktop (please complete the following information):

  • Windows version: 10
  • Application version [e.g. 2.0.0]: 2.1.0

Win32Exception when clicking on INRS link

Describe the bug
Win32Exception when clicking on INRS link

To Reproduce
Steps to reproduce the behavior:

  1. Go to About
  2. Click on INRS
  3. See error

System.ComponentModel.Win32Exception
HResult=0x80004005
Message=An error occurred trying to start process 'http://www.inrs.fr/risques/travail-ecran/ce-qu-il-faut-retenir.html' with working directory 'C:\Users\benoi\source\repos\github.com\bNobo\needabreak\NeedABreak\bin\Debug\net8.0-windows'. Le fichier spécifié est introuvable.
Source=System.Diagnostics.Process
StackTrace:
at System.Diagnostics.Process.StartWithCreateProcess(ProcessStartInfo startInfo)
at System.Diagnostics.Process.Start(ProcessStartInfo startInfo)
at NeedABreak.AboutBoxWindow.Hyperlink_RequestNavigate(Object sender, RequestNavigateEventArgs e) in C:\Users\benoi\source\repos\github.com\bNobo\needabreak\NeedABreak\AboutBoxWindow.xaml.cs:line 64
at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
at System.Windows.Documents.Hyperlink.NavigateToUri(IInputElement sourceElement, Uri targetUri, String targetWindow)
at System.Windows.Documents.Hyperlink.OnClick()
at System.Windows.Documents.Hyperlink.OnMouseLeftButtonUp(Object sender, MouseButtonEventArgs e)
at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
at System.Windows.UIElement.ReRaiseEventAs(DependencyObject sender, RoutedEventArgs args, RoutedEvent newEvent)
at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
at System.Windows.ContentElement.RaiseTrustedEvent(RoutedEventArgs args)
at System.Windows.Input.InputManager.ProcessStagingArea()
at System.Windows.Input.InputProviderSite.ReportInput(InputReport inputReport)
at System.Windows.Interop.HwndMouseInputProvider.ReportInput(IntPtr hwnd, InputMode mode, Int32 timestamp, RawMouseActions actions, Int32 x, Int32 y, Int32 wheel)
at System.Windows.Interop.HwndMouseInputProvider.FilterMessage(IntPtr hwnd, WindowMessage msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at System.Windows.Interop.HwndSource.InputFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
at System.Windows.Application.RunDispatcher(Object ignore)
at System.Windows.Application.RunInternal(Window window)
at NeedABreak.App.Main()

NB: link should be localized

Keep time left when screen is locked for less than five minutes

Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

Describe the solution you'd like
A clear and concise description of what you want to happen.

Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.

Additional context
Add any other context or screenshots about the feature request here.

Replace "suspend mode" by "do not disturb" mode

The purpose of "suspend mode" is not really clear and can encourage the user to stay in front of their screen for too long (because the countdown is also suspended).

A contrario, the objective of NEEDABREAK! is clear: encourage the user not sit for too long in front of their screen in order to avoid health issues like musculoskeletal disorders, headaches, eye strain.

So "suspend mode" should be remove and replaced by a "do not disturb" mode that would be useful in case of watching a movie or participating to a remote meeting but would not stop the timer. So the user would be invited to make a break as soon as the "do not disturb" mode would be stopped.

Idle detection can be improved

  • The idle delay should be a little bit longer, maybe between 5-10 seconds (ideally it should be personalizable)
  • Mouse buttons state should be taken into account for idle time detection. Use case : the user maintain the button to select a large text file and it takes more than 3 seconds to select all. The countdown appears because user last input was more than 3 seconds ago. Because of this the user selection is interrupted and they have to make it again.

[BUG] Counting time left should continue even when NeedABreak is suspended

Describe the bug
Scenario :

  1. Set auto-suspend ON
  2. Set delay to 90 minutes
  3. Make a visio-conference call or watch a video (the application is suspended during this time)
  4. After some time, let's say one hour stop the video and go back to work

=> Because the timer was suspended during one hour, I still have to wait 90 minutes before the application prompts me to move. The total time before notification will be 150 minutes which is too much. Even if I was inactive I was in front of the screen.

Expected behavior
The notification should not be sent because I don't want to be interrupted when the application is suspended but the timer should continue. For instance if the delay is 90 minutes and I watch a full screen video during one hour, I should be prompted to move 30 minutes after stopping the movie. If the movie last for more than 90 minutes, I should be prompted immediatly after stopping the movie.

The window needs to be resizable

The window which opens after pressing "adjust the wait time before lockdown" is a fixed size so on smaller screens it would be impossible to see the whole window which can create accessibility issues.

Restore countdown after short interruption

When the user reboot its computer, the application is stopped and restarted after Windows startup. The wait remaining before screen lock is then reinitialized and the user won't be notified in time. For example, there could be only 5 minutes left before locking when the reboot occurs. The user will then stay in front of his screen for too long.

=> Store wait remaining when the PC is rebooted and "Launch at startup" is checked.
=> When the application starts, setup the wait accordingly

The easiest way to do this is to store "startTime" and restore it in InitStartTime method.

Display today's screen time

Display today's screen time in the tooltip:

"" (less than 1 minute: nothing to display)
"Today's screen time: 1 minute"
"Today's screen time: 12 minutes"
"Today's screen time: 1 hour"
"Today's screen time: 1 hour, 34 minutes"
"Today's screen time: 2 hours"
"Today's screen time: 2 hours, 56 minutes"

Today's screen time is the time spent in front of the screen between 00:00:00 and 23:59:59

Add a settings window

Describe the solution you'd like
Add a settings window to allow user to parametize idle time

Describe alternatives you've considered
Instead of a new Window it should be possible to add an input box directly on the popup menu. But UX won't be great. Moreover a new window could maybe be used for future settings.

[BUG] Time left not reset after screen lock when "do not disturb" mode is active

Describe the bug
Time left not reset after screen lock when "do not disturb" mode is active

To Reproduce
Steps to reproduce the behavior:

  1. Activate "do not disturb" mode (note time left before locking)
  2. Lock screen
  3. Unloack screen
  4. Time left before locking is not reset

Expected behavior
Time left should be reset to the value selected by the user. (we suppose the user was not in front of their screen when it was locked).

Desktop (please complete the following information):

  • Windows version: 10
  • Application version [e.g. 2.0.0]: 2.3.1

Allow prefered wait time selection

Add a star icon on each tile to allow user to select its favorite wait time. His preference will be saved and restored at startup unless startup follows a reboot and time left was restored (see issue #9)

Pause when an app run in fullscreen

It can be annoying if the countdown raises while the user is watching a movie or playing a game. Is it possible to detect when an application runs in fullscreen mode and pause the application?

[BUG] Manual session locking not detected anymore

Describe the bug
Sometimes when I log into Windows the countdown shows immediately.

To Reproduce
Steps to reproduce the behavior:

  1. Wait for delay to be almost up
  2. Lock windows for a few minutes using Windows+L
  3. Relog to windows
  4. The countdown appears almost immediatly

Expected behavior
When the computer is manually locked using "Windows + L", the countdown should be reset when user relog himself.

Desktop (please complete the following information):

  • Windows version: 10
  • Application version [e.g. 2.0.0]: 2.3.1

Discourage user from selecting "Postpone"

Is your feature request related to a problem? Please describe.
It can be difficult for the user to leave its seat, espacially if they are focused on a problem. However it is specially when you stick on a problem that a break provide the most benefits.

Describe the solution you'd like
The application should request a confirmation if the user request a postpone for the second time and 2 confirmations if they request a postpone for the third time.

Describe alternatives you've considered
Remove the postpone button, but it's too violent

[BUG] About box title bar has the wrong color

Describe the bug
The color of the About Box dialog title bar is the default green of the MahApps.Metro Green theme.

Expected behavior
The color should be #00B570 as on the SettingsWindow

Desktop (please complete the following information):

  • Windows version: Windows 10
  • Application version [e.g. 2.0.0]: 2.0.0

Add an installer

Create an installer in order to permit end-user to easily install and update the application.

The countdown should be on a separate window called CountdownWindow

The MainWindow has two many responsibilities : it is the startup Window, it contains the taskbar icon, menus, balloon tip which are logically placed here but it also contains the countdown before locking. This last element should be handled on a seperate window called CountdownWindow.

Make a logo

I've made the actual logo representing a coffee cup in 5 minutes with Paint 3D. This application certainly deserve a better logo :)

Benoît => Benoit

This template is for everything othen than bug report and feature request.

Add a "lock now !" button on the main window (count down)

Sometimes when the countdown before locking appears there is nothing to save and we just want to lock the screen and leave our seat. Actually we have to wait for the countdown to reach 0 or manually lock the screen using "windows + L". It would be easier if they were a "lock now !" button on the countdown window

Allow wait time personalization

Is your feature request related to a problem? Please describe.
There are situations where user could need a personalized wait time. For e.g. when he hears there will be a meeting in 30 minutes or when he needs to reboot its computer while there are only few minutes left, see #9. In these situations, there is no suitable choice because the selection is limited to 45, 60, 90 and 120 minutes.

Describe the solution you'd like
There should be a slider on the "adjust wait time" window in order to allow the user to select a personalized duration instead of a predefined value.

Describe alternatives you've considered

  1. put the slider on the popup menu instead of "adjust wait time" window but I don't know if it is technically feasible and it seems to me that it is not the most user-friendly solution.
  2. change computer time to mislead the countdown :/

The time remaining before session lockout should be reset when the user puts the PC to sleep

Describe the bug
When I puts the PC to sleep instead of shutting down and restart the day after, the app popups the countdown before lockdown almost immediately.

To Reproduce
Steps to reproduce the behavior:

  1. Put the PC to sleep
  2. Start the PC the day after
  3. After NEED A BREAK! starts we can see that the time remaining is very is "less than one minute"

Expected behavior
The time remaining should be reset

Desktop (please complete the following information):

  • Windows version:11
  • Application version [e.g. 2.0.0]:all

Missing version number on About window

The about window should show the application deployed version. For example, if installed version is 1.2.0, the text of the first line should be

NEED A BREAK! v1.2.0 Copyright (C) 2020 Benoît Rocco

instead of

NEED A BREAK! Copyright (C) 2020 Benoît Rocco

The currently installed version can be obtained with ApplicationDeployment class.

The popup window should appear only when the user is inactive

Is your feature request related to a problem? Please describe.
The popup is often appearing whereas I'm writing or moving the mouse. It is very frustating because I'm interrupted in my work, sometimes in the middle of a word I'm typing or just before I click on a button.

Describe the solution you'd like
The popup window should appear only when the user is inactive (not typing and not moving the mouse). The amount of time to wait for inactiveness should be parametizable.

Review english translations

Application was first developed in french and I have used bing translator to make an english version. I have reviewed translations but i'm not native english speaking so it would be great if someone native could verify translations.

Use squirrel for installation and updates

Is your feature request related to a problem? Please describe.

  • ClickOnce requires a web site to store binaries and a certificate to sign the installer. Currently binaries are stored on GitHub Pages which is quite slow (several seconds to download only 2Mb!).
  • A certificate is expansive so given that it is an open source application with no revenue there is currently no certificate. Final users get a red warning from the UAC each time they download or install the application
  • When there is an update the user has to wait until its installation after having launched the application

Describe the solution you'd like

Create a package nuget from the project and deploy it using Squirrel.Windows

Describe alternatives you've considered

I've considered many alternatives in issue #6 but none of these seem to come close to what Squirrel offers.

Additional context

squirrel.windows

Getting Started Guide

Migrate to .Net Framework 4.8

It will be necessary to create a new branch to keep a version compatible with Windows Vista for users who didn't migrate yet.

[BUG] Update not automatically proposed

Describe the bug
When the app starts automatically at windows startup, the user is never prompted to update. It is mandatory to quit and restart manually via the Windows Start menu in order to be prompted for update.

To Reproduce
Steps to reproduce the behavior:

  1. Check "launch on startup"
  2. Restart Windows
  3. Restart Windows
  4. Restart Windows
  5. ...

=> NEED A BREAK! starts and never update

Expected behavior
NEED A BREAK! should update itselft even when started automatically.

Screenshots
image

Desktop (please complete the following information):

  • Windows version: Windows 11
  • Application version [e.g. 2.0.0]: 2.2.0

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.