toast notifications(+) #17
Reference in New Issue
Block a user
No description provided.
Delete Branch "dev/toast_notifications_plus"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Why
I'm looking for a Windows client that can run as a service (or minimized to notifactions tray) -> not just minimized to the task bar so that it runs "in the background" AND that has an option to make the notifications stay up until dismissed (because I'm pushing alerts that are important and need to be seen).
ntfysh-windows already has the first, but by using the default Windows notification tooling, the ability to set the notification to stay for requested time is hampered.
This PR replaces calling the built-in Windows Toast notification for using an animated window. This provides the flexibility to have a timeout progress bar or have an infinite/until-dismissed notification.
What I have done
Make an option to use "custom" notifications (if False - the default - still uses Windows toad notification, if true, use new notification).
That custom WinForm still:
and now:
I also introduced ntfysh_client.Themes namespace which contains a
default
(based on the current Settings dialogue and adarkMode
to allow the user to choose the style/theming of their pop ups.Testing / Demo
Demo: https://youtu.be/BF3kzUK8DR0
Hey there @mshafer1,
I haven't been able to do a full code review yet, but will do so tomorrow when I get the chance.
I think my main response right now would be your use case doesn't fit everyone's requirements. I for one wouldn't like the new notifications and would find them extremely frustrating and distracting, but I can absolutely see the appeal in the more obstructive and attention grabbing style.
I think a full replacement is a little too far, but a good compromise would be to add a configuration option which allows the user to choose which type of notification they would like to receive, with the native Windows one being the default as this is what users so far have come to expect from the application.
I think a config option is a good idea. I contemplated adding that in round
one but thought but wasn't sure if it should be included in the MVP.
I could also see a strong case for making them sized more like before, but
beyond just shrinking it, I would argue non MVP.
I also don't actually want the status/progress bar, as my use-case is
important only (i.e. would be set to not timeout).
Would you rather I take that part back out, or make that a config option as
well.
On Fri, Dec 20, 2024, 18:04 Alexander Horner @.***>
wrote:
A feature MVP should strive to at least not break existing expectations or functionality for sure, so I think it's an important addition for a config option to choose.
You might wish to add an option to show or hide the counter and/or progress bar, but I think it's a good attention catching feature once again and has value.
The size and style could do with being made more consistent with the rest of the application, but for now I would say it works fine
@alexhorner, all right, I got a draft of the settings dialogue updated and have tested that everything but the dark-mode switch works (that's not implemented yet). I'll plan to work on making the default be winForms default colors in the morning.
I noticed this while debugging.... while I didn't do a proper Chesterton's Fence investigation on it, it seem pretty wrong...., I'll dig into history on this more later.
Thaaaat looks like a keyboard ninja tab tab enter move typo 🤣 Was that me? Whoops!
HI @mshafer1
Please see attached review comments for my full code review.
Thanks for your work!
In keeping with established convention please use a _ and remote the this.
Nitpick: newline
This seems a little cursed. If that's the best way to do it, fair enough, but if there's a better way (such as changing the type of
timeout_ms
) that might be better because we're throwing away precision.Can
UseNativeWindowsNotifications
andUseCustomTrayNotifications
not be merged?A blank line between the previous if closure and this one's opening, and a comment consistent with the one above the previous if would be good
Nitpick: newline
Nitpick: One liner?
if (this.shownStopwatch is null) return;
Nitpick: newline
What's the purpose of this override?
Nitpick: newline
This is a great candidate for the new
switch expression
syntax, and then it can be turned into a lambdaNitpick: Lambda one liner
Nitpick: Naming convention is capitalised first letter
Nitpick: Naming convention is capitalised first letter title casing without underscores
Nitpick: convention is use of _ for private variables to avoid the use of this. Goes for all others in this section
This appears to be set but never read outside of the
progress
getterCould this just read
this.progressBar1.Value
instead?Any reason we're wrapping this? Is it protected usually?
Does this need
this
es?Nitpick: newline
Nitpick: newline
Nitpick: newline
Nitpick: Naming convention is capitalised first letter
Nitpick:
timeout_ms
should betimeoutMilliseconds
immediate?
I try to rename my elements to match the TitleCase naming convention. Not a major one, just a nice-to-have. I appreciate this isn't consistent within the application anyway.
@@ -0,0 +41,4 @@
{
// close the current notification
HandleTimeout(null, null);
}
Nitpick: newline
@@ -0,0 +58,4 @@
{
_displayTimeoutTimer.Stop();
_displayTimeoutTimer.Dispose();
}
Nitpick: newline
@@ -0,0 +64,4 @@
{
_updateTimer.Stop();
_updateTimer.Dispose();
}
Nitpick: newline
@@ -0,0 +148,4 @@
{
BringToFront();
AnimateWindow(
Nitpick: newlines
@@ -0,0 +153,4 @@
time: 250,
flags: NFWinUserAnimateWindowConstants.AW_SLIDE | NFWinUserAnimateWindowConstants.AW_VER_NEGATIVE
);
}
Nitpick: newline
@@ -0,0 +170,4 @@
private void UIThreadAnimatedHideWindow(object? sender, EventArgs? e)
{
AnimateWindow(
Nitpick: Newlines, same as earlier
AnimateWindow
example@@ -0,0 +174,4 @@
Handle,
time: 250,
flags: NFWinUserAnimateWindowConstants.AW_SLIDE | NFWinUserAnimateWindowConstants.AW_VER_POSITIVE | NFWinUserAnimateWindowConstants.AW_HIDE
);
Nitpick: newline
@@ -0,0 +269,4 @@
{
_shownStopwatch.Stop();
_shownStopwatch = null;
}
Nitpick: newline
@@ -0,0 +285,4 @@
SoundPlayer loadedSound = new(defaultSoundPath);
loadedSound.Play();
}
Nitpick: newline
@@ -26,1 +69,4 @@
}
#endregion
public SettingsDialog()
Nitpick: Naming convention is capitalised first letter
Nitpick: Naming convention is capitalised first letter
Would it be better to make
0
no timeout requiring closing notifications instead of-1
? My logic behind this is0
is not a valid value anyway, and would result in the immediate closure of the notification, which seems somewhat pointless and a bug. Then we don't end up with an invalid value between two valid values (-1
and1
) and can enforce a minimum value of0
easily.They can. Currently these two are mutually exclusive. Preference between "UseOldNotificationsStyle" (or "New") and making it an enum? I can't imagine a 3rd notification style getting added, but FOSS is not exactly predictable. (i.e., I would lean toward the single boolean)
@alexhorner, is there a linter tool or editor config file that I can setup to check code against the desired style?
I'll change it to seconds and drop the whole conversion. Only reason I made it take mS originally was to create a minimal diff with the old method.
@@ -26,1 +69,4 @@
}
#endregion
public SettingsDialog()
0 for not timeout makes sense. Although, a 0 was valid before.
(but...., If I understand correctly, a default Windows install will ignore anything outside of 1-10 and just use 10 instead, so a 0 before became 10 s, ...., but the way we have it setup now anyone upgrading will have to open the settings dialogue to switch over anyays...)
I'm leaning toward using 0.
I'll change the comment to better explain the desired intent
rationale:
if a user click the x button, they expect the window to go away "now". My observation is that general Windows users are about 50% split on whether a going away animation in response to telling a window to close is annoying or "fine" (and only a few people "prefer it"). Because of this, I intentionally implemented the button close handler to immediately close the pop up (don't animate, and don't wait for the timeout).
I think this is just left over from my first attempts at getting the animation to work.
I tried to rename all new private fields to
_...
and remove all occurrences ofthis.
. It seems to be working.updated
I went through and attempted to add a blank line before every if statement that was not the opening statement of the parent scope (and if preceded by a comment, the blank line went before the comment).
changed
I added a blank line before the if statement
@@ -0,0 +153,4 @@
time: 250,
flags: NFWinUserAnimateWindowConstants.AW_SLIDE | NFWinUserAnimateWindowConstants.AW_VER_NEGATIVE
);
}
I added a blank line before the if statement
@@ -0,0 +148,4 @@
{
BringToFront();
AnimateWindow(
Added
removed
@@ -0,0 +170,4 @@
private void UIThreadAnimatedHideWindow(object? sender, EventArgs? e)
{
AnimateWindow(
added
@@ -0,0 +174,4 @@
Handle,
time: 250,
flags: NFWinUserAnimateWindowConstants.AW_SLIDE | NFWinUserAnimateWindowConstants.AW_VER_POSITIVE | NFWinUserAnimateWindowConstants.AW_HIDE
);
I added a blank line before the call to the parent class
I added a blank line before the if statement
updated
swapped
@@ -0,0 +269,4 @@
{
_shownStopwatch.Stop();
_shownStopwatch = null;
}
I added a blank line before the if statement
@@ -0,0 +285,4 @@
SoundPlayer loadedSound = new(defaultSoundPath);
loadedSound.Play();
}
I added a blank line before the if statement
I think I've addressed all current comments.
I also added in "themes" and implemented the "showCustomNotificationsInDarkMode" switch.
There are some open questions still. I'll update the demo/screen-recording once those are addressed.
interesting....
Settings.Timeout is a
decimal
, but the UI element for changing it is set toincrement=1
. Which means that the only way to get it to not be an int would be to edit the json file by hand...I'm going to mark this as resolved.
removed
yes, I originally thought there would be more to the setter. Removed.
Not in the end. Removed. (I had originally though the UI would be
.SetInfo(...); .Show()
or something, but the way it is now has a better expandability and doesn't use this.no, that's just what style I was used to back when I last worked in C# (removed all)
This got changed to
timeoutSeconds
to deal with corresponding comment inMainForm.cs
I added a blank line before the if statement
I added a blank line before the if statement
heh, wonder where that style came from...
settings dialog is using camelCase for everything....
I think the Pep8 guidance that "consistency within a file is most important" is a good point here.
I opted to make the new things in SettingsDialogue always use camelCase, but changed the NotificationDialogue be TitleCase.
renamed
@@ -0,0 +41,4 @@
{
// close the current notification
HandleTimeout(null, null);
}
I added a blank line before the if statement
@@ -0,0 +58,4 @@
{
_displayTimeoutTimer.Stop();
_displayTimeoutTimer.Dispose();
}
I added a blank line before the if statement
@@ -0,0 +64,4 @@
{
_updateTimer.Stop();
_updateTimer.Dispose();
}
I added a blank line before the if statement
@@ -26,1 +69,4 @@
}
#endregion
public SettingsDialog()
renamed
Changed
Changed to 0 and dropped -1 handling/updating
Could do an enum?
So typically I use Rider (alternatively Resharper) whilst working and it picks out most of these things. As far as I know, what it works on is the microsoft standard convention, so I just use that as it's pretty universal and sensible.
Changed to an enum.
I installed an ran the Rider ide and looked through for additional style changes (and applied the ones that didn't seem to conflict with the previous comments).
@alexhorner, are you accustomed to "reviewer marks conversations as resolved once they confirm they have been addressed" or to "submitter marks conversations as resolved once they have attempted to address them"?
I wouldn't say either to be honest. As long as they remain visible and I can go back and see them I guess you can mark them as resolved once you're satisfied with the solution you have produced.
GitHub kind of tries to hide resolved conversations....
Ah that's a pain. I'm not used to using GitHub code review tools. Too used to DevOps
@alexhorner, do you need anything else from me before doing another round of review?
@mshafer1 Looks fine to me at this point. One bug I have noticed in testing is that in native windows notification mode, the ping sound still plays. This is unnecessary as Windows plays its own sound.
Heh, I hadn't thought of sound.
Let me check on that.
On Thu, Jan 9, 2025, 15:59 Alexander Horner @.***>
wrote:
@alexhorner, I have added a setting for "custom notifications play default Windows sound" and implemented and tested it.
@mshafer1 I'm a fool! The ping sound was coming from the ntfy.sh website I was using during testing. My comment must've been a bit confusing lol, I thought you implemented a custom sound for your notifications too. which played at the same time as the Windows sound, but I see now that you actually just didn't play any sound.
Either way, your latest commit looks good and fixes the real issue, not the one I mistook it for 😛 I have tested and provided a little more review feedback but other than that I think this is a nice addition ready to make its way in
@@ -0,0 +98,4 @@
ProgressBar1.Visible = false;
LblTimeout.Visible = false;
}
Nitpick: One liner & newline
Just made some tweaks for you on this one. I thought it'd be easier to do them and let you read and understand them rather than attempt to explain every tweak to you to try and do yourself when you're not a mind reader
@@ -0,0 +98,4 @@
ProgressBar1.Visible = false;
LblTimeout.Visible = false;
}
applied
Thanks
@alexhorner I was quite surprised when I unmuted my laptop and heard a bell noise on the custom :) (things made a little more sense to me when I switched back to default and also heard the bell -> I wound up muting the site's tab while testing :D)
I have addressed your feedback, and pushed one more commit to deal with the title text continuing to be selected on my machine.
Aha! We both got caught by that one did we? 😆
All looks good to me, thank you for your hard work!
@lucas-bortoli This one should be ready to merge, I have tested. As an aside, would you consider adding me as a maintainer so I may accept pull requests and package and release binaries on the releases page? Thanks!
@lucas-bortoli, any updates? I would like to deploy this soon and would prefer to do so with a build from the shared main branch.
@lucas-bortoli Bump