In the example above, the button handler is a function that runs in loop(), copy&paste that and the associated global vars.
The 4 ms button history shows the last 8 reads, in binary it's a picture. 0's and 1's mixed is bounce, all 0 or 1 is a held state, 10000000 and 01111111 are change+stable detections in a 4ms period. Buttons clean or dirty all end in the same pictures/values.
To the functions you add
If button==picture then do something. Is that hard?
The between read period can be changed. History can be 16 or 32 or even 64 bits though to me it'd be wasting RAM. The history needs to cover stability + 1 read to detect change+stable where stable is > the longest bounce.
Any time the sketch wants button state, the picture is there without waiting and it will compare as a value.