Skip to content

Comments

Apply new notification thresholds only after timeout expires#777

Merged
GyulyVGC merged 13 commits intoGyulyVGC:mainfrom
vcrn:update-finished-typing
May 21, 2025
Merged

Apply new notification thresholds only after timeout expires#777
GyulyVGC merged 13 commits intoGyulyVGC:mainfrom
vcrn:update-finished-typing

Conversation

@vcrn
Copy link
Contributor

@vcrn vcrn commented Apr 13, 2025

Changes to notifications settings are stored temporarily in temp_notifications field. These are saved to configs only after a timeout has expired. The checking of this timeout and whether there's any new notifications settings to store are done in TickInit and TickRun arms of fn update().

Changes to notifications settings are stored temporarily in
temp_notifications field. These are saved to configs only after a
timeout has expired. The checking of this timeout and whether there's
any new notifications settings to store are done in `TickInit` and
`TickRun` arms of `fn update()`.
@vcrn
Copy link
Contributor Author

vcrn commented Apr 13, 2025

This should close #658.

I tried some different approaches but finally decided to put this one up for review since this implementation is the most straightforward one to me, and the one that is the most consistent with existing design.

Note that it's not just the notifications thresholds that are instantly applied, but all notifications settings.

What do you think? Some things that bother is that the checking whether to update the notifications settings is done for every Tick, and that the very first if-state if !self.timing_events.was_just_notifications_edit() will be true for a majority of the time that the app is running.

By the way, when looking at the docs for TickInit and TickRun, it seems like TickInit should be every 5 seconds and TickRun every second, but they both use PERIOD_TICK, which is 1 second. Is that something that should be changed?

@GyulyVGC GyulyVGC added the enhancement New feature, request, or improvement label Apr 13, 2025
@GyulyVGC GyulyVGC added this to the v1.4.0 milestone Apr 13, 2025
@GyulyVGC
Copy link
Owner

GyulyVGC commented Apr 20, 2025

Some remarks from a quick review.

  • 1. this behavior should only apply to threshold changes

  • 2. no need to update notification settings in TickInit since notifications won't be received in the initial page of the app; you can just call the update to notifications inside Sniffer::refresh_data (fixed)

  • 3. no need to store the configurations as part of notifications update; in fact, changes to the configuration file are only done during app shutdown (fixed)

@vcrn
Copy link
Contributor Author

vcrn commented Apr 20, 2025

Thank you for the fast review! I'll fix the remaining point you brought up in the coming days and fix the failing test

@vcrn
Copy link
Contributor Author

vcrn commented Apr 23, 2025

Now the thresholds are the only notifications settings that aren't applied right away.

I went a bit back and forth between what type to store the not yet applied thresholds as, experimenting between using Option<(PacketNotification, BytesNotification)> and Option<Notifications>. I went with the latter since I believe it makes the code somewhat simpler, but there's merit to using the other type as well in case you want me to go that route.

@vcrn vcrn changed the title Apply new notifications settings only after timeout expires Apply new notification thresholds only after timeout expires Apr 24, 2025
@GyulyVGC
Copy link
Owner

GyulyVGC commented Apr 24, 2025

Haven't re-reviewed the code yet, but I notice an issue by simply testing via running Sniffnet: if I click on the checkbox to enable/disable a specific notification kind, the corresponding notifications are enabled/disabled with some latency... hence I suspect that enabling/disabling is still subject to the timeout.

@vcrn
Copy link
Contributor Author

vcrn commented Apr 24, 2025

Thanks! I'll get it fixed and get back to you. I'll see if I can expand the testing to check for this scenario

@GyulyVGC
Copy link
Owner

Thank you!

@GyulyVGC GyulyVGC marked this pull request as draft May 1, 2025 21:33
@vcrn
Copy link
Contributor Author

vcrn commented May 6, 2025

If the user changes the ByteMultiple of BytesNotification, do you think that should be applied immediately?

@GyulyVGC
Copy link
Owner

GyulyVGC commented May 6, 2025

If the user changes the ByteMultiple of BytesNotification, do you think that should be applied immediately?

No. The Byte multiplier is part of the threshold and is set via the text input, so its modification has to be subject to timeout.

@vcrn
Copy link
Contributor Author

vcrn commented May 7, 2025

I've gone with the other approach of storing the temporary thresholds, in a field of type Option<(PacketNotification, BytesNotification)>.

@GyulyVGC
Copy link
Owner

GyulyVGC commented May 7, 2025

Is the PR ready for review?

@vcrn vcrn marked this pull request as ready for review May 7, 2025 13:16
@vcrn
Copy link
Contributor Author

vcrn commented May 7, 2025

Yes, ready for review :)

// Threshold adjustments are saved in `self.temp_thresholds` and then applied
// after timeout, but for simplicity, this field is always updated to whatever the
// latest change has been.
self.update_sound(notification, emit_sound);
Copy link
Owner

Choose a reason for hiding this comment

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

Do we really need to have all these different methods to update notification values? Can't we merge all of them into one that updates everything except thresholds to make the code more compact?

Copy link
Owner

Choose a reason for hiding this comment

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

Also, I think these could be an impl of Notifications structs rather than Sniffer struct.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure! I tried out different approaches, and went this since although it's quiet verbose, it's very explicit what's going on. Having it in one method looked quiet convoluted in the end when I tried it, but I'll give it another go, I'll probably have some new ideas of how to make it cleaner :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've tried having this an an impl of Notifications instead, but I believe it will make things more complicated. The majority of the code in these methods are to unpack and compare notifications settings and finally potentially apply them immediately. If we put it in impl Notifications we won't be able to apply them, which in my mind would cause an extra layer somewhere else in the code. What do you think?

Copy link
Owner

Choose a reason for hiding this comment

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

Then you can leave it as Sniffer's impl but try to make it just one method that's less verbose

/// Host data for filter dropdowns (comboboxes)
pub host_data_states: HostDataStates,
/// Temporary storage for thresholds while editing.
pub temp_thresholds: Option<(PacketsNotification, BytesNotification)>,
Copy link
Owner

@GyulyVGC GyulyVGC May 8, 2025

Choose a reason for hiding this comment

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

I suggest this to be part of the field TimingEvents::threshold_adjust like (std::time::Instant, Option<(PacketsNotification, BytesNotification)>).
This way you can update it when you call threshold_adjust_now, and you can make was_just_threshold_adjust return an Option instead of bool.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good idea, I'll implement this!

@GyulyVGC GyulyVGC marked this pull request as draft May 8, 2025 13:14
@GyulyVGC
Copy link
Owner

Hey @vcrn how're you doing?

I just wanted you to know that in a few days I'll merge #795 into main.
Since that is a huge PR and would cause many conflicts, I'd like to have this one finished and merged first if possible.

@vcrn
Copy link
Contributor Author

vcrn commented May 18, 2025

Thanks for the heads-up! I'll try to get something pushed by the end of the day

@vcrn
Copy link
Contributor Author

vcrn commented May 18, 2025

I have something in place that is a bit rough but it does what it's supposed to do. Since this latest round is more concerning design, I'm considering slightly polishing what I have and pushing it to hear your thoughts on these changes. What do you think?

@GyulyVGC
Copy link
Owner

IIRC the last time I tested the most recent commit, it was already working fine from a functional perspective.
So yeah, the main concern was about making it more compact since I think there was too much code for what we're trying to do.

@vcrn
Copy link
Contributor Author

vcrn commented May 18, 2025

Not sure why clippy failed in the pipeline for MacOS but not the others (Linux at least fine when I run it locally, but the build was cancelled in the pipeline, I guess since MacOS failed before that).

Anyway, clippy for MacOS complains about some code I haven't touched, so you better be the judge of whether it should be changed or ignored.

Regarding my latest change, I created one big method that handles all the logic of updating notifications settings and temporary thresholds. Macros could probably decrease the lines of code, but I tried to keep repetition and abstraction layers to a minimum to get your feedback on which way we should go.

I'll also add a comment here on GitHub for a function that I think needs some extra attention.

@vcrn vcrn marked this pull request as ready for review May 18, 2025 12:06
}

/// If timeout has expired, take temporary thresholds
pub fn threshold_adjust_expired_take(
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Pretty bad name, but I wanted it to be clear that it mutates the value. Also, the logic is changed, since we want a value to returned/taken if enough time has passed: compared with previous version, where true was returned if not enough time had passed.

Copy link
Owner

Choose a reason for hiding this comment

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

I'd call it was_just_threshold_adjust_take.

Copy link
Owner

Choose a reason for hiding this comment

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

and turn the logic the way round if possible, otherwise leave it as it is

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't believe we'll be able to change the behavior of "if timeout has expired, return taken value, else None". If this is the case, I can add a doc string explaining how the method works.

Also, could potentially go with the name was_not_just_threshold_adjust_take, to try and point out the somewhat reversed behavior compared with the other methods since to most people false ~ None, true ~ Some. At the cost of making the name more convoluted.

Copy link
Owner

Choose a reason for hiding this comment

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

I'll think to it and will personally take care of it during the review 👍

@GyulyVGC
Copy link
Owner

Thanks will check this out.
Don't worry about clippy, I'll fix it. By the way, it's due to the new clippy lints recently added in the latest version of Rust.

@vcrn
Copy link
Contributor Author

vcrn commented May 18, 2025

Yeah, after updating my toolchain it's failing on Linux as well. A bit odd that it isn't failing for Windows though, but maybe it isn't up to date

@GyulyVGC
Copy link
Owner

On Windows the CI/CD is skipped in PRs since they need a secret environment variable to be set at the repo level (used to download Npcap).

@GyulyVGC GyulyVGC merged commit 47e219a into GyulyVGC:main May 21, 2025
1 of 3 checks passed
@GyulyVGC
Copy link
Owner

Finally merged 🎉

Thanks mate, I hope I wasn't too pedantic during the process 🤣

@all-contributors please add @vcrn for code

@allcontributors
Copy link
Contributor

@GyulyVGC

I've put up a pull request to add @vcrn! 🎉

@vcrn
Copy link
Contributor Author

vcrn commented May 22, 2025

Finally merged 🎉

Thanks mate, I hope I wasn't too pedantic during the process 🤣

@all-contributors please add @vcrn for code

Don't worry, you weren't too pedantic, you we're great! 🙂 Really enjoyed this PR and learned some stuff as well.

I'll be on the look out for other issues I can help out with. Thanks again for a great app and for all your work!

@allcontributors
Copy link
Contributor

@vcrn

@vcrn already contributed before to code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature, request, or improvement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Threshold values for notifications immediately get updated while the user is still typing

2 participants