Elytra’s Fall 2020 update is finally here alongside the release of iOS 14. This is v2.0 and will be the first build to only support iOS 14. If you’re still on iOS 13 and for whatever reason you won’t be updating to iOS 14 soon, rest assured, v1.8 will continue to function as long as you use it.
Apple will be releasing new hardware later in October starting with the recently announced new iPad Air 4th Generation devices. Elytra will be ready on day-1 when these devices reach you with no new updates required.
iOS 14 UI
Throughout the app, I’ve made changes to the app’s interface to closely follow new updates Apple has released this year, including menus from buttons (for the sorting option), new Sidebar Layout style on the iPad, Triple Column Layout on the iPad and new List styles.
New Code Theme
Also in this release, I’ve included a new Code theme which uses the semantic colours from iOS, auto-updates for dark mode without reloading the entire stack and, may I say so myself, looks beautiful. You can read more about in this blog post I wrote earlier.
How could an iOS 14 release build be complete without new Widgets! I’ve personally been looking forward to using Widgets and making them was fun too! Elytra 2.0 ships with 2 different widgets:
Counters Widget: Shows the latest counts of articles from Unread, Today and Bookmarks sections of the app. This widget is only available in the small size.
Unread: Shows the latest articles from the unread section. The medium size widget shows 2 articles and the large size widget will show 4 articles. This widget will prioritize articles with cover images.
Full Change Log
All new triple column support using Apple’s own UI Framework.
An all new Sidebar Interface. This uses Apple’s latest UI Framework for displaying your folders and feeds.
iOS 14 Widgets support. Contains a Counters (Small) Widget and an Unread Articles (medium and large) widget.
Implements Trailing Swipe actions on Article List Items.
Directional marking as read. Long press on an article in Unread, Today or a Feed to see these options.
New Code Theme for pre-formatted code blocks.
The Add Feed interface now shows Recommendations for its default state to help improve finding and adding new feeds.
Unread counts update more reliably as you read through your content.
Improved underlying code for managing the initial state of the app.
Force touch and tapping on urls now works reliably.
Updated Feed Sorting options to use a menu interface instead of an options controller.
Improved styling for inline code blocks.
New Folder/Edit Folder interface now uses a basic interface which is faster to use IMO.
Prevents an issue causing the app to sync data twice upon successfully launching.
Fixes an issue where marking currently loaded articles as read in the Unread view would prevent new articles from loading.
If you have setup a custom title for a Feed, the custom title will now show up correctly for the empty state.
Fixed a crash caused when trying to share a Feed’s URL or its website’s URL.
Fixed an issue where reading an article from today would not decrement the “Unread Today” counter.
Fixes showing cover images inside the Article Reader.
Fixed I/O View not appearing when importing / exporting OPML files.
Fixed some pre-formatted quotes appearing as single-line code blocks.
Fixed code blocks appearing out of order. A year old bug finally fixed!
This update also includes miscellaneous improvements and fixes under the hood to improve the general stability of the app.
As recently put by one of Elytra’s admirers on twitter:
As part of the v2.0 release cycle, I’ve been working on a macOS/UIKit inspired code theme. In this post, I’m sharing what I have come up with so far inviting feedback and suggestions for changes.
The colours are platform specific, so they will be slightly different across iOS/iPadOS, macOS and the Web. Work on the web part is pending but it’ll look mostly similar to the macOS screenshots.
On macOS, the colours will respect platform specific accessibility features like enhanced contrast, and light & dark modes.
All colours are taken directly from the system provided semantic colours with some alpha tweaks in places where it makes sense.
The story is similar on iOS just like macOS. System provided semantic colours are used throughout.
Across the board, I quite like how this is rendering. It’s softer on the eyes too, and if you didn’t notice, the code blocks no longer use the Menlo typeface at a static 16pt. It’ll now scale dynamically to your font-preference, system sizing or custom, using the SF Monospaced typeface from Apple.
In a future update, I’ll look into embedding additional Monospaced fonts suited for viewing code (my current favourite being Fira Code).
I’ll share additional screenshots on Twitter as I go along tweaking and optimising the code.
So let’s get into the technical details of this for those of your interested.
Here is an excerpt of what the original css structure looked like.
This is from the light theme of my CodeParser. This CSS file is imported by the Class, parsed and processed to convert those hex values into their respective UIColor counterparts and then used in Attributed Strings.
So to make this existing system use semantic system colours included making some trivial changes to my code base, starting with the CSS file which now looks like this:
I’m now directly using the semantic colour names, prepending it with an asterisk to denote a semantic color name, and followed by a pound with the alpha component.
As you can imagine, parsing the above is pretty trivial, so is detecting if it should use the semantic name using -[UIColor performSelector] or the method from my HEX to UIColor category.
Once all of this is wired up, the information is assigned to ranges in the Attributed String the same way as it did before with no changes to that part of the code.
With this new system in place, I can use any of the semantic colours exposed by the host OS, of pure hex values or a combination of both in the same file which makes this solution very versatile and light weight.
It’s been some time since I posted an update here and since I was gathering some screenshots of my progress on the Mac Catalyst app, I thought I would share my progress here as well for everyone to check out.
Hello, Big Sur
As noted in my previous post (WWDC20 and Elytra), I mentioned I’d release two separate builds, one for Catalina and another for Big Sur. But looking at how much better the app is using new technologies released this year, the plans have changed a bit. There won’t be a Catalina build, not anytime soon anyways. However, here’s an early look at the work in progress app running on Big Sur:
The app is probably only 50% done. There a lot of tweaks and adjustments that need to be precisely made so that the app feels native to macOS Big Sur. It is still missing critical features like Importing & Exporting OPML files and managing your Subscriptions.
So I’d definitely tag this as Alpha for now. Once I determine it has all the necessary features from its iOS and Web counterparts, I’ll tag a beta pipeline and figure out a way to introduce it to testers. So if you’re interested in helping me test the macOS App, have Big Sur running on one of your computers, send me DM on Twitter or email me. Also send in any feedback or features you’d like to see in the macOS app.
WWDC20 week is currently going and Apple has released all new SKDs for their upcoming OSes for the iPhone, iPad and Macs. There is so much cool new stuff packed into these releases, it was extremely hard for me to evaluate how to proceed with development for Elytra.
During the two weeks leading up to WWDC20, I was working on the Mac Catalyst App for Elytra, trying to figure out if it would be a good fit. Turns out, yes, but with some undesired effects.
During the same time, I’ve been working on v1.8 of the app for the Fall release to coincide with the releases of the new OSes.
Unfortunately, all the new amazing APIs Apple is releasing this year for developers to use are tricky to backport to iOS/iPadOS 13 and macOS Catalina. So to make things easier for users of Elytra, you: I’ve decided on the following roadmap:
v1.8 will be released as planned for iOS 13 and macOS Catalina. I’ll simply bring this release forward by two weeks, so everyone who plans to stay on iOS 13 and macOS Catalina for a bit longer can continue to use Elytra with the new features I am implementing in v1.8. This also gives me enough time to submit bug fix builds if they are required.
v1.9 will be released simultaneously with the new OS releases and will be a one-to-one identical release of v1.8 targeting only the new OSes. This will be the new branch that’ll continue onward to future releases of the app across all 3 platforms.
However, so much will be changing in the app, the v1.9 tag doesn’t make much sense. So I’ll be bumping things to v2.0 for the iOS/iPadOS 14 and MacOS Big Sur release. So this fall, you can expect v1.8 and v2.0 of Elytra.
I have some really exciting things planned for these releases. I’ll also be merging the release of Elytra of Web with the 2.0 release of the apps.
With some careful planning on my part, I hope to have all existing and new users of Elytra up to the latest features with a solid foundation for future releases.
In the meantime, here’s a look at the new App Icon coming with v1.8 and v2.0 of the apps.
I’m starting a new series of posts detailing changes I release to the Web Service. The Web Service is responsible for syncing your account across your devices and browsers. It also caches new articles so you only fetch information from sources that have changed since the last sync.
I keep getting error reports from the Web Service in a unified private channel on Elytra’s Slack group. I use these reports to patch bugs as soon and as quickly as I can.
Yesterday, I received some errors regarding adding feeds using the ftr.freshangle.net service. This is the first I had heard about so I quickly investigated and found some issues in Elytra’s code that prevented these feeds from being processed. The ftr.freshangle.net service now has first class support in Elytra for both the XML and JSON feed endpoints.
There was a major sync bug in Elytra’s code both on the Web Service and iOS App. I released v1.7.4 on iOS to patch this issue and patched the Web Service as well. By morning of 4th June, these errors dropped down to just 12% compared to the day before it. As soon as all users update to the latest version of the iOS App, this should drop down to 0%. If you still haven’t updated, check the App Store for updates.
On 2nd June, we faced an interruptions and eventually an outage from our service provider which caused Elytra’s first ever downtime this year. Things eventually began recovering by 03:30AM IST on the 3rd of June. Everything is now stable. This outage resulted in some angry customers and I completely understand that. If you ever face any issues with the App or Service, always feel free to contact me at email@example.com
On a separate note, a White Hat Hacker recently got in touch with me regarding a critical issue with the API Service. I have since patched the issue. No data was affected as the core issue had to do with DNS setup for emails sent from Elytra’s domain.
Elytra for web is now in public beta and in this post I’ll document some features and quirks of the webapp. You can start using it right away.
When I set out to build the Web App, I wanted to bring as much functionality of the iOS App as possible, and this proved to the tricky. Since version 1 of the app, the Article Reader never used HTML to render the contents. Everything was drawn native to bring native accessiblity functions and remove privacy-sucking scripts from the entire reading experience.
To do the same on the web with the same data was a tad bit challenging, but not impossible.
Some features are notably missing at the moment like:
Viewing and reading your bookmarks
to name a few. I’ll be adding these over the next couple of days and I hope to align the final release of the Web App along with v1.8 of the iOS App.
Just like the iOS App, you can also view your Youtube feeds in the Web App. This has become the de-facto way of me and some hard critics of Elytra to consume the latest content from their favourite Youtube Creators.
Microblog Feeds also get first-class treatment on the Web App just like the iOS App. I am a supporter of what Micro.blog stands for and try to actively use it as time permits. My main website is basically a hosted Micro.blog.
I am really exicted to talk about this feature. I’ve always wanted to listen to podcats in Elytra on iOS but I believe it deserves its own separate app so it does not come in the way of reading content. But things are different on the web. Browsers can host multiple tabs for the same domain. So now on the web, you can open any article in it’s own tab and continue reading another article in the main window. I personally use this to play a podcast in the background while I work or read other articles. I’d love to hear from you how you use this feature.
As some of you may have noticed, I have used the New York font in one of the screenshots. If you have the font installed on your macOS systems, you will be able to use in the App as well. The app does not host the font itself because of its License, but can use it if you have it installed.
We now also have a Slack Group for discussions around the iOS and iOS app and soon the macOS App as well. I’d love to see you there and join in on the discussion.
It’s been a tremendous journey for Elytra since its inception back in 2016 and it’s public launch in 2018. As an Indie Developer, I’d really appreciate it if you shared this post with your friends who may be looking for an RSS Feed Reader on the web. As this is a public beta, everybody is welcome. And as always, you can send support queries to firstname.lastname@example.org or DM me on Twitter. Happy Reading.
If you launch the app or open the web app (if you have access) and notice a sudden surge of unread articles waiting for you, I can explain.
Traditionally, to check if an article is unique and new, I checked its GUID which the feed provides and checked if it already exists in Elytra’s database. This works fine if there is only one source for an RSS feed. It breaks when there are multiple sources for a single website. This happens when say I subscribe to a Website’s XML Feed and someone else subscribes to its JSON Feed. Both sources are valid, but both bring in articles with the same content and GUID. So the articles would map only to the first feed. The second feed would never get new articles.
To solve this problem, I just updated my unique constraint to also use the Feed’s unique ID. The new unique pair constraint of GUID-FeedID works for all feeds from a single website, irrespective of which source the user subscribes too.
This caused a huge surge in unread articles for all users. I do apologise for having overlooked this issue, but on the bright side: We all have a bunch of articles to read over the weekend which we missed out on, no thanks to me.
Brent Simmons writing on his blog, Why NetNewsWire Is Fast, I realised how similar a lot of stuff is between the two, albeit, Elytra offloads a lot of the feeds syncing to its API. The similarities still do exist.
NetNewsWire is fast because performance is one of our core values. Being fast is part of the very definition of the app. … The best general advice I can give is just this: make sure performance is part of the foundation of your app. Make sure it‘s part of every decision every day.
Every app, irrespective of the platform, technologies and, toolchains should aim for that. And that’s not technical, it’s behavioural, on our part.
The most painful way to parse XML is with a SAX parser — but it’s also how you’ll get the best performance and use the least memory.
Yes. It’s a pain in the *** to deal with, but the only proper way to handle thousands of feeds. Elytra’s Polling Server (yes, 1, a t2.nano EC2 instance) chugs through 1K+ Active Feeds 1,not including RSS Feeds which support WebSub, in under 3 minutes.
The parsers are fast — but we also do our best to skip parsing entirely when we can. There are two ways we do that.
We use conditional GET, which gives the server the chance to respond with a 304 Not Modified, and no content, when a feed hasn’t changed since the last time we asked for it. We skip parsing in this case, obviously.
Always respect cache headers for RSS Feeds. Some Feeds when publish a frequency property which you can respect, Elytra does not do that. Elytra uses the Last-Modified and Etag headers specifically.
Now say you’re marking all articles in the current timeline as read. You could call article.read = true for each article — and, for each article, trigger a whole bunch of work. This can be very, very slow.
Elytra v1.0 did this silly thing, a notification for every change and no coalescing. I fixed that in v1.1 once the number of feeds started growing and I had more and more articles I marked read in bulk.
So, instead, we coalesce these — we make it so that recalculating unread counts happens not more often than once every 0.25 seconds (for instance). This can make a huge difference.
This is a fantastic idea. I’m going to use this to Elytra in v1.8.
What I suspect is less common is use of sets. The set is our default collection type — we never want to check to see if an array contains something, and we never want to deal with duplicate objects. These can be performance-killers.
I believe Brent and I ran in to the same issues with fetching Articles from the database such that Sets was the obvious choice over Arrays. I use NSMutableOrderedSet to be specific.
I finally come to the point I currently disagree with Brent on:
My experience with stack views tells me that they’re excruciatingly slow. They’re just not allowed.
No Auto Layout in Table Cell Views
Brent has his own reasons here which he describes in his post. I really like Stack Views and it becomes easy for me to think about layouts for the iOS App and the Web app as its very similar to the flex layout model on the web. I have so far not come across performance issues with using Stack Views in Elytra.
No Auto-Layout in Table View Cells is a deal-breaker for me. Apple’s recent work on self-sizing cells, diffable datasources and composable collection view layouts has really simplified writing code for interfaces. The best part is: with every major OS release, these things become slightly faster, slightly better, and sometimes much faster and better.
I do miss writing up interfaces in code, but I often found myself fighting the OS when Apple releases new device sizes, requirements (like split-view on the iPad in the past), or new technologies.
I was happy to read that most of what I am doing in Elytra is very similar to Brent’s approach for NetNewsWire. I first heard about him when Vesper came out and have since followed his work and blog. I have much to learn from him and I hope he never stops writing such posts.
1. An Active Feed is any RSS Feed which is at-least subscribed by one user. All other feeds are polled once per day.
I’ve been contemplating on this decision for a while now and I think it’s finally time to implement a major breaking change in Elytra’s TestFlight policy. All future releases of Elytra on TestFlight will require you to have an active and valid subscription.
Since before v1.0, all testers using Elytra through TestFlight bypassed all subscription checks. This is generally what is expected. However, some people are using this to bypass subscriptions entirely.
This however doesn’t mean all testers will be affected. I know those who actively share feedback, crash reports and communicate with me. I’ll maintain your subscriptions for free for as long as you wish to be on TestFlight program. Everyone else getting started can use the free trail and as required contact me for a a bump in your subscription expiry dates.