What no! I just said it should not be much faster than your existing solution - it just hides the CPU usage better
But it sounds like it could get all the dock badges at once, or does that one call just end up taking all the CPU that the separate calls would have?
In the end it's also just looping over all of the items, that you could do with your existing script as well.
But let's see. I'll add it, then we can do some more tests
Ahhh, I see now! Sorry, I was confused. Standing by to test inside BTT!
I think it could be more efficient since the script is ran only once every N seconds, instead of having to do it for each button (like initial Apple Script
).
I've made some performances experiments with top -pid $( /Applications/Utils/dock-notification-count > /dev/null & echo $! )
but can't really compare it to previous implementation :
Load Avg: 1.51, 1.91, 2.13 CPU usage: 3.53% user, 3.18% sys, 93.28% idle SharedLibs: 228M resident, 45M data, 28M linkedit.
MemRegions: 151217 total, 5093M resident, 155M private, 2303M shared. PhysMem: 14G used (3177M wired), 1755M unused.
VM: 2662G vsize, 1298M framework vsize, 3739548(0) swapins, 4244583(0) swapouts. Networks: packets: 1110609/1837M in, 1670440/1639M out.
Disks: 3592108/56G read, 1569031/39G written.
By the way, @GoldenChaos, when you said "they notoriously hog energy", how were you able to tell it ? By comparing BTT script usage from Activity Monitor with and without script enabled ?
When dock badges were first implemented, they were all enabled by default. Users (including myself) suddenly noticed that our systems were getting one hour of battery life and constantly running at ~20-40% CPU at ridiculous temperatures. @Harrumph made a great post with CPU stats to verify: GoldenChaos-BTT Support and Feedback Thread
The underlying code for dock badges hasn't changed since then. We were unable to find a true solution, all we could do is turn on as few dock badges as possible by default, which led to the current default setup of apple-only apps being enabled.
The holy grail, naturally, is being able to support enabling all dock badges at once by default, eliminating the need for user configuration.
Oh okay I see, indeed it was huuuuge CPU and impact on battery !
So after two days of using it, I can confirm that I don't see any negative impact with my implementation. Still have ~8hours battery life, and CPU absolutely not affected (at least < 10% when doing nothing CPU-consuming).
Even if I add a TouchBar button for every app in my Dock, I'm pretty sure it won't affect performances as the only script running in these buttons is fetching the value from the BTT variable.
Could you try actually doing that (enabling every app) and see what happens? I'm curious...
I think it'll be less too, as only one script looks through the whole dock once and spits out a list which we can store somewhere.
Currently every badge digs into there every second, each making a new (request? i don't have professional knowledge here), added the very low efficiency of applescript too.
@AnthoPak, do you have the seperate exec method setup now or did you figure out how to use the one that spits out a list?
@GoldenChaos I've made the try creating a button for each app in my Dock, and as expected, I don't see any difference. Every new button only executes following script, which can't use too much CPU as it only fetch a variable value :
tell application "BetterTouchTool"
set notificationBadgeApps to get_string_variable "notificationBadgeApps"
end tell
if (notificationBadgeApps contains "Mail") then
return true
else
return ""
end if
@yuuiko I'm currently using the implementation I've posted in #22. This is only calling the helper once, and then every button fetch the last response from the helper. So no need to re-run the helper for each button, therefore no performance issues.
The only thing I regret is not having the ability to create buttons on the fly based on helper response, which could be even better. In current implem, I have to create a button for every Dock app, and each one has to update every 10 seconds to see if app name is contained in saved variable.
BUT ! Something just came to my mind (again…), I could use the helper widget, and without saving the result in a var, use update_touch_bar_widget
from BTT API to change buttons text, and therefore changing their visibility. This would avoid having each button updates every 10 seconds. I may try this when having some time
Interesting. I guess we’re all just waiting for @Andreas_Hegenberg
Will try myself sometime soon too.
i’m also eyeing the add_new_trigger function in btt’s documents
Okay, I've finally found some time and implemented my above suggestion
Works really well ! Only one script for an infinite number of apps
I even tried setting the refreshing time to 0.1s and don't see any performance issue, no difference in CPU usage But of course 0.1 is useless, I'll stick with ~2s I think.
(EDIT : in fact i've just noticed that with 0.1s I got BetterTouchToolAppleScriptRunner
going to ~5% CPU, whereas it almost always < 1% with 2s. But this performance change may mostly be related to widget update)
So basically, here is the process :
- Create a widget for each app we want (in fact a button could be sufficient, but
update_touch_bar_widget
is, as it name suggests, made for widgets and not for classic buttons). I've set the refresh time of these widgets to 10000 (as I don't want them to refresh themselves) - Copy the
UDID
for every button, and add it to following helper widget script - Create the AppleScript helper widget that will update each button when needed, and this script :
UpdateDockBadgesButtons.scpt :
set udidRecords to {Mail:"EE7C0AF6-8406-4278-879F-593CFBCD1000", Messages:"0ECB327C-0CC9-4C12-B300-1BC7210F74B9", Franz:"7E02811B-73E3-458E-967A-9DFD11D101DB"} --All UDIDs from BTT widgets for apps that you are interested in notifications badges
set notificationBadgeApps to (do shell script "/Applications/Utils/dock-notification-count")
-- Can't make a loop here since I can't find a way to fetch records from udidRecords with variable…
checkAndUpdateCurrentBadgeStatusForApp("Mail", notificationBadgeApps, (get Mail of udidRecords))
checkAndUpdateCurrentBadgeStatusForApp("Messages", notificationBadgeApps, (get Messages of udidRecords))
checkAndUpdateCurrentBadgeStatusForApp("Franz", notificationBadgeApps, (get Franz of udidRecords))
return "" --hidden helper widget
on checkAndUpdateCurrentBadgeStatusForApp(appName, notificationBadgeApps, udid)
if notificationBadgeApps contains appName then
updateButtonWithUDID(udid, "show") --here we can try fetching badges count from notificationBadgeApps if we are interested in getting badge count, and replace true with count
else
updateButtonWithUDID(udid, "") --hide button
end if
end checkAndUpdateCurrentBadgeStatusForApp
on updateButtonWithUDID(udidToUpdate, newText)
tell application "BetterTouchTool"
update_touch_bar_widget udidToUpdate text newText
end tell
end updateButtonWithUDID
Still, creating buttons on the fly will be even better so we won't have to deal with UDIDs, but I've also looked into add_new_trigger
and I don't think it could create a button. This could definitely be a great new feature.
Personally I don't mind making a bunch of badges for every app, though being able to create and remove "virtual" buttons on-the-fly is something I've wanted for a while and would make the reminders/calendar/browser tabs groups behave a lot nicer. I might make a separate thread to request this feature, I know it's come up in the past and add_new_trigger
isn't a good option for this because it creates permanent buttons.
@GoldenChaos @yuuiko
Next alpha later today will have a new apple script function that can be used like this:
tell application "BetterTouchTool"
get_dock_badge_for "Calendar" update_interval 5
end tell
When an update interval is provided, BTT will internally refresh the badges for all apps every x seconds. In this case the "get_dock_badge_for" function calls are basically free, as they will just return the last cached value. This is the recommended way to do it, and the update_interval should not be too small.
If you need to refresh the cache immediately for some reason, you can leave the update_interval function out. Then BTT will immediately refresh all the dock badges and return the latest value.
tell application "BetterTouchTool"
get_dock_badge_for "Calendar"
end tell
Instead of the app name you can also use its url (to make it independent from any language), e.g. file:///Applications/Google%20Chrome.app/
Hope this works!!
Will these have a “don’t show when DND ON” function?
Otherwise a dnd variable would be great. A couple of my users are struggling with the badges always hiding and i’m not sure what’s causing it
The function just returns the current dock badge number for the requested app efficiently, what you do with it is up to you
Ok, just added a variable for that. It's available via "SystemDoNotDisturbState" as a number variable.
how does it sense dnd? just curious
It reads the user defaults of the notificationcenterui
NSUserDefaults* defaults = [[NSUserDefaults alloc] initWithSuiteName:@"com.apple.notificationcenterui"];
BOOL dnd = [defaults boolForKey:@"doNotDisturb"];