17 March 2009 - 20:37Weave 0.3 M5 (Weekly 2009/11-3)
We released Weave 0.3 M5 last week March 12th, so I got in a bit of hacking for the first half of the week. This initially involved more deleting code than adding code though, but I’m probably just being obsessive-compulsive about keeping things clean and orderly. But the more interesting part is finally getting some initial UI for helping users get out of a “broken state”. I then got to fixing things up for the new text view for About:Tab by refactoring code from the thumbnail view.
Weave Debugging Sync UI
The initial debugging sync UI is to help users get out of situations where the server might contain incorrectly encrypted data (perhaps you accidentally used two different passphrases) or some other reason your local data isn’t syncing to the weave server. So for now, you can use the buttons to wipe the server data, wipe local data and resync with the server, or wipe remote data and have them resync with the server.
It’s kind of neat watching the local wipe clear out the bookmarks toolbar and then have it fill in with the bookmarks encrypted on the server. But don’t get too attached to the interface. We’ll be switching it to be more user friendly such as having diagrams of which way you’re syncing data (two-way sync, one way to your machine, one way to other machines) as well as being able to select which pieces of data to push out.
But this initial step is just getting the right logic to perform the various syncs. For example, I created a way to have each data engine reset their local temporary data without completely wiping out permanent data. Previously, there was just a single resetEngine method, but some engines treated that as wiping. There’s a whole set of service calls to reset and wipe the local/remote client and server now.
Weave Refactoring
The first thing I cleaned up was the syncing logic of choosing which engines to sync. Right now weave syncs all engines, but some previous version used to sync engines by thresholds. The threshold syncing was actually handled by a separate code path, but it did pretty much the same thing as a full sync. So I just combined the two and cleaned up the callers and fixed some divergences in the code. There were potential bugs in the unused threshold sync because we’ve only been updating the full sync code.
Another refactoring was deciding if a sync should run and if we should schedule a sync. Both of these were basically checking a number of statuses such as logged in, enabled, etc.; so I just combined them to simplify the logic for the two. This made me feel much cleaner about making weave not try syncing when in private browsing or offline — I only had to make changes to the unified “check sync” logic instead of duplicating code all over the place.
One last cleanup I got in was switching code to use the lazy services attached to the Weave.Svc object. Instead of having each object differently implementing their own lazy services, they could just re-use the lazy property that might already have gotten the service. Some of the original code checked if a “private” instance existed and returned that, others had a getter define another getter with a local closure to capture the instance, and some just grabbed the service directly. Instead of having all these class ids and interfaces scattered throughout the code, the centralized code can efficiently implement laziness as well as simplify debugging.

New Tab Text View
After looking through the initial feedback for the new tab page, Aza made a text-focused view for the new tab page, which got rid of all the thumbnails that were slow and not too useful. This was a whole separate page that had its own logic, but I cleaned things up by refactoring the shared data logic between the thumbnail and text views.
It turns out this is a good way to figure out how code should be structured to be reusable with different views. For example, the code for picking out which sites to show as well as their accompanying feeds were already in their own separate modules, but various clean-up code that could be used by both could be pushed to the data source as well.
However, I did run into an issue moving <script> code into a Cu.import module. Apparently plain unicode characters work just fine in the script code, but when imported, they need to be escaped like \u2013 for –. So I just escaped them when sharing the subtitle trimming code between the two views.
New Tab Customization
Another feature added recently was the ability to persist site removal. A lot of people want to customize their site list, so now you can just keep removing sites until you find the one you want. This actually ended up being fairly simple to implement as the back-end site storage just kept an array of sites to use, so modifying that structure allowed it to persist across new tabs.
Also, by reusing that site storage, we allow configuration of the number of feeds (or none) for each site, and that gets persisted across new tabs. With all this data in that shared storage, it shouldn’t be hard to get cross-browser data. All that needs to be done is to write the data out to disk, perhaps in a preference. Javascript now has a handy JSON object to stringify and parse json objects, so writing and reading the array is easy.
New Tab Performance
One last thing in terms of performance is that both sites and feeds are being prefetched on browser load. This is done asynchronously (yay Shawn!) so it doesn’t block the main thread which handles drawing and UI. The sites fetching code needed to be switched to use async queries, but that just needed some code restructuring. Instead of using a return value right away, pass the site getter a callback that gives the result. So for prefetching, the callback is used to trigger yet another async query, but this time for feeds. 🙂
Looks like you’ve been busy Ed!