NetNewsWire 3.0d62 Change Notes
17 Mar. 2007
This page lists the changes in NetNewsWire since 3.0d46. You can download the current shipping version via the NetNewsWire home page. You can download the current pre-release version here.
NetNewsWire 3.0d62 is a sneak peek release—it’s not even a beta. It is not feature-complete and it has bugs.
Changes since 3.0d46
Automatic updates checking via Sparkle
NetNewsWire can now check for updates automatically.
In the NetNewsWire menu is a new "Check for Updates..." menu item. Use it to manually check for updates.
In the preferences window, on the General pane, near the bottom, is a checkbox for automatically checking once a day. There's a check-now button so you can manually check from there too.
NetNewsWire uses Sparkle to check for updates. (Sparkle actually includes a revised version of some RSS parsing code I had released years ago. It makes me proud that Sparkle is using some of my code -- I think that's cool.)
Crash reporting
On launch, if NetNewsWire finds that it has crashed within the previous 24 hours, it displays a window and asks you to send the crash log to me by clicking the Send Crash Report button.
This way I'll get lots of crash logs, which I like. ;) (I like getting reports because I love fixing crashing bugs.)
Cache cleanups
You shouldn't notice any of these cleanups happening. They're designed to be slow, just do a little at a time. They run only periodically, after a period of idle time.
And so it will take a while -- don't expect your various folders to get cleaned up right away. It will take days, most likely. (Also: there are more folders to do. This isn't everything.)
Raw source: ~/Library/Caches/NetNewsWire/FeedSource.noindex -- cleans up unused items -- deletes files for unsubscribed feeds.
NewsItems folders: ~/Library/Application Support/NetNewsWire/NewsItems/ -- deletes folders for unsubscribed feeds.)
NewsItems items: ~/Library/Application Support/NetNewsWire/NewsItems/ -- deletes items that no longer appear in NetNewsWire.
FeedData: ~/Library/Application Support/NetNewsWire/FeedData.noindex -- deletes files for subscriptions that no longer exist.
TabThumbnails: ~/Library/Caches/NetNewsWire/TabThumbnails.noindex -- deletes images for tabs that no longer exist.
Combined View
Restored keyboard shortcuts:
collapse-all: ;
expand-all: '
collapse: ,
expand: .
Browser Tabs
Vertical and horizontal options
You can choose between horizontal or vertical. See and . (The vertical tabs have more features: thumbnails, drag and drop. But some people prefer the classic horizontal tabs.)
Bug fixes for vertical tabs
You can no longer double-click no a tab and have it switch to editing mode.
When dragging, there is no longer an extraneous weird extra title superimposed on the image, at the top.
Return to news items on close tab
There's a new pref for returning to the news items tab when closing a tab. See Preferences > Browsing > "After closing a tab, return to news items"
Ever since even before 2.0 shipped, this was a very common feature request. I didn't make it the default, since lots of people *don't* use NetNewsWire that way -- they load up a bunch of pages in tabs and go through them, right-to-left or bottom-to-top, closing them as they go. (That's what I do, at least. ;)
Hide/Show tabs
In the Tab menu is a command for hiding the tabs. (Due to popular demand. ;)
The hide-tabs command is disabled by default: another new command -- Automatically Hide & Show Tabs -- is checked. This gives you the current behavior: it shows the tabs if there is one or more browser tabs, hides them if not. To get manual control, choose this menu item (to uncheck it), then use the Hide/Show Tabs command.
Removed from Preferences > Browsing > Behavior the "Always show tabs" preference.
Known bug: the resize indicator has the wrong background when hiding tabs. Don't tell me -- I see it. (It looks like a Cocoa bug. I think I'm going to have to draw the resize indicator manually when tabs are hidden.)
Export Browser Tabs
At the bottom of the Tab menu is the Export Tabs... command. You can choose where to export your tabs and choose a format: HTML, plain text, or OPML.
Also included is AppleScript support: here's a sample script (just edit the paths to make it work on your machine):
tell application "NetNewsWire" export tabs to file "/Users/brent/Desktop/foo.opml" as OPML export tabs to file "/Users/brent/Desktop/foo.html" as HTML export tabs to file "/Users/brent/Desktop/foo.txt" as plain text end tell
Why did I add this feature? A couple reasons:
1. You might want a way to save tabs without having to have them in NetNewsWire.
2. You might want a way to share your tabs or re-purpose them in some way. AppleScript support was added for those of you who want to get your tabs in a file, maybe do some operation on them, upload to a website, whatever.
Note that you always could get your tabs via AppleScript, but there were no builtin formats, and there was no manual export command. I could have added more and more formats -- Netscape bookmarks, Safari bookmarks, RSS, Atom -- but figured that the returns diminish after three formats.
Note: adding AppleScript features is always a little risky -- let me know if any of your existing scripts break. I don't think they will, but it's always possible.
Also note: the Post Tabs to Weblog command already works. It's MarsEdit-only, but I have a script somewhere around here that should make it work for ecto too. (In other words, ecto support is on the to-do list.)
Feed downloading: Redirected feeds
Feeds that redirect to an empty or broken URL no longer get placed back in the download queue over and over.
Example feeds: http://waiterrant.net/wp-rss2.php http://zombtracker.the-zomb.com/rss.php
The symptom of the bug was that, during a download session, the number of feeds to download would just keep growing and growing, as these feeds were redirecting badly over and over. Now the app can deal with these.
If you find other redirected feeds causing problems, please let me know. (You'll know it when the feeds-to-download count keeps going up and the download session doesn't end. You can open up the Activity Window and find out what feed is causing the problem, then send me the URL of that feed.)
Feed downloading: hits disk less
The 3.x series had changed how feeds were downloaded -- they were downloaded to disk instead of memory. Which sounds good, until you realize that they still have to be read into memory to be parsed and processed. So all this was really doing was adding additional reads and writes to disk, instead of actually saving memory and performance.
So I went back to how it worked in 2.x -- feed data is downloaded into memory, parsed and processed, then written to disk (and purged from memory, of course). This may make download sessions a bit more smooth, since there's less file-system access.
Feed downloading: memory
Sometimes a downloaded feed was in memory twice -- now just once, for a memory savings and one less disk access.
Feed parsing: Ignoring non-feeds
Sometimes feeds return an HTML page (for whatever dumb reason). NetNewsWire would try to parse them with the RSS parser. Now it checks to see if it looks like an HTML page, and doesn't bother to try to parse. (Which saves some CPU time and temporary memory use in those cases.)
Feed parsing: RSS performance/memory enhancement
Ignores non-elements when they should be ignored, saving a little on performance and memory use during RSS parsing.
NewsGator syncing: performance
Changed how read/unread status is synced. The old way was terrible for performance -- the new way is much better.
Here's an explanation:
The old way was via a call to a method named SetState on the server. The response looked (conceptually) like this:
postID: state
Or...
49567024965024: 1 23948203942094: 0 etc.
So NetNewsWire had to loop through all the news items, because any news item might be referenced in the response. This was a lot of work and a lot of memory use.
The new call -- UpdatePostMetadata -- is more like this:
feedID: someID postID: state
Or...
feedID: 234234 postID: 49567024965024 state: 1 feedID: 252366 postID: 23948203942094 state: 1
The obvious thing here is the feedID. This tells us which feed a given post is in, which means NetNewsWire just has to look in specific feeds.
In case that doesn't make sense, look at it this way -- which house is easier to find, based on the address?
1075 NW Elk St.
Or...
1075 NW Elk St. Kansas City
(Never mind the issue of duplicates -- pretend there can be only one 1075 NW Elk St.)
The main thing this will do is help performance at the beginning of syncing -- which is also the beginning of the download process. It should be faster, use less memory and CPU, and hit disk less.
NewsGator syncing: flagged items
Works partly now, as part of the change above. Still more work is needed to make this work fully.
NewsGator syncing: feedback in Activity window
Added some more feedback to the activity window during the NewsGator syncing phase.
Performance: headlines table and hitting disk
If you use traditional or widescreen view, and you don't have summaries showing in the headlines table, NetNewsWire can often now build the headlines table without hitting the disk, even if descriptions and summaries have been swapped out to disk.
Performance: caching last update dates
A major performance boost for people who sort their subscriptions by last update date: NetNewsWire now caches the dates instead of calculating them on the fly.
Things might be a little unsorted until the calculating and caching all takes place. One way to force it to calculate and cache all the dates is to open the Dinosaurs window.
Keep-in-memory behavior
If you have less than 200 feeds and your global persistence setting is set *not* to keep items (or not for long), then NetNewsWire keeps all news items in memory rather than cleaning them out. This is a performance boost for people whose use fits this pattern. (My sense is that the average user will get a benefit from this, since most people don't have hundreds of feeds and persistence.)
This change prevents the typical user from being penalized by changes that benefit people with giant subscription lists.
Misc. memory use fixes
Found a workaround for the memory leak when getting an NSImage from a CIImage: More info on my weblog.
Feeds that aren't NewsGator synced use slightly less memory as they no longer contain an empty dictionary for sync attributes.
News items take up less memory
I've reduced the amount of memory that each news item uses by a little bit: instead of storing the full path to the item on disk, it just stores the filename, since the path is easy to get from the item's source object.
Say this saves 80 characters in each news item, and you have 10,000 news items. That works out to (80 * 10000) / 1024 K -- or 781.25 K. Nothing to sneeze at. (Nothing to jump and down about though, either. Still, worth doing.)
Misc. performance fixes
The browser tabs were being redrawn way too often, which used quite a bit of CPU. Fixed.
The browser tab thumbnail images were being read from disk every time they were being drawn. Now they're cached in memory until no longer needed.
If you have tab thumbnails hidden, they're no longer created, saving a little CPU and memory.
The feeds-in-page popup button was being updated way too often, and the results weren't being cached. (It's an expensive thing, because it involves treating the page as an XML document and running XPath queries on it.) Fixed -- it now gets updated only when needed, and results are cached per-URL. (Cached only for the current session.) This helps overall performance and also performance when switching from tab to tab.
Much better code for HTML generation (in regular and Combined View) -- doesn't generate so many temporary strings.
Optimized handling the main UI color. (Doesn't call into NSUserDefaults every time it's asked for.)
Creating fewer temporary strings and various other objects during table and outline data source methods.
Optimized some of the custom view drawing code.
Misc. crashing bug fixes
Fixed a threading-related crash getting the summary (or calculated summary) that could happen when displaying summaries in the headlines table when a feed is being updated.
Fixed a crashing bug related to asking a subs list folder if it's expanded -- if not on the main thread, don't ask.
Fixed a crashing bug when searching. (A threading issue -- a lock was needed.)
Fixed a Combined View generation crash. (Another threading issue.)
Enclosures: feature restored
(Obviously, I want to go to the next step -- for instance, the Combined View should know about enclosures. But step one is just restoring the feature.)
Under the hood, NetNewsWire now handles multiple enclosures per item -- but this isn't yet exposed through the UI or through AppleScript. (I don't know if multiple enclosures will get exposed before 3.0 ships.) (It was because of this under-the-hood change that enclosures were temporarily turned off.)
Dinosaurs in the subscriptions list: feature restored
Once again, feeds older than 60 days turn brown in the subscriptions list. Yes, it's cruel, cruel software. ;)
(They won't necessarily turn brown right away, because of the date caching change mentioned previously. Once the date for a feed has been calculated and cached, then it will turn brown if it's a 60-day dinosaur.)
WebViews and plugin loading/unloading
Non-visible tabs should not unload their plugins.
(I think I'm finally using setHostWindow correctly -- that is, I'm setting it for every WebView, even when they're not actually in a window (which I think is the point of this). Before removing a browser tab WebView I'm calling setHostWindow with nil to avoid a retain cycle.)
WebKit Cache
I finally figured out how to get an alternate location for the WebKit cache. It's now at ~/Library/Caches/NetNewsWire/WebKitCache/
(Yes, I've tried to put it there before, but I've only just now got it working.)
The reason for doing this is because it's recommended by Apple, actually - the WebKit cache folder shouldn't contain other cached stuff, which is what I was doing. All better now.
(For people who are curious about this kind of thing, there ismore info on my weblog.)
.Mac/FTP syncing
Probably fixed a performance issue with syncing tabs.
Growl
No longer sending any pending Growl notifications if NetNewsWire is shutting down.
Misc. AppleScript
Fixed some headline properties which were broken: isFake, subject, creator.
Fixed a bug getting the description (content) of a news item via AppleScript.
Misc. UI
Feed Reports window is now a regular window instead of a panel.
The Colors and Info windows now have standard backgrounds.
Sites Drawer is back to standard window background.
Added credits for UKCrashReporter and Sparkle to About box.
Colors in the feed source window now match the UI color.
Reset demo period, so that anybody who had tried 2.x in the past can try 3.x for 30 days.
Full screen mode fixes
Full screen mode was supposed to not show the window top (no traffic light buttons). Fixed.
Also -- NetNewsWire leaves full screen mode on quit (if in full screen mode).
Removed feature: Bonjour sharing
This is a little treat for people who read all the way to the end of the change notes...
The Bonjour sharing feature has been removed, which removes some code, a thread (the Bonjour server), a prefs pane, a tab item in the Sites Drawer, a pane in the Info window, 32 bits per datasource, and some data in the subscriptions list on disk.
You can't overestimate the joy I get from removing features. ;)
Here's a little note that developers might find interesting:
The data source (feed) object in NetNewsWire has a struct that stores flags as bit fields (instead of using a bunch of BOOLs). With stuff like this you want it to be a multiple of 32. I had 33 flags, so (with padding) the flags took up 64 bits per feed. Removing the Bonjour sharing flag for each feed meant I could have 32 flags instead, which saves 32 bits per data source object. Not a big deal -- not earth-shaking, not even really noticeable -- but it's real. Say you have 200 feeds -- it would save just over 6K. (Which is lost in the noise, because a single image from a web page will likely be more than 6K. But still, I'll take every memory savings I can get.) The main thing is that 33 felt just so wrong, and 32 is so right, that I just about did a jig. (I may never add another per-feed setting just because I don't want to disturb my perfect 32 flags. ;)
typedef struct __RSDataSourceFlags {
unsigned int subscribedTo:1;
unsigned int needsUsernameAndPassword:1;
unsigned int settingsDirty:1;
unsigned int dataItemsDirty:1;
unsigned int beingRead:1;
unsigned int beingProcessed:1;
unsigned int manualSubscription:1;
unsigned int triedLinkTag:1; /*8*/
unsigned int gotURLFromSourceList:1;
unsigned int guessedURL:1;
unsigned int attemptedFaviconDownload:1;
unsigned int useCustomRefreshSchedule:1;
unsigned int skipDuringManualRefresh:1;
unsigned int suspended:1;
unsigned int useCustomPersistenceSettings:1;
unsigned int persistItems:1; /*16*/
unsigned int useCustomSharingSettings:1;
//unsigned int includeInRendezvous:1;
unsigned int includeWhenExporting:1;
unsigned int markingAllAsRead:1;
unsigned int beingRedirected:1;
unsigned int askingUserForAuthentication:1;
unsigned int useCustomEnclosureSetting:1;
unsigned int automaticallyDownloadAudioEnclosures:1;
unsigned int automaticallyDownloadOtherEnclosures:1; /*24*/
unsigned int newSubscription:1;
unsigned int isAtomFeed:1;
unsigned int isAtom10Feed:1;
unsigned int syncDirty:1;
unsigned int firstNGSync:1;
unsigned int skipAutoDiscovery:1;
unsigned int userExcludesFromNewsGatorSyncing:1;
unsigned int is60DayDinosaur:1; /*32*/
} _RSDataSourceFlags;