When you choose the command, it sends the current article to MarsEdit — which opens it in a new window, and then you can edit and add your own commentary before posting to your blog.
* * *
See SendToBlogEditorApp.m for the code that packages up the article and sends an Apple event.
The code is not MarsEdit-specific — other apps in the past have supported this same Apple event, though I don’t know if any other current apps do. If I find some, I’ll add them to the sharing menu alongside MarsEdit.
* * *
The Apple event code is written in Objective-C, even though I almost always write new code in Swift. But, with Apple events code, Objective-C is easier.
It’s easy to call from Swift: see SendToMarsEditCommand.swift.
(Reminder: this is all MIT-licensed. You can use this code.)
It sends the title and link of whatever you’re reading over to the Micro.blog Mac app, and you can edit it before actually posting.
This is hugely important. RSS readers exist not to just make reading easy but to make the web a conversation.
Ideally, every app like Micro.blog and MarsEdit would have a sharing extension — but, where they don’t, I can add them as long as they support some kind of way to do so.
Micro.blog supports a URL scheme for sending it a post: see See SendToMicroBlogCommand.sendObject for the implementation in Evergreen. (And of course feel free to use any Evergreen code in your app.)
It’s not that we realized just today that posting from an RSS reader is important. Since posting was always an absolute requirement, way back in 2003 I released NetNewsWire 1.0 with an integrated blog editor.
I got that idea from Radio UserLand, which was an RSS reader and blog editor by the company where I worked before I wrote NetNewsWire. It’s Dave’s idea, not mine.
By the time I was working on NetNewsWire 2.0, it became apparent that smooshing a blog editor into a reader app meant that the blog editor suffers. The blog editor in NetNewsWire 1.x was pretty darn bad. So I had the idea of splitting out the blog editor to a separate app — inducing mitosis — which you can read about in my MarsEdit report of late 2004.
Mitosis was a success.
One of the keys of that success was that the API for contacting MarsEdit had to be open, and NetNewsWire had to support any blog editor, or any other app, that supported that API — because otherwise I would have been unfairly leveraging success with NetNewsWire on behalf of my new blog editor, and that would have been wrong.
MarsEdit still supports that interface, and my next step is to write the client side in Evergreen, so it can send to MarsEdit and any other app that supports that interface.
I am, by the way, delighted to be writing code for a 14-year-old API that still works.
Ben Curtis posted feed_searcher to GitHub — it creates custom search feeds, and even has a handy Deploy to Heroku button. Cool.
(This is in reference to App Idea: Mentions).
I had this idea around the time Apple came out with Bonjour (née Rendezvous), and all these years later I realize I’m never going to get around to it.
Here’s the scoop:
The idea is microblog posts (tweet-like) but that live inside a specific network only.
You run a Mac app that:
- Lets you post short messages.
- Shows short messages from people inside your network.
The app runs a small webserver that’s discoverable via Bonjour, that has a specific service name. That webserver publishes a feed of your posts.
The app also downloads a feed from every other app it finds (and caches those feeds, for when other apps are offline).
In other words, it’s instant office microblogging with no centralized server. Completely peer-to-peer.
The design is what you expect — a reverse-chronological list of posts with usernames and avatars. You can reply, mention people, mute people, etc. (I think you’d follow everybody on the network automatically — so muting becomes the thing, not following.)
* * *
Important thing: your posts are network-specific. So if you go to a coffee shop or the airport with your Mac, you won’t be publishing your at-the-office posts.
* * *
I haven’t done research into whether this is do-able on iOS. Is it possible to run a little webserver, in a backgrounded app, that other people on the local network could connect to? Seems unlikely — but I don’t know. Cool if you could.
* * *
I have no idea how you’d make money with this one. If you charge for it, not enough people would use it to make it worthwhile. (The standard dilemma of social networking apps.)
Maybe, though, you could add some IAP features? One might be to let people add RSS feeds, so it could also function as a lightweight RSS reader. A person might want posts from Daring Fireball and wherever else added to their timeline.
Or just add that feature anyway, and do the whole thing for fun.
PS “Inside Story” is a long name. Should be one word. Scoops? Bulletins? Officecast? Gossip? (“Gossip” was, if memory serves, the name of an app Chuck Shotton was working on a long time ago. Probably reusable at this point.)
(I mean, c’mon, office Gossip. It’s so perfect.)
“Hold on — I need to check my Mentions.”
Ten years ago or more we had several blog-specific search engines and services: Technorati, BlogBridge, and others.
One of the great things about these services was not just being able to search for something but being able to set up persistent searches: that is, you’d get a search as an RSS feed, and in your feed reader you’d get results from all over the place on the thing you’re searching for.
In the obvious and common cases, you’d set up searches for people linking to your blog, writing about the apps you work on, mentioning the place where you work, and mentioning you.
I’d like to see something like this for today, but where the scope is just the Apple/Mac/iOS community. It would crawl the obvious sites (such as Daring Fireball and Loop Insight) and it would crawl the many blogs and microblogs that make up the community.
I think this is best as a web service, though it could have Mac and/or iOS client apps. It needs to provide feeds for people using feed readers.
* * *
With that reduced scope, and with the better tools and cheaper cloud computing these days, I don’t think it would be terribly expensive. Not like it was 15 years ago.
You might want to make money with this, though, and there are a few ways to do it: charge extra for things like notifications and email alerts. Charge money for client apps. Make the first three search feeds free, and charge money for a ten-pack of searches. Etc.
* * *
An alternate version of this idea isn’t a web service — it’s a Mac and/or iOS app that does the crawling. A kind of specialized Mac/iOS feed reader.
The list of feeds-to-crawl would probably just be an OPML file on the web, and the app would periodically grab that list.
(If you did this, you could use RSParser as starter code, since it parses OPML, RSS, Atom, JSON Feed, and RSS-in-JSON.)
This would make a great open source project, but it could just as well be free or for-pay.
* * *
One challenge is handling spam and abusive or hateful content. You’d most likely want to have a suggest-a-site form, so you don’t have to go out and find every single site there is.
But you have to be able to say no, and you have to be able to update the list of sites-to-crawl quickly if a site turns bad or inappropriate somehow.
You’d also need a way for users to report an issue.
(Again, the reduced scope — Apple-related blogs — makes this somewhat easier than if you tried to do the entire blogosphere.)
* * *
I want this! I’d use it every day. I know other people who would too.
But I’ve got enough on my plate that there’s no way I can do it myself — though I’d be happy to answer questions and provide feedback to anyone who does want to do it.
I have a vision for 1.0, and then, as time goes on, I have to cut it back beyond where it hurts. I have to keep punting. I hate this part of shipping software.
But I also love it because it reminds me that I have the stomach for it. Shipping software is an emotional skill.
After shipping — no matter what — there will be people who absolutely cannot believe that feature X wasn’t included. In fact, it’s the one thing they totally need.
And they’re right. Not wrong. And I would have loved to have included feature X, loved I not quality (the app maker’s honor) more.
* * *
I wondered if Evergreen as open source instead of as a for-pay app would affect what and how much I punt. I hope the answer is: not at all; the decisions would have been the same.
I think that’s right because I’m trying to make as good an app as I can, which would be true regardless.
But it is nice not to have to consider money as I make decisions. I do think about how I want it to have as many users as possible, and I want people to love the app. And I have to think about the economy of my time. But I don’t have to consider money.
Another difference between open source and commercial is that I can be utterly transparent about what’s been punted. Check out Evergreen’s 2.0 milestone. It will keep growing. Every single one of those things was originally supposed to go in 1.0.
* * *
Some things I keep reminding myself as I make progress toward 1.0…
This isn’t the last release, it’s the first. There will be many more. (I hope to work on this app for 20 years. It’s been only three years so far.)
Any feature I ship, I probably have to support forever. So it’s wise to be cautious.
Quality — design, stability, performance, lack of bugs — is way more important than any collection of features.
And, perhaps most importantly: shipping 1.0 means learning about your users, how they use your app, and what they need — and those lessons will change future plans, as they should. It’s best to learn those lessons early, before doing too much.
In this episode I finally get around to talking to Mark Boszko, the show’s intrepid producer and The Omni Group’s Video Producer.
I’ve known Mark for more than ten years — we met at a SXSW conference many years ago, long before either of us came to Omni. Mark didn’t even live in Seattle in those days. Now he does, and now we have the pleasure of working together on a podcast.
PS If you like movies, definitely check out the podcast Mark hosts: The Optical.
Mike Monteiro writes of Twitter CEO Jack Dorsey:
Jack let it happen. He watched as a once-entertaining, once-illuminating, once-vital network to global communication became a garbage fire of hate. He did nothing to stop it. Or curb it. He didn’t see a problem.
Our current crises of democracy and good faith did not just blow in with the wind and transform the air without our knowledge or consent.
These crises were made by people, and we knew what they were doing, and we agreed to this.
Jack Dorsey is one of those many people. Just one. But one with a kind of power that nobody in the world should have: the power to directly control a vast amount of the world’s communication.
It’s not that Dorsey failed to consider the good of the world. Or, really, it’s not just that. It’s that this kind of power should not exist at all.
But we agreed to it. We’re still agreeing to it.
Twitter — and Facebook, and the power of tech companies — is not our only problem.
But I have no doubt that had Twitter not become a loving home for hate, Trump would not be President now. In that universe we’d still have big problems, yes, but not like this.
How we can stop agreeing to this
The great social network is, or ought to be, the web itself.
The unruly web — unregulated and uncontrolled — is, perhaps paradoxically, the easiest place to limit hate. Not because we can stop people from publishing, but because we don’t have to live by Dorsey’s and Zuckerberg’s rules and designs.
I don’t know all the details of how we get there, or what it will be like once we do. That’s fine: that’s part of what makes the journey fun.
Consider a few apps.
Overcast and Castro and others help ensure that podcasting is not just a vital and exciting medium of independent publishing but is also open and built on standards. Anybody can write any kind of podcasting software they want to — but nobody can control podcasting.
And nobody can force you to listen to hate. You pick the shows you want to hear.
MarsEdit lets you write whatever you want to write and publish it on the web. You’re limited only by the law and whatever terms of service your hosting provider may have.
All the words you read in MarsEdit are your own. And nobody can make you read what other MarsEdit users write.
Evergreen (which I’m working on), NetNewsWire, Reeder, Unread and other RSS readers work like Overcast and Castro but for written words. You choose what to read, and if a blogger you like suddenly turns hateful, you hit the Delete key.
Then there’s Manton’s new service, which needs its own section…
It’s a publishing platform and a social network, based on standards.
You don’t even have to use Manton’s Mac or iOS apps: you can write posts in MarsEdit or other blog editor, or read your timeline using an RSS reader.
People could, though, sign up for it and flood your mentions with hate. In theory. So I asked Manton about that, and he wrote:
Micro.blog is similar to MarsEdit in a way in that it can be used to write hateful posts, etc. What we have to do as a social network is limit the damage. So, by default, if someone writes something terrible… No one sees it. It doesn’t automatically show up in trends (because we don’t have them, for this reason) and it doesn’t show up in Discover (because that’s curated by a human). Replies are where it’s an issue, and that’s where good tools and automatic flagging and reporting are needed.
In other words: the rules are different, and the easy exploits on Twitter are not so easy on Micro.blog. And there’s an actual committment to fighting this.
Manton also writes on his blog:
Imagine instead a service based on blogs, where the internal posts on the platform were the same format as the external posts. The curators of the platform would have more freedom to block harassing posts and ban nazis because those problematic users could always retreat to their own web site and leave everyone else in the community alone.
That’s how the web is supposed to work. It’s a core principle of Micro.blog.
(I’m @brentsimmons on Micro.blog, by the way. Here’s my microblog. I plan to post there more often than on Twitter in 2018.)
I should also mention…
I’m not sure where to put Slack in all this — except to say that admins control who’s in their groups, and I’ve never seen hate and harrassment there. I run a few groups, and I would have zero tolerance for this, and so would everybody I know who runs groups.
Well. One more thing about Slack: it meets some of the needs that Twitter used to meet. The talking-with-friends-and-family needs are very well covered there.
And the more we find ways outside of Twitter and Facebook to meet those needs, the less we’ll use Twitter and Facebook.
Maybe, back in 2012, Twitter did five important things for you that only Twitter did. I bet, in 2018, that that’s down to one or two.
The period from 1995-2008 (roughly speaking) was fun. It seemed like everybody was coming up with new things, and people were experimenting, and we were finding new joys in new connections, both human and technological.
Then, as Facebook and Twitter (and Google Reader; can’t forget that thing) grew, it’s as if we froze.
And those things were fun for a while, but they’re not now, and it’s obvious we made a mistake in allowing that much power to concentrate.
It’s time for the thaw: it’s time to get back to having fun. You’re free to make whatever you want.
What I’m Not Saying
Rebuilding the social open web is not the one cure that we need for all our ills. I’m fully skeptical of technological solutions to problems of culture and politics.
But it is an important thing we can and should do.
My small hope for 2018 is the knowledge that I’m not the only person thinking that way.
Me in 2011: What we talk about when we talk about RSS
Me in 2013: Why I love RSS and You Do Too
IndieWeb is a thing I need to learn more about.
Tantek Çelik (video) - The once and future IndieWeb
I copied Evergreen’s parsing framework, RSParser, to a separate repository on GitHub.
It has no dependencies other than system-supplied libraries. It’s offered via the MIT License.
It builds a Mac framework only at the moment, but adding an iOS target should be easy. It’s the one issue in the bug tracker (at least so far).
Otherwise it’s fast and stable and does the jobs it’s designed to do.
Things it parses
- JSON Feed
- Internet dates
- HTML metadata
- HTML links
In addition, you can build your own XML or HTML parser by creating an
It’s a mix of Objective-C and Swift. More recent code is in Swift.
Parsing a feed that’s RSS, Atom, JSON Feed, or RSS-in-JSON is a matter of calling
FeedParser.parse and getting back a
ParsedFeed object. Pretty simple.
Sounds great! I’m on board.
One of the best parts about it — easily enough to sell me — is that a crash in
WKWebView won’t crash my app.
(Back when I was doing NetNewsWire, crashes in the old
WebView — the predecessor to
WKWebView — were the most common crash. But, to be fair, many if not most of those were actually Flash crashes.)
I’ve also heard, though I’m not sure how to verify, that
WKWebView is better for accessibility, too. So it’s a win all around.
But it’s not a win all around
WebView — good ’ol trusty friend — has a bunch of things that
WKWebView is missing.
The new web view has no built-in support for finding text, for instance. I’m not sure what I’m going to do about this, since the ability to hit cmd-F and look for some text is a pretty fundamental thing, and I can’t skip it.
It also has no delegate method for when you mouse over a link. Seems like another fundamental thing, right? Any browser offers you a status bar or some way to see the URL of the link your mouse is over.
renderedHTML() method.) Then I added handlers in DetailViewController: see
viewDidLoad and the
This worked fine: now my status bar shows the URL of the link your mouse is over. Cool.
Then the issue of scrolling came up
Evergreen’s design includes a key feature: you can go through all of your news just by hitting the space bar repeatedly.
If there’s more to scroll in the web view (the article), it scrolls. If not, then it goes to the next unread article.
This is a coffee-in-hand feature, which is critical for a news reader.
WKWebView provides no access to its scroll view. (It does on iOS, yes, but not on Macs.)
The logic goes like this:
if canScrollDown() scrollDown() else goToNextUnread()
There are two parts to this, and both (I thought) required access to the scroll view.
I did this an DetailViewController, in the
(Unfortunately, this is asynchronous. I expect it to be super-fast, but I won’t know if this is a problem without a bunch of testing. Let’s set that issue aside.)
fetchScrollInfo method creates a
ScrollInfo struct (at the bottom of
DetailViewController) that has
So that’s how I know if the web view can scroll. Part one of two solved.
(I write Mac apps. “Noticeably different” is the kiss of death.)
So I did some nerd-sniping, on Twitter and Slack, to see if anybody had a suggestion that would work.
People had ideas. Nothing worked.
So I’m frustrated, and I’m just about to switch back to my old friendly friend
WebView, because I know it will do what I want.
The voice of another old friend — the guy who mentored me in my early days as a programmer — came into my head, as it often does in these situations.
“What is the real problem you’re trying to solve?” asks Dave Winer, in my head.
The real problem is not arbitrary animated scrolling. The real problem is that I want to do a page-down exactly the same way it would work if the
WKWebView had focus and you hit the space bar. Exactly the same animation and scroll distance.
But not arbitrary scrolling: just a page-down.
So I think maybe I can spy on the event stream; maybe I can figure it out by seeing what happens when I click in the web view and hit the space bar. Maybe I can post an event that will do the job.
To do so I make an
NSApplication subclass, which I do (in Swift, of course), and break on
But of course this doesn’t work. The app crashes immediately saying it can’t find the
EvergreenApplication class. (Which is right there! Dude!)
Okay, maybe it’s back to
WebView after all. Forget
Then I do a search in Xcode on
pagedown, just out of a last gasp of trying — and, forgotten long ago by me, but look: there is a
scrollPageDown method in
NSResponder — and
WKWebView is an
NSView subclass which is an
NSResponder subclass — so, could it be? maybe? it might work?
I tried it: sure enough! It works! With animation and everything. It’s perfect.
* * *
So, in the end, the action method is in MainWindowController — see
(It’s a little weird due to the async thing I mentioned earlier. But it does the job.)
And now — after three years of working on this app — I was finally able to go through all my news just by hitting the space bar. Big day for me.