Mr Pennyworth Posted November 8, 2020 Share Posted November 8, 2020 (edited) Link to better quality videos Download the code and play around: https://github.com/mr-pennyworth/alfred-extra-pane Q: What is it? A: An app that workflow creators can add to their script filters Q: What does it do? A: It renders html from quicklookurl of every item in the json. Q: How does it do it? A: By intercepting the json and by monitoring up-arrow and down-arrow keypresses. Q: How to add it to a workflow? A: By adding it to the script filter. Here's an example (from the workflow in the above GIF): notice how everything remains the same, just that at the very end, json needs to be piped through the helper app # Before: query=$1 PATH=/usr/local/bin:$PATH items=$(curl 'http://127.0.0.1:7700/indexes/dictionary/search' --data "{ \"q\": \"$query\" }" | jq '.hits') echo "{ \"items\": $items }" # After: query=$1 PATH=/usr/local/bin:$PATH items=$(curl 'http://127.0.0.1:7700/indexes/dictionary/search' --data "{ \"q\": \"$query\" }" | jq '.hits') echo "{ \"items\": $items }" | 'AlfredExtraPane.app/Contents/Resources/scripts/alfred-extra-pane' Q: Sounds great! Now tell me everything that's not working! A: This is more of a proof-of-concept and very rough around the edges. Things that are easily doable, but haven't been done yet (contributions welcome! ) change appearance automatically based on alfred's theme make other things configurable like dimensions Things that seem doable, but quite difficult with my knowledge of macOS GUI programming (which is about a week) let alfred remain horizontally-centered when the pane is not present, and when the pane appears, make the "alfred+pane" combination horizontally-centered (by moving both the pane and alfred window to left) Things that seem doable, but require guessing about alfred's inner workings: as @deanishe points out, alfred builds "uid-based-knowledge". that means if the returned json has an uid field, alfed can use that later to re-order items while displaying based on whether of them were previously actioned on. the knowledge is an sqlite database, so that's the easy part. the not-trivial part is to figure out how alfred sorts the items. Workaround: if you want to use this tool in your workflow, don't add UIDs to your json. One perfect use case for this is the dictionary workflow in the GIF. You looking up a word in the dictionary is a very weak signal that the word is important (many times, it is actually a signal that it is now less likely that the word will be looked up) This is a GUESS based on LIMITED observation. sorting is based on 1) how many times an item has been actioned (freq) 2) latest timestamp of action (timestamp) primarily sorted based on freq, ties are broken by timestamp special case: if the script filter has executed without an argument, and one of the resultant items has an entry in the latching table, the item goes to the top, irrespective of the above sorting. The above algorithm has been implemented and seems to match alfred's sorting. Things that seem impossible to me: take into account mouse scroll interactions. right now, when selected row changes because of a mouse hover, the pane doesn't update, and will continue to show the old preview. As mouse hovers over various rows, the pane updates correctly, as long as Alfred's results have not been scrolled using mouse. Edited November 24, 2020 by Mr Pennyworth zeitlings and caobo 2 Link to comment
deanishe Posted November 9, 2020 Share Posted November 9, 2020 6 hours ago, Mr Pennyworth said: Things that seem impossible to me This is a really interesting idea, but I think there’s a fundamental flaw: Alfred doesn’t always show results in the order they are in the JSON file. If items have UIDs, Alfred will apply its “knowledge” and sort the results based on previous user behaviour. If I understand the way your app works correctly, that means your previews will often be out of sync with the results if UIDs are used. Mr Pennyworth 1 Link to comment
Florian Posted November 9, 2020 Share Posted November 9, 2020 This is actually a thing I've been hoping to see in Alfred for many years. I wish you good luck, and I also hope this gets worked on as an official Alfred API. Great POC! Mr Pennyworth 1 Link to comment
Mr Pennyworth Posted November 19, 2020 Author Share Posted November 19, 2020 (edited) @deanishe @Andrew I totally get the idea that an HTML preview-pane isn't widely useful, and probably doesn't even fit into Alfred's core design philosophy. However, I think some workflows' UX could benefit considerably if they had such an option available. This POC could suddenly become so much more polished and robust if there was a Distributed Notification for "result selected/highlighted" that external processes could subscribe to. The data for that notification would contain entire json for the highlighted result. Then, instead of manually tracking keypresses and mouse-movements like the tool does now, it could simply subscribe to such a notification. It would also remove the need to crudely guess how alfred's "knowledge" works. I know it's quite unlikely that such a thing will be implemented, as I can already see so many reasons not to. I just wanted to pick your brain about what your reasoning would be... Performance: posting distributed notifications slows stuff down. Feature/code bloat: not worth adding to Alfred's codebase something that'll only be used by some obscure tool. Non-trivial implementation: would need time/refactoring disproportionate to usefulness. Undesirable extension: don't want to expose weird APIs. Priority: proposal sounds good, but there are just way too many things with greater priority that it'll be a very long time to come to this. Undesirable functionality: want to discourage such "alfred companion tools". If I were the developer, my reason to not implement would've been some combination of the above. How about you? Edited November 24, 2020 by Mr Pennyworth Link to comment
deanishe Posted November 19, 2020 Share Posted November 19, 2020 4 minutes ago, Mr Pennyworth said: an HTML preview-pane isn't widely useful It's a feature I'd very much like to see, tbh. I don't think the distributed notifications are likely, for the reasons you give. Link to comment
Mr Pennyworth Posted November 19, 2020 Author Share Posted November 19, 2020 2 minutes ago, deanishe said: I don't think the distributed notifications are likely, for the reasons you give. Yep. I tried to make that list exhaustive. What I'm curious to know is which among the above are @Andrew's reasons. (must admit I'm clinging onto the teeeny tiny hope that he replies "no reason not to... watch out for it in some future release". but short of that, it's just a good thing to know the "why" ) Link to comment
deanishe Posted November 19, 2020 Share Posted November 19, 2020 I missed your earlier update about handling UIDs. I don't know exactly how Alfred's knowledge works. Personally, I'd probably just have the helper strip UIDs from the JSON when it's passed through. Link to comment
Andrew Posted November 19, 2020 Share Posted November 19, 2020 Hey! I forgot to chime in when I saw this originally - very impressive! Richer content natively within Alfred is something which has always been on the plan for the future, but this really does provide a solid stepping stone. It wouldn't be a huge amount of effort to post a distributed notification for the quicklookurl, but due to a whole host of reasons (of which you outline some above), I wouldn't make Alfred post this by default. Having said that, for fun, I wouldn't be adverse to make it a defaults write on Alfred's prefs just to see this working better, and see where you take it Cheers, Andrew Mr Pennyworth, Rooter, Florian and 3 others 6 Link to comment
Mr Pennyworth Posted November 19, 2020 Author Share Posted November 19, 2020 8 minutes ago, Andrew said: Native richer content natively within Alfred is something which has always been on the plan for the future Yayy! Awesome to hear that!! 9 minutes ago, Andrew said: Having said that, for fun, I wouldn't be adverse to make it a defaults write on Alfred's prefs just to see this working better 🎉🥳 you're the best! Keeping my fingers crossed! 🤞🏼 Link to comment
Florian Posted November 28, 2020 Share Posted November 28, 2020 Damn, with this announcement from Andrew and the recent feats by Pennyworth, I think I will have to start writing workflows again! Link to comment
Mr Pennyworth Posted December 5, 2020 Author Share Posted December 5, 2020 (edited) On 11/20/2020 at 2:05 AM, Andrew said: Having said that, for fun, I wouldn't be adverse to make it a defaults write on Alfred's prefs just to see this working better, and see where you take it Hi @Andrew, I forgot to ask this last time! How do I find out when this lands in Alfred? Right now, after each pre-release build update, I run the following two commands and see if there's anything of interest there: defaults read com.runningwithcrayons.Alfred defaults read com.runningwithcrayons.Alfred-Preferences Is that the correct way of checking? Edited December 5, 2020 by Mr Pennyworth Link to comment
Andrew Posted December 5, 2020 Share Posted December 5, 2020 @Mr Pennyworth I'll post back in this forum when it's available, I have quite a bit of other Alfred 4.3 work remaining but this is still on the plan. You won't see anything extra in the defaults read when this is available, as you'll be using a defaults write to add something. Mr Pennyworth 1 Link to comment
Andrew Posted December 8, 2020 Share Posted December 8, 2020 @Mr Pennyworth If you update to 4.3 b1199, you can now set the following pref: defaults write com.runningwithcrayons.Alfred experimental.presssecretary -bool YES You'll need to restart Alfred after setting this preference, then subscribe to the distributed notification: alfred.presssecretary You'll get relatively detailed output, for example: { announcement = "selection.changed"; selection = { objectuid = "D51F7B33-AE36-4A45-91FF-E983659833EF"; quicklookurl = "file:///Applications/Safari.app/"; resultuid = "user.workflow.1B09DD22-0FDA-43B0-88DE-FBC92B83DA70./Applications/Safari.app"; subtext = "/Applications/Safari.app"; title = Safari; workflowuid = "user.workflow.1B09DD22-0FDA-43B0-88DE-FBC92B83DA70"; }; view = default; windowframe = "NSRect: {{921, 884}, {718, 259}}"; } Announcement types are as follows: window.shown - The Alfred window has been shown on the screen window.hidden - The Alfred window has been hidden context.changed - The view has changed from e.g. the default results to file system navigation selection.changed - The selected item in Alfred has changed The different contexts are as follows: default navigation actions music (note: actions and music don't post out selection notifications) Important note: This feature is experimental, and there is no guarantee that it will remain in Alfred in the future. Having said that, if it's removed, it would likely be replaced with a more robust solution. Let me know how you get on Cheers, Andrew Chris Messina, Mr Pennyworth and Florian 3 Link to comment
Mr Pennyworth Posted December 8, 2020 Author Share Posted December 8, 2020 Love the name! This is so cool!! ☺️ Link to comment
Mr Pennyworth Posted December 8, 2020 Author Share Posted December 8, 2020 @Andrew I'm so sorry this is likely such a n00b question! I'm only seeing window.hidden notifs. I don't seem to be able to catch the others... The extra-pane was the first time I'm writing swift, (or any mac-related programming for that matter) So likely it is something really dumb that I'm doing... DistributedNotificationCenter.default().addObserver( forName: NSNotification.Name(rawValue: "alfred.presssecretary"), object: nil, queue: nil, using: { notification in NSLog("\(notification)") } ) I just wanted to confirm that the notifications are posted with DistributedNotificationCenter.Options.deliverImmediately I'm not really sure whether it is the poster's responsibility or the observer's... Assuming the observer can ensure immediate delivery irrespective of how the poster posted the notifications, I tried this code: #import <Foundation/Foundation.h> static void callback( CFNotificationCenterRef center, void *observer, CFStringRef name_cf, const void *object, CFDictionaryRef userInfo ) { NSLog(@"event: %@", (__bridge NSString*)name_cf); NSLog(@"user info: %@", userInfo); NSLog(@"object: %@", (__bridge id)object); return; } int main(int argc, const char * argv[]) { NSString* name = @"alfred.presssecretary"; CFNotificationCenterAddObserver( CFNotificationCenterGetDistributedCenter(), nil, callback, (CFStringRef) name, nil, CFNotificationSuspensionBehaviorDeliverImmediately); [[NSRunLoop currentRunLoop] run]; return 0; } The results are still the same, I only get the "window.hidden" notifs and none of the other types... Link to comment
Andrew Posted December 8, 2020 Share Posted December 8, 2020 @Mr Pennyworth hah very strange, it seems that it doesn't like the NSValue version of NSRect and discards that message (I was only doing internal logging of messages sent so didn't see they weren't being delivered). Give me 15 mins, I'll see what I can do. Mr Pennyworth 1 Link to comment
Andrew Posted December 8, 2020 Share Posted December 8, 2020 @Mr Pennyworth If you update to b1201, you should get more satisfying results. I now use NSStringFromRect for the window rectangle, so you should be able to use NSRectFromString to convert back. Cheers, Andrew Mr Pennyworth 1 Link to comment
Mr Pennyworth Posted December 8, 2020 Author Share Posted December 8, 2020 @Andrew Getting them all now! 🎉 Getting selection.changed only on keypresses though, not on mouse-hover... Link to comment
Andrew Posted December 8, 2020 Share Posted December 8, 2020 @Mr Pennyworth Ah sorry about that - I'll get that added for the next pre-release build (which likely won't be until tomorrow now). Cheers, Andrew Mr Pennyworth 1 Link to comment
Mr Pennyworth Posted December 9, 2020 Author Share Posted December 9, 2020 Typo alert: "annoucement" is missing an "n" Andrew 1 Link to comment
Andrew Posted December 9, 2020 Share Posted December 9, 2020 @Mr Pennyworth .... Mr Pennyworth and deanishe 2 Link to comment
Andrew Posted December 9, 2020 Share Posted December 9, 2020 @Mr Pennyworth could you please update to pre-release b1203 which will fix this spelling mistake, and also make the notifications fire on relevant mouse movement. Mr Pennyworth 1 Link to comment
Mr Pennyworth Posted December 9, 2020 Author Share Posted December 9, 2020 Deleting a bunch of code is so satisfying! no more mouse tracking no more keypress monitoring no more accessibility hoops to get window events and sizes no more guessing "how does Alfred rank results?" nikivi, Chris Messina, Florian and 2 others 5 Link to comment
Alfred0 Posted December 10, 2020 Share Posted December 10, 2020 Whoa, this is so cool!!! This is something I have also longed for and really think this could be a game changer!! Can’t wait to see where you take this and what other devs come up with! Link to comment
Mr Pennyworth Posted December 14, 2020 Author Share Posted December 14, 2020 Thanks @Alfred0! My most favorite use-case is actually something that I hadn't originally thought about: "Search Google as You Type" Google has become more and more of a question-answering-machine. So many times, I just want a quick answer and am not looking at reading articles/blogs etc. For those cases, the mode of operation is "search google -> look at result -> move on". The extra pane fits so well for them! And ofc, pressing enter would open the same page in browser if I want to interact with that page further. @Andrew The above involved writing this script filter: I would agree that writing such a script filter is a minimal-effort, no-hassle thing. It does feel like a teeny-tiny duplication-of-function though, given that Alfred already has awesome web-searches. Is there a way to access the URL the web-searches are building? Or, would it be possible to expose those URLs through press-secretary? Or, is that not desirable due to privacy concerns? Also, is there a programmatic way of accessing the web-searches? cc: @deanishe @vitor (that way, someone could programmatically build a workflow mirroring the web-searches and their keywords if they want) I scoured through various plists and alfdbs, but couldn't find where they are stored... Are they stored in some proprietary format / right inside the binary? Or did I miss something obvious? Having said all this, I must agree I don't really foresee much value in doing this for all web-searches because with the exception of google and wolframalpha, I would assume most of the searches are such that they require further interactions with results (like clicking a link, copying some text etc). Aside: Here's a different (vertical) configuration I've been toying with: allonli, JJJJ, luckman212 and 1 other 4 Link to comment
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now