<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Timm Preetz</title><description>Posts and updates from Timm Preetz.</description><link>https://timm.preetz.xyz</link><item><title>A touch-screen remote control for Linn Selekt DSM, using Rust on ESP32</title><link>https://timm.preetz.xyz/p/linn-remote-esp32-embedded-rust</link><guid isPermaLink="true">https://timm.preetz.xyz/p/linn-remote-esp32-embedded-rust</guid><pubDate>Tue, 19 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&amp;lt;a href=&quot;https://www.youtube.com/watch?v=WTHIx9r_eZs&quot;&amp;gt;&amp;lt;img class=&quot;inline-img&quot; src=&quot;/assets/posts/linn_remote/bombardier_7500_oled_knob.jpg&quot; alt=&quot;Bombardier 7500 OLED Knob&quot;&amp;gt;&amp;lt;/a&amp;gt;&lt;/p&gt;
&lt;p&gt;While engineering the requirements for a client project to build a lighting control app to run on the infotainment / Cabin Management System (CMS) iPads on a Bombardier Global 6000 jet (&lt;a href=&quot;https://www.vistajet.com/en/private-jets/bombardier/global-6000/&quot;&gt;like this&lt;/a&gt;), I came across this integrated screen/rotary dials built into the newest version of these planes.&lt;/p&gt;
&lt;p&gt;&amp;lt;a href=&quot;https://www.amazon.de/knob/dp/B0F8QWF7N3&quot;&amp;gt;&amp;lt;img class=&quot;inline-img-left&quot; src=&quot;/assets/posts/linn_remote/heltec_knob.jpg&quot; alt=&quot;Heltec ESP32-S3 Knob&quot;&amp;gt;&amp;lt;/a&amp;gt;&lt;/p&gt;
&lt;p&gt;While such custom hardware and embedded development was not something feasible on the given timeline (and would require physical changes to the aircraft), creating such a purpose-built gadget left me intrigued. Since I have no API-enabled smart lighting system at home, I instead opted to build a remote for my &lt;a href=&quot;https://www.linn.co.uk/de/network-music-players/selekt-dsm&quot;&gt;Linn Selekt DSM&lt;/a&gt; HiFi system instead. I knew that it does have an API, and having a dedicated piece of hardware seemed so much nicer than having to use the iPhone app (which does not have any live activities or similar to speed up control).&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We all have desires, things we want to build, ways to express ourselves, ways that we find joy and meaning.&lt;/p&gt;
&lt;p&gt;– &lt;a href=&quot;https://colossus.com/article/scott-wu-tapes-cognition/#:~:text=think%20that%E2%80%99s%20right.-,We%20all%20have%20desires,-%2C%20things%20we%20want&quot;&gt;Scott Wu&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;As it turns out you can even get a basic variant of that hardware (IPS instead of OLED, but a solid &quot;scroll wheel&quot; with a ball-bearing around the display) on Amazon[^1]. Unfortunately that device&apos;s chip (ESP32-S3) is a little harder to get started with using my preferred Rust toolchain, so I opted for a &lt;a href=&quot;https://www.waveshare.com/esp32-c6-touch-amoled-1.43.htm&quot;&gt;ESP32-C6 board&lt;/a&gt; with an OLED display (but sadly no wheel) instead.&lt;/p&gt;
&lt;p&gt;Luckily the overall development environment is stable at this point and the basic setup to get started is &lt;a href=&quot;https://docs.espressif.com/projects/rust/book/&quot;&gt;well documented&lt;/a&gt;. With those docs and Claude I was able to get a basic &quot;app&quot; running on that device in no time at all.&lt;/p&gt;
&lt;p&gt;The streamer has a &lt;a href=&quot;https://docs.linn.co.uk/wiki/index.php/Developer:LPEC&quot;&gt;documented control protocol&lt;/a&gt; and with a bit of debugging real responses a client class was built in no time. On the UI layer the generated code was a bit convoluted in the &quot;AI does not tire of writing code&quot;-sense, e.g. display and touch handling were entirely distinct, even though of course there should be a close relation between what&apos;s rendered on screen and what areas receives touches. But with my previous knowledge of the Flutter rendering stack, I guided the implementation in a direction I felt comfortable with, building small widgets which only redraw their own area of the screen, and having input aligned with the rendering.&lt;/p&gt;
&lt;p&gt;One downside of the hardware I picked is that it doesn&apos;t have a built-in battery, which would be really cool for a remote. So for now I have to tack one to the back, but I hope that the next generation of ESP32-S31 boards will come in a nicer packaging so that I can revisit this again.&lt;br /&gt;
Having the physical rotating knob would be an especially nice upgrade, and overall the displays could always be a bit bigger and higher resolution.&lt;/p&gt;
&lt;p&gt;But after a bit of tinkering the whole package works now: It connects to WiFi and can be powered off via the hardware button and thus lasts a long time without needing a charge.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&amp;lt;img class=&quot;inline-img&quot; src=&quot;/assets/posts/linn_remote/linn_remote_oled_1.jpeg&quot; alt=&quot;Linn OLED Remote&quot; /&amp;gt;&lt;/td&gt;
&lt;td&gt;&amp;lt;img class=&quot;inline-img&quot; src=&quot;/assets/posts/linn_remote/linn_remote_oled_2.jpeg&quot; /&amp;gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;So overall I am happy about how this turned out and how it made me change my mind on what&apos;s possible to build. Looking forward to what&apos;s next!&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;How many ideas does one person have in a day, and how many of those things do they actually get to do? Until that proportion is 100%, you know there is a pretty meaningful bottleneck in terms of the drudgery of execution.&lt;/p&gt;
&lt;p&gt;– &lt;a href=&quot;https://colossus.com/article/scott-wu-tapes-cognition/#:~:text=put%20this%20is%3A-,How%20many%20ideas,-does%20one%20person&quot;&gt;Scott Wu&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The full code is &lt;a href=&quot;https://github.com/tp/esp32_home/&quot;&gt;available on GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;[^1]: For that specific board there is even a fully implemented Roon remote control &lt;a href=&quot;https://github.com/muness/roon-knob&quot;&gt;up on GitHub&lt;/a&gt;.&lt;/p&gt;
</content:encoded></item><item><title>Building an Odometer for Playlist Counts in SwiftUI</title><link>https://timm.preetz.xyz/p/swiftui-odometer</link><guid isPermaLink="true">https://timm.preetz.xyz/p/swiftui-odometer</guid><pubDate>Sun, 17 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;For a playlist count feature in an upcoming app I wanted it to update a little more prominently as a feedback when skipping a song or adding new items to the queue. This would also apply to every normal &quot;next song&quot; transition, but in that case few people are likely to watch.&lt;/p&gt;
&lt;p&gt;I knew about SwiftUI&apos;s &lt;code&gt;.contentTransition(.numericText())&lt;/code&gt; but was dismayed that the number always rolled in from below, which didn&apos;t make much sense for the usual case of &lt;code&gt;-1&lt;/code&gt; when the next song started playing. Turns out I was not using it correctly: One just needs to pass in the count as the &lt;code&gt;value&lt;/code&gt; parameter, and then the effect would align the direction accordingly.&lt;/p&gt;
&lt;p&gt;Unfortunately before finding that tiny fix, I recalled an article by &lt;a href=&quot;https://livsycode.com/swiftui/an-odometer-style-number-animation-in-swiftui/&quot;&gt;Livsy about building an Odometer in SwiftUI&lt;/a&gt; building atop that inbound effect. The main point was that SwiftUI directly goes from current to next, whereas for a more interactive feel it can be nice to count up (or down) to show the intermediate steps. That approach works well and is a nice and compact improvement atop the core behavior.&lt;/p&gt;
&lt;p&gt;But what kept bothering me was that SwiftUI would always use a blurred transition between the numbers instead of a real &quot;wrap around wheel&quot; style like we&apos;ve seen on the iOS date / time picker.&lt;/p&gt;
&lt;h2&gt;Custom &lt;code&gt;Odometer&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;So I set out to build my own variant based on that effect. While trying out various approaches to handle this, the most important parts were breaking up the number into separate digits to be able to control them individually and then building the animation for each one. Each digit view contains the numbers 0-9 in a wrap around way using a combined effect of &lt;code&gt;rotation3DEffect&lt;/code&gt;, &lt;code&gt;offset&lt;/code&gt;, &lt;code&gt;scale&lt;/code&gt; and &lt;code&gt;opacity&lt;/code&gt;. To keep it clean only the active digit is shown on rest, and the adjacent one becomes visible while it animates in place.&lt;/p&gt;
&lt;p&gt;Then came a lot of playing around with the widget and adjusting the animation curves. For the default transition (±1) I just let SwiftUI handle it across 1 or 2 digits using &lt;code&gt;.animation(…, value: digit)&lt;/code&gt;. For bigger changes we step through all the intermediate numbers at a slightly faster clip, but still slow enough that one can make out the individual steps. I capped this at 20 which is plenty for the current use-case and didn&apos;t become boring yet (though maybe I am currently too enamoured with this view). For distances beyond that we enter a kind of &quot;reset&quot; where each digit just rotates to the destination in the fastest way possible (not necessarily up or down as given by the count change). Here we step through with aligned timing/distances, so one digit/wheel might settle before the others (which to me makes sense if the distance was shorter). In order to manage this transition and &quot;trust&quot; the animation without stepping through many cases in testing each time I opted to first model the transitional steps on a data layer (which could easily be tested), and then just apply each successive step after a short timeout.&lt;/p&gt;
&lt;h2&gt;Demo&lt;/h2&gt;
&lt;p&gt;The final piece looks as follows (at the bottom, with the stock animations shown atop for comparison):&lt;/p&gt;
&lt;p&gt;&amp;lt;center&amp;gt;
&amp;lt;figure&amp;gt;
&amp;lt;video autoplay loop muted playsinline style=&quot;max-width: 300px;&quot;&amp;gt;
&amp;lt;source src=&quot;/assets/posts/swiftui-odometer.mp4&quot; type=&quot;video/mp4&quot;&amp;gt;
&amp;lt;/video&amp;gt;
&amp;lt;figcaption&amp;gt;
&amp;lt;code&amp;gt;.contentTransition(.numericText())&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.contentTransition(.numericText(value: count))&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;OdometerView&amp;lt;/code&amp;gt;&amp;lt;/figcaption&amp;gt;
&amp;lt;/figure&amp;gt;
&amp;lt;/center&amp;gt;&lt;/p&gt;
&lt;h2&gt;Source Code&lt;/h2&gt;
&lt;p&gt;And this is the code to implement this:&lt;/p&gt;
&lt;p&gt;&amp;lt;script src=&quot;https://gist.github.com/tp/2ceb617b41c67e89644580ff83297e6a.js&quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;/p&gt;
</content:encoded></item><item><title>Speeding up batch inserts in SQLite using dynamic statements</title><link>https://timm.preetz.xyz/p/sqlite-batch-inserts-single-statement</link><guid isPermaLink="true">https://timm.preetz.xyz/p/sqlite-batch-inserts-single-statement</guid><pubDate>Sun, 24 Nov 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://pub.dev/packages/indexed_entity_store&quot;&gt;&lt;code&gt;indexed_entity_store&lt;/code&gt;&lt;/a&gt;&apos;s &lt;code&gt;writeMany&lt;/code&gt; used to insert a batch of items in a single transaction, but using &lt;em&gt;n&lt;/em&gt; individual &lt;code&gt;REPLACE INTO&lt;/code&gt; statements (and then the corresponding index updates). In my testing I saw it take ~10ms for 1000 items with a small JSON payload (which serialization time is included in the total).
This &lt;a href=&quot;https://github.com/simolus3/sqlite3.dart/issues/260#issuecomment-2447854905&quot;&gt;is considered best practice&lt;/a&gt; and does seem okay for most practical one-time batch imports of data (such that one did not have to resort to an &lt;code&gt;async&lt;/code&gt; initial setup to avoid multi-frame drops).&lt;/p&gt;
&lt;p&gt;Initially I wondered why, even inside the transaction, we had to loop over the individual inserts and could not execute a single statement which would write all data at once (up to a point I suppose, as there is surely a practical limit on how large a query can get, though than a similar constraint might apply to the in-progress transaction side.)&lt;/p&gt;
&lt;p&gt;As it turns out we can insert multiple row just fine in a single statement, it&apos;s just a little bit unusual to write as SQLite does not allow binding to lists of values.&lt;br /&gt;
So from our single insert compiled statement (&lt;code&gt;REPLACE INTO entity (type, key, value) VALUES (?, ?, ?)&lt;/code&gt;) we have to switch to a dynamically generated on that accounts for the number of inserts we want to do: &lt;code&gt;REPLACE INTO entity (type, key, value) VALUES (?1, ?, ?), (?1, ?, ?), … (?1, ?, ?)&lt;/code&gt;. That way we can call execute this statement with a concatenated parameter list of all the entities we want to write.[^1]&lt;/p&gt;
&lt;p&gt;This pattern has been implemented in &lt;a href=&quot;https://github.com/LunaONE/indexed_entity_store/pull/26&quot;&gt;this PR&lt;/a&gt;, and indeed shows some nice improvements for my tests of batch sizes 1,000 and 10,000:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Batch size&lt;/th&gt;
&lt;th&gt;Transaction (old)&lt;/th&gt;
&lt;th&gt;Single statement (new)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1,000&lt;/td&gt;
&lt;td&gt;&lt;code&gt;writeMany&lt;/code&gt; took 7.41ms&amp;lt;br&amp;gt;&lt;code&gt;writeMany&lt;/code&gt; again took 17.59ms&lt;/td&gt;
&lt;td&gt;&lt;code&gt;writeMany&lt;/code&gt; took 2.47ms&amp;lt;br&amp;gt;&lt;code&gt;writeMany&lt;/code&gt; again took 5.38ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10,000&lt;/td&gt;
&lt;td&gt;&lt;code&gt;writeMany&lt;/code&gt; took 69.68ms&amp;lt;br&amp;gt;&lt;code&gt;writeMany&lt;/code&gt; again took 134.04ms&lt;/td&gt;
&lt;td&gt;&lt;code&gt;writeMany&lt;/code&gt; took 21.74ms&amp;lt;br&amp;gt;&lt;code&gt;writeMany&lt;/code&gt; again took 43.21ms&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Overall this resulted in a nice 3x speed-up. That is a fine start, but does not really change the ballpark speed of the operation in the general case.&lt;/p&gt;
&lt;p&gt;Further I wondered whether the small payload sizes used in the example would benefit either one of the approach. So I ran another test where each entity had a ~10kB payload JSON.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Batch size&lt;/th&gt;
&lt;th&gt;Transaction (old)&lt;/th&gt;
&lt;th&gt;Single statement (new)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1,000&lt;/td&gt;
&lt;td&gt;&lt;code&gt;writeMany&lt;/code&gt; took 261.57ms&amp;lt;br&amp;gt;&lt;code&gt;writeMany&lt;/code&gt; again took 474.71ms&lt;/td&gt;
&lt;td&gt;&lt;code&gt;writeMany&lt;/code&gt; took 133.56ms&amp;lt;br&amp;gt;&lt;code&gt;writeMany&lt;/code&gt; again took 193.89ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10,000&lt;/td&gt;
&lt;td&gt;&lt;code&gt;writeMany&lt;/code&gt; took 2334.00ms&amp;lt;br&amp;gt;&lt;code&gt;writeMany&lt;/code&gt; again took 5128.63ms&lt;/td&gt;
&lt;td&gt;&lt;code&gt;writeMany&lt;/code&gt; took 1159.16ms&amp;lt;br&amp;gt;&lt;code&gt;writeMany&lt;/code&gt; again took 1849.37ms&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;In this case the new approach still resulted in a 2x speed-up and did not run into any size limits. I did not measure the peak memory usage, but very likely this would have been higher in the new case, were all serialized entities are passed to the SQLite library in 1 call vs. the loop-approach, where Dart&apos;s GC has a chance to clean up each individual entity after passing it off.&lt;/p&gt;
&lt;p&gt;Lastly I wondered how much of a penalty in these real-life tests was the overall JSON serialization (which one can exchange for a smaller and/or more efficient storage format). So in the last comparison I just saved the primary payload string straight to the database, without any JSON serialization:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Batch size&lt;/th&gt;
&lt;th&gt;Transaction (old)&lt;/th&gt;
&lt;th&gt;Single statement (new)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1,000 (small)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;writeMany&lt;/code&gt; took 6.27ms&amp;lt;br&amp;gt;&lt;code&gt;writeMany&lt;/code&gt; again took 12.00ms&lt;/td&gt;
&lt;td&gt;&lt;code&gt;writeMany&lt;/code&gt; took 1.87ms&amp;lt;br&amp;gt;&lt;code&gt;writeMany&lt;/code&gt; again took 3.29ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1,000 (large)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;writeMany&lt;/code&gt; took 248.43ms&amp;lt;br&amp;gt;&lt;code&gt;writeMany&lt;/code&gt; again took 451.07ms&lt;/td&gt;
&lt;td&gt;&lt;code&gt;writeMany&lt;/code&gt; took 86.97ms&amp;lt;br&amp;gt;&lt;code&gt;writeMany&lt;/code&gt; again took 138.00ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10,000 (small)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;writeMany&lt;/code&gt; took 59.21ms&amp;lt;br&amp;gt;&lt;code&gt;writeMany&lt;/code&gt; again took 121.93ms&lt;/td&gt;
&lt;td&gt;&lt;code&gt;writeMany&lt;/code&gt; took 12.74ms&amp;lt;br&amp;gt;&lt;code&gt;writeMany&lt;/code&gt; again took 32.15ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10,000 (large)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;writeMany&lt;/code&gt; took 1925.63ms&amp;lt;br&amp;gt;&lt;code&gt;writeMany&lt;/code&gt; again took 4741.23ms&lt;/td&gt;
&lt;td&gt;&lt;code&gt;writeMany&lt;/code&gt; took 743.32ms&amp;lt;br&amp;gt;&lt;code&gt;writeMany&lt;/code&gt; again took 1432.79ms&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Interestingly this did not result in a big speed-up compared to building the JSON values in the previous test run. But somehow the new approach benefited much more from this than the old one, making it even faster especially for larger payloads.&lt;/p&gt;
&lt;p&gt;Overall I would have expected to be able to gain more by doing less transitions from Dart to the SQLite C-library, but this confirms just how fast the in-process &lt;code&gt;ffi&lt;/code&gt; approach is and bigger gains would have to come from elsewhere.&lt;br /&gt;
The biggest difference in the approach seems to driven by the library&apos;s use of indices (to efficiently find entities later). When I disable them for testing, both approaches come very close to each other, but do not get significantly faster than the &quot;single insert with search indices&quot; approach. That suggests that there is a rather penalty being paid for updating the index table individually for each row entry (inside the transaction).&lt;/p&gt;
&lt;p&gt;[^1]: The &lt;code&gt;?1&lt;/code&gt; in all these cases is the &lt;code&gt;entity&lt;/code&gt; type, which is the same across all rows, and thus we provide it only once to keep the parameter list length a bit down.&lt;/p&gt;
</content:encoded></item><item><title>File storage in Flutter apps (Part 2)</title><link>https://timm.preetz.xyz/p/file-storage-flutter</link><guid isPermaLink="true">https://timm.preetz.xyz/p/file-storage-flutter</guid><pubDate>Sun, 17 Nov 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;/p/binary-data-sqlite-flutter&quot;&gt;Last week&apos;s article&lt;/a&gt; looked at various implementations of how to store files with metadata in SQLite using the package &lt;a href=&quot;https://pub.dev/packages/indexed_entity_store&quot;&gt;indexed_entity_store&lt;/a&gt;. This time, let&apos;s look at cases where you want to have the actual files on disk, with only its metadata stored in a database. Reasons for this might be that the files are very large, accessed often (e.g. for sharing, uploading), or need to be edited in place.&lt;/p&gt;
&lt;p&gt;To get consistency across the files and their metadata, let&apos;s implement a store that exposes a subset of the usual operations, but which takes care of the file management in addition to the metadata storage.&lt;/p&gt;
&lt;p&gt;The final interface should look something like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class FileStore&amp;lt;T&amp;gt; {
  // The directory this store is managing, and where it places its copy of the files
  final Directory baseDirectory;

  // Creates or updates an entry for T, backing it with the contents of `file`
  // If `file` is not &quot;owned&quot; by this store (e.g. not in its managed directory),
  // it will copy the file to take ownership of a copy of it.
  void write(T metadata, File file);

  // Returns a list of metadata + files matching the given query
  // The caller gets access to the files as they are managed by this store (e.g. residing in `baseDirectory`)
  // The caller may modify the files in place, but must not delete them on disk directly. For that they must use `delete` on this store in order to clean up the metadata as well.
  List&amp;lt;(T, File)&amp;gt; query(…);

  // Deletes the entry `metadata` refers to, as well as the backing file
  void delete(T metadata);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This implementation already incorporates some design choices, which could be adapted for different use-cases. Here the store will make sure that it always &quot;owns&quot; the underlying file. Thus when a file is added which does not reside in the directory managed by this store, it will copy it there and store a reference to that new location. On the flip-side (the reading) part, it will hand out &lt;code&gt;File&lt;/code&gt;s referencing its internal storage paths, such that the caller might modify the file in place. This introduces a trade-off though, such that the store itself does not get notified of in-place file modifications (which may or may not be relevant to know about). This could be alleviated by e.g. always copying the files to a temporary location for reading, and expecting the outside to call &lt;code&gt;write&lt;/code&gt; again after each change (at which point a copy would be written to the store&apos;s internal directory)[^1].&lt;/p&gt;
&lt;p&gt;An approach like the one outlined above is implemented &lt;a href=&quot;https://github.com/LunaONE/indexed_entity_store/tree/945725eb02deccd792a34c995f165e25340faf91/example/lib/src/examples/disk_file_store&quot;&gt;as an example here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For brevity only the &lt;code&gt;delete&lt;/code&gt; method is shown below, but &lt;code&gt;write&lt;/code&gt; is similarly the reverse as described above (copying the file into the store&apos;s realm if needed), and &lt;code&gt;get&lt;/code&gt; and &lt;code&gt;query&lt;/code&gt; are just straightforwards read from the store to get the metadata and file path.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class DiskFileStore&amp;lt;Metadata, Key&amp;gt; {
  final IndexedEntityStore&amp;lt;FileWithMetadata&amp;lt;T&amp;gt;, K&amp;gt; _store;

  /// Remove the entry identified by [key] from the store, and deletes the backing file
  void delete({
    required K key,
  }) {
    final existingEntry = _store.readOnce(key);
    if (existingEntry != null) {
      File(existingEntry.filepath).deleteSync();

      _store.delete(key: key);
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That&apos;s it. By combining the metadata writes with the files, we can now ensure that the pair of them is always up to date, and we have a single, simple interface to manage them together.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://pub.dev/packages/indexed_entity_store/versions/2.0.0-dev3&quot;&gt;upcoming 2.0.0 version&lt;/a&gt; of the package will furthermore introduce some additional enhancement for this use-case: As a file usually belongs to some other entity and doesn&apos;t exist by itself, it will allow you to reference that &quot;parent entity&quot; from the file&apos;s metadata via an index, for example a mail attachment might reference the parent like this: &lt;a href=&quot;https://github.com/LunaONE/indexed_entity_store/blob/main/test/foreign_key_test.dart#L175-L177&quot;&gt;&lt;code&gt;index((e) =&amp;gt; e.metadata.mailId, as: &apos;mailId&apos;, referencing: &apos;mails&apos;);&lt;/code&gt;&lt;/a&gt;. This ensures that all file entries point to a valid parent. And if the parent gets deleted, its files must be cleaned up beforehand.&lt;/p&gt;
&lt;p&gt;The above excerpt and the example in general make a lot of assumptions and design choices which might not be ideal for every use-case. But since the full &quot;file store&quot; is only 100 lines of code, I think it&apos;s clear that it can be easily adapted to suite one&apos;s needs (e.g. handing out temporary files, or using &lt;code&gt;async&lt;/code&gt; file operations, ensuring notifications for file changes, etc.).&lt;/p&gt;
&lt;p&gt;[^1]: On modern copy-on-write filesystems, though would not even need to incur performance penalty for the cases where the file is not modified after all.&lt;/p&gt;
</content:encoded></item><item><title>Storing binary data in Flutter</title><link>https://timm.preetz.xyz/p/binary-data-sqlite-flutter</link><guid isPermaLink="true">https://timm.preetz.xyz/p/binary-data-sqlite-flutter</guid><pubDate>Sun, 10 Nov 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Data storage in a Flutter app initially usually focuses on storing some domain objects (e.g. chat messages), whereas binary data (files) are often either loaded on demand (e.g. attachment downloads) or cached transiently with something like &lt;a href=&quot;https://pub.dev/packages/cached_network_image&quot;&gt;&lt;code&gt;cached_network_image&lt;/code&gt;&lt;/a&gt; (e.g. for profile images).&lt;/p&gt;
&lt;p&gt;But what is to be done when one needs to permanently store files with the app, either as a local cache to reduce network usage across app runs, or to support offline functionality?&lt;/p&gt;
&lt;p&gt;Let&apos;s look it this from the perspective of persisting profile images, as these would generally be small enough to allow this thought experiment and to not force us into any specific storage medium by default.&lt;/p&gt;
&lt;h2&gt;Local files with pointers from the entities&lt;/h2&gt;
&lt;p&gt;Imagine a user class like &lt;code&gt;typedef User = ({int userId, String name, String? profileImagePath })&lt;/code&gt;. The &lt;code&gt;profileImagePath&lt;/code&gt; can be used to refer to a file on disk. This is easy enough to start with and populate initially, it would just be important to remove this file every time the that specific &lt;code&gt;User&lt;/code&gt; object is either removed or updated to point to a new profile image path.&lt;br /&gt;
Because when looking into the &quot;file folders&quot; afterwards (in some clean up operation), it&apos;s probably not easy to identify which files are actively in use, and which are not and thus could be removed.&lt;/p&gt;
&lt;h2&gt;Storing files separately in the database&lt;/h2&gt;
&lt;p&gt;If we just need to store some files by known keys (e.g. &lt;code&gt;profile_image_123&lt;/code&gt;), we could set up an &lt;a href=&quot;https://pub.dev/documentation/indexed_entity_store/2.0.0-dev2/indexed_entity_store/IndexedEntityStore-class.html&quot;&gt;&lt;code&gt;IndexedEntityStore&lt;/code&gt;&lt;/a&gt; like this that stores the image like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;typedef ProfileImage = ({int userId, Uint8List data});

/// Stores the profile images by user ID,
final profileImageConnector = IndexedEntityConnector&amp;lt;ProfileImage, int, Uint8List&amp;gt;(
  entityKey: &apos;profile_images&apos;,
  getPrimaryKey: (t) =&amp;gt; t.userId,
  getIndices: (index) {},
  serialize: (t) =&amp;gt; t.data,
  deserialize: (s) =&amp;gt; (userId: -1, data: s),
);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The problem with this approach is approach is similar to the file storage above. While we can easy check whether we have a specific profile image stored for a user and then retrieve it, we can not (with the current library methods) get a list of all the profile images with their user IDs as the key is only used for storage but then not returned in &lt;code&gt;deserialize&lt;/code&gt; or available to be queried (e.g. there is no &lt;code&gt;getAllKeys&lt;/code&gt;).&lt;br /&gt;
This minor limitations could of course alleviated in the store&apos;s API (though it&apos;s questionable whether this would be a broadly useful extension of it), but when we work with what is available right now, we would still have to manually clean up each profile image when the user is deleted.&lt;/p&gt;
&lt;p&gt;In a purpose-built SQLite-based storage for this use-case, one could of course have a foreign key from the profile images to the user, to ensure that they are removed in unison – or just make the profile image a column in the user table.&lt;/p&gt;
&lt;h2&gt;Storing the file with the entities&lt;/h2&gt;
&lt;p&gt;Another approach would be to store the file alongside the entity in whatever object storage the app uses. This introduces some obvious limitations, like the maximum file size (which is probably fine for a profile picture, not so much for a home video), and the amount of files any entity could refer to (is it 1 or 2, or &lt;code&gt;n&lt;/code&gt;?).&lt;/p&gt;
&lt;p&gt;It would probably not be advisable to put the profile image directly on the &lt;code&gt;User&lt;/code&gt; object using any approach (like &lt;code&gt;typedef User = ({int userId, String name, Uint8List? profileImage })&lt;/code&gt;), as that would leave no way to pass around the &lt;code&gt;User&lt;/code&gt; without the image data.
Also when serializing this, one would have to handle the primitive data and the user image separately, as the usual &lt;code&gt;toJSON&lt;/code&gt; would not be satisfactory by default.&lt;/p&gt;
&lt;h2&gt;Storing files with metadata&lt;/h2&gt;
&lt;p&gt;So, if one still wants to store the files in the database, but not directly with the containing entity (such that also one-to-many relationship would also be possible without building bigger and bigger BLOBs), one might choose to save the file plus some metadata as its own entity.&lt;/p&gt;
&lt;p&gt;The constraint of our chosen storage solution is though, that we only get one database field to write everything into. Thus we have to implement a storage format that can handle both the metadata and the binary data. In this case we&apos;ll assume that the metadata is much smaller than the actual data, and will prepend the metadata (as JSON in this case) in front of the &lt;code&gt;Uint8List&lt;/code&gt; binary data.&lt;/p&gt;
&lt;p&gt;The storage inside the database would look like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;-------------------------------------------------------------
| Metadata length | Metadata JSON |       Binary data       |
-------------------------------------------------------------
     4 bytes        $length bytes           * bytes
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The implementation of that storage approach might looks like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;typedef ImageWithMetadata = ({ImageMetadata metadata, Uint8List data});

final imageWithMetadataConnector =
    IndexedEntityConnector&amp;lt;ImageWithMetadata, int, Uint8List&amp;gt;(
  entityKey: &apos;user_profile_image&apos;,
  getPrimaryKey: (t) =&amp;gt; t.metadata.userId,
  getIndices: (index) {
    index((t) =&amp;gt; t.metadata.userId, as: &apos;userId&apos;);
    index((t) =&amp;gt; t.metadata.fetchedAt, as: &apos;fetchedAt&apos;);
  },
  serialize: (t) {
    final metadataJSON = JsonUtf8Encoder().convert(t.metadata.toJSON());

    final lengthHeader = Uint8List.view(
      // uint32 is enough for 4GB of metadata
      (ByteData(4)..setUint32(0, metadataJSON.length)).buffer,
    );

    return (BytesBuilder(copy: false)
          ..add(lengthHeader)
          ..add(metadataJSON)
          ..add(t.data))
        .takeBytes();
  },
  deserialize: (s) {
    // Get the lenght of the metadata
    final metaDataLength = ByteData.view(s.buffer).getUint32(0);

    final jsonDecoder = const Utf8Decoder().fuse(const JsonDecoder());
    final metaData = ImageMetadata.fromJSON(
        // pass a view into the metadata into the JSON decoder
      jsonDecoder.convert(Uint8List.view(s.buffer, 4, metaDataLength))
    );

    return (
      metadata: metaData,
      // Pass out the binary data as a read-only view into the raw value retrieved from the database
      data: Uint8List.view(s.buffer, 4 + metaDataLength).asUnmodifiableView(),
    );
  },
);

class ImageMetadata {
    final int userId;
    final DateTime fetchedAt;
    final Uri fetchedFrom;

    // […] implementation of toJSON/fromJSON etc. is omitted for brevity
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With this approach we can just retrieve the profile image with it&apos;s metadata whenever we need it. As we stored the &lt;code&gt;userId&lt;/code&gt; and &lt;code&gt;fetchedAt&lt;/code&gt; properties as indexed columns, we can also easily query it for&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;no longer known user IDs (in case there was a bug and not all profile images where cleaned up when the user was deleted)&lt;/li&gt;
&lt;li&gt;remove stale images (say &lt;code&gt;fetchedAt&lt;/code&gt; is older than 7 days)&lt;/li&gt;
&lt;li&gt;Check the metadata&apos;s original request URL upon read and re-fetch the image if the server has a new version available&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A full-fledged example of this approach is available in &lt;a href=&quot;https://github.com/LunaONE/indexed_entity_store/blob/f35b55749f3afa1eb4b827ccb26b0e49888581aa/example/lib/src/examples/binary_data_storage.dart&quot;&gt;the repository here&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Next steps&lt;/h2&gt;
&lt;p&gt;For the last example it would be super beneficial if we could add a foreign key constraint between the profile image entity and the known users, thus ensuring that the images get cleaned up when a user gets deleted.&lt;br /&gt;
This is a further direction to explore in the library, as it seems universally useful, and guarding against this from every possible angle seems cumbersome in the application code (as only the database can reliably enforce such an invariant).&lt;/p&gt;
&lt;p&gt;Another abstraction to build on top of foreign key approach could be to combine disk file storage with such an external metadata storage, where insertions and deletions automatically handle the underlying file operations.&lt;br /&gt;
This seems much easier to get right on a single file basis for just &lt;code&gt;read&lt;/code&gt;/&lt;code&gt;write&lt;/code&gt; instead of handling it for various entity types whenever they get updated in the database.&lt;/p&gt;
</content:encoded></item><item><title>Designing repositories for Flutter apps on top of `IndexedEntityStore`</title><link>https://timm.preetz.xyz/p/flutter-repositories</link><guid isPermaLink="true">https://timm.preetz.xyz/p/flutter-repositories</guid><pubDate>Sun, 03 Nov 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://pub.dev/packages/indexed_entity_store&quot;&gt;&lt;code&gt;IndexedEntityStore&lt;/code&gt;&lt;/a&gt; is a new &lt;em&gt;synchronous&lt;/em&gt; database package to handle your Flutter app&apos;s persistent storage in an easy way, with a focus on simplicity and development speed.&lt;/p&gt;
&lt;p&gt;Though it handles data management and efficient querying, it&apos;s only a small building block in the app architecture. For most use-cases one wants to probably build repositories on top of this storage – in combination with one&apos;s backend APIs – to put a full data-layer in place.&lt;/p&gt;
&lt;p&gt;Let&apos;s now consider 3 examples approaches for how to do this. The API and usage of the package itself is not documented in detail, instead refer to the &lt;a href=&quot;https://pub.dev/packages/indexed_entity_store/example&quot;&gt;documentation&lt;/a&gt; if needed.&lt;/p&gt;
&lt;h2&gt;All the data, all the time&lt;/h2&gt;
&lt;p&gt;Consider a simple todo list app, where all the data is available all the time. If the app has a syncing capability, that might still run initially and throughout the usage of the app, but once these jobs complete 100% of the data of the app is available locally. This approach can lead to a very simple design.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class TodoRepository {
  TodoApi remoteApi;

  IndexedEntityStore&amp;lt;Todo, int&amp;gt; store;

  // Depending on the application&apos;s needs, this would either run initially before the user can interact with the app, or in the background
  Future&amp;lt;void&amp;gt; fetchAll() async {
    // This could be extended to only get new todos on subsequent calls, and then insert those locally
    final todos = await remoteApi.getTodos();

    store.insertMany(todos);
  }

  /// Return a live-updating query to the list of open todo items
  QueryResult&amp;lt;List&amp;lt;Todo&amp;gt;&amp;gt; getOpenTodos() {
    /// while the column access uses `String`s, it&apos;s still checked at runtime to refer to an indexed column
    return store.query((cols) =&amp;gt; cols[&apos;done&apos;].equals(false));
  }

  // Returns a &quot;view&quot; onto a stored todo item
  // The caller will automatically receive updates through the `ValueListenable` interface whenever the stored todo was changed in the database
  // The returned todo item is optional (nullable), as we assume that it might not have been synced to the local database when the request is made (e.g. because a todo detail page was opened via a deep link).
  // If the user could only navigate to existing/known items in the app, we could make it non-optional, which would simplify the usage site a bit.
  QueryResult&amp;lt;Todo?&amp;gt; getTodo(int id) {
    return store.get(id);
  }

  Future&amp;lt;void&amp;gt; updateTodo(Todo todo) {
    store.insert(todo);

    // Failure handling for this is left as an exercise to the reader. Depending on whether the app is offline-first or requires connectivity and instant updates on the server,
    // we could either store the todo with some &quot;sync pending&quot; flag locally and try again later, or roll back the local update in case the server call failed.
    await remoteApi.updateTodo(todo);
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Both read methods above (&lt;code&gt;getOpenTodos&lt;/code&gt; and &lt;code&gt;getTodo&lt;/code&gt;) return a &lt;code&gt;QueryResult&amp;lt;T&amp;gt;&lt;/code&gt; which implements &lt;code&gt;ValueListenable&amp;lt;T&amp;gt;&lt;/code&gt;. In a Flutter &lt;code&gt;Widget&lt;/code&gt; one could use a subscription to these results in combination with a &lt;code&gt;ValueListenableBuilder&lt;/code&gt; like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class _TodoListState extends State&amp;lt;TodoList&amp;gt; {
  late final openTodos = widget.repository.getOpenTodos();

  @override
  Widget build(BuildContext context) {
    return ValueListenableBuilder(
      valueListenable: openTodos,
      builder: (context, openTodos, _) {
        return Column( // or ListView.builder etc.
          mainAxisSize: MainAxisSize.min,
          children: [
          for (final openTodo in openTodos)
            CupertinoListTile(
              title: Text(openTodo.text),
            ),
          ],
        );
      },
    );
  }


  @override
  void dispose() {
    // important to unsubscribe here, so the database does not send any more updates into the `QueryResult`
    openTodos.dispose();

    super.dispose();
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;On-demand data loading with offline storage&lt;/h2&gt;
&lt;p&gt;Next let&apos;s image a use-case where the data is not (or can not) all be known beforehand, and we need to fetch it on demand. This could be the case for example with an event-planning app, where event details are fetched on first view and which would from then on be available locally (with potential background updates from the server to communicate new changes).&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class EventRepository {
  EventApi remoteApi;

  IndexedEntityStore&amp;lt;Event, int&amp;gt; store;

  // The list of events in a category is handled ephemerally in this case and not persisted in the database
  // For simplicity&apos;s sake we&apos;re using a `Future` here (and thus likely a `FutureBuilder` in the `Widget`)
  Future&amp;lt;List&amp;lt;EventsSummary&amp;gt;&amp;gt; getEventsInCategory(int categoryId) {
    return remoteApi.getEvents(categoryId);
  }

  // Returns a &quot;view&quot; onto an event detail (containing more information than just the summaries above)
  QueryResult&amp;lt;EventDetail?&amp;gt; getEventDetails(int id) {
    final event = store.get(id);

    if (event.value == null) {
      // event is not yet loaded into the store, so we need to fetch it
      remoteApi.getEvent(id).then((event) =&amp;gt; store.insert(event));
    }

    return event;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The simple method signature of &lt;code&gt;getEventDetails&lt;/code&gt; hides one important fact though: While we can distinguish between &quot;loading&quot; and &quot;loaded&quot; (&lt;code&gt;null&lt;/code&gt; vs. an non-&lt;code&gt;null&lt;/code&gt;), the caller will not get notified if the remote loading fails.&lt;br /&gt;
To expose this further information we could change the signature to &lt;code&gt;DisposableValueListenable&amp;lt;AsyncValue&amp;lt;EventDetail&amp;gt;&amp;gt;&lt;/code&gt;, but merging the local state with the latest API result is a little bit more involved and thus not part of this introduction. But a &lt;a href=&quot;https://github.com/LunaONE/indexed_entity_store/blob/058564857d87478e7eac3f5ebf0a05fd6a15f607/example/lib/src/examples/async_value_group_and_detail.dart#L169&quot;&gt;full example showing that approach is available here&lt;/a&gt;. Once this is abstracted and a common pattern in the repository implementations, this could likely become just second nature though.&lt;/p&gt;
&lt;h2&gt;On-demand data (alternative)&lt;/h2&gt;
&lt;p&gt;For the practically asynchronous data on-demand case as in &lt;code&gt;getEventDetails&lt;/code&gt; above, a nicer signature might be &lt;code&gt;FutureOr&amp;lt;DisposableValueListenable&amp;lt;EventDetail&amp;gt;&amp;gt;&lt;/code&gt;, as that clearly distinguished between &quot;has the data been loaded successfully&quot; and &quot;here is a view to the latest local data&quot; (non-&lt;code&gt;null&lt;/code&gt; even, as we then expect it to stay available).&lt;/p&gt;
&lt;p&gt;This could be implemented like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import &apos;package:value_listenable_extensions/value_listenable_extensions.dart&apos;;

class EventRepository {
  …

  Future&amp;lt;DisposableValueListenable&amp;lt;EventDetail&amp;gt;&amp;gt; getEventDetails(int id) async {
    final event = store.get(id);

    if (event.value == null) {
      try {
        final remoteEvent = await remoteApi.getEvent(id);

        store.insert(remoteEvent);
      } catch (e) {
        event.dispose(); // failed to load the data, close view to database

        rethrow;
      }
    }

    // If we reached this, we now know that we have a value in the local database, and we don&apos;t expect it to ever be deleted in this case, and thus can &quot;force unwrap&quot; it.
    return event.transform((e) =&amp;gt; e!);
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To me this signature looks better, but we have to be careful when using it. It&apos;s important to always &lt;code&gt;dispose&lt;/code&gt; the query result view (which is now wrapped inside a &lt;code&gt;Future&lt;/code&gt;), so we&apos;ll have to keep that in mind. Especially since the &lt;code&gt;Widget&lt;/code&gt; using it could already be dismissed before the &lt;code&gt;Future&lt;/code&gt; resolved (e.g. when the data loading was so slow that the user went back), in which case we still have to clean up the query result should it become available.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class _EventDetailState extends State&amp;lt;EventDetail&amp;gt; {
  late final event = widget.repository.getEventDetails(widget.eventId);

  @override
  Widget build(BuildContext context) {
   return FutureBuilder(
      future: event,
      builder: (context, data) {
        if (!data.hasData) {
          return const CupertinoActivityIndicator();
        }

        return ValueListenableBuilder(
          valueListenable: event.requireData,
          builder: (context, event, _) {
          return EventTitle(event: event);
          },
        );
      },
    );
  }


  @override
  void dispose() {
    // Imporant to cancel the underlying value listenable here when it has finished loading, even if that may happen after the widget is already disposed.
    event.then((eventResult) =&amp;gt; eventResult.dispose());

    super.dispose();
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If Dart had something like &lt;a href=&quot;https://docs.swift.org/swift-book/documentation/the-swift-programming-language/concurrency/#Task-Cancellation&quot;&gt;Swift&apos;s structured concurrency&lt;/a&gt; we might be able to cancel the work &quot;inside&quot; the &lt;code&gt;Future&lt;/code&gt; in a more straightforward way, but while that is not the case an approach like the one shown above must be taken.&lt;/p&gt;
&lt;p&gt;Both usages inside &lt;code&gt;build&lt;/code&gt; and &lt;code&gt;dispose&lt;/code&gt; can be greatly simplified though by the use of some helpers. We can easily imagine a &lt;code&gt;FutureValueListenableBuilder&lt;/code&gt; that handles both the unwrapping of the future and listening to the changes inside it, as well as an extension method on &lt;code&gt;Future&amp;lt;DisposableValueListenable&amp;lt;T&amp;gt;&amp;gt;&lt;/code&gt; which would make the clean up shorter.&lt;/p&gt;
</content:encoded></item><item><title>Receiving File Drops on macOS (and iOS) with SwiftUI</title><link>https://timm.preetz.xyz/p/file-drops-on-macos-and-ios-with-swiftui</link><guid isPermaLink="true">https://timm.preetz.xyz/p/file-drops-on-macos-and-ios-with-swiftui</guid><pubDate>Sat, 09 Jan 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&amp;lt;div class=&quot;note&quot;&amp;gt;A complete example of the code to be used on iOS and macOS is available &amp;lt;a href=&quot;https://github.com/tp/demo-FileDropTests&quot;&amp;gt;on GitHub here&amp;lt;/a&amp;gt;.&amp;lt;/div&amp;gt;&lt;/p&gt;
&lt;h2&gt;Starting Point&lt;/h2&gt;
&lt;p&gt;&amp;lt;figure&amp;gt;
&amp;lt;img src=&quot;/assets/posts/file-drops-on-macos-and-ios-with-swiftui/ios_after_drop.png&quot;&amp;gt;
&amp;lt;figcaption&amp;gt;Example of the drop behaviour on iOS/iPadOS&amp;lt;/figcaption&amp;gt;
&amp;lt;/figure&amp;gt;&lt;/p&gt;
&lt;p&gt;While porting a pure &lt;code&gt;SwiftUI&lt;/code&gt; app, I noticed that the &lt;code&gt;onDrop&lt;/code&gt; file import handler used for the iOS app does not work as expected on macOS:&lt;/p&gt;
&lt;p&gt;&amp;lt;figure&amp;gt;
&amp;lt;img src=&quot;/assets/posts/file-drops-on-macos-and-ios-with-swiftui/mac_using_ios_implementation_file_url.png&quot;&amp;gt;
&amp;lt;figcaption&amp;gt;macOS app receiving a URL with a different path &amp;amp; content than the dragged file&amp;lt;/figcaption&amp;gt;
&amp;lt;/figure&amp;gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;providers.first!.loadFileRepresentation(forTypeIdentifier: UTType.item.identifier) {
  url, _ in
    message = describeDroppedURL(url!)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;At first I thought it was just an issue with file names being erased / hidden, e.g. &lt;code&gt;.com.apple.Foundation.NSItemProvider.MpBDqm.tmp&lt;/code&gt; instead of &lt;code&gt;notes.txt&lt;/code&gt;, but upon closer inspection the file contents were also different. Instead of the expected data, the file read from the initial URL contained another URL in the form of &lt;code&gt;file:///.file/id=6571367.2773272/&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Adaptation for macOS&lt;/h2&gt;
&lt;p&gt;Eventually I came to find out that these are known as &lt;a href=&quot;https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/AccessingFilesandDirectories/AccessingFilesandDirectories.html#//apple_ref/doc/uid/TP40010672-CH3-SW6&quot;&gt;&lt;code&gt;File reference URL&lt;/code&gt;s&lt;/a&gt;, and &lt;a href=&quot;https://christiantietze.de/posts/2018/09/nsurl-filereferenceurl-swift/&quot;&gt;this post&lt;/a&gt; offered a good reference on how they had to be handled historically (with &lt;code&gt;NSURL&lt;/code&gt;), and that they should work out of the box with Swift&apos;s &lt;code&gt;URL&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In order to avoid having the system to create temporary files which then need to be read &amp;amp; referenced to get to the final file, I switched the macOS implementation to read the dropped file URL from the &lt;code&gt;NSPasteboard&lt;/code&gt; item itself:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;providers.first!.loadObject(ofClass: NSPasteboard.PasteboardType.self) {
  pasteboardItem, _ in
    message = describeDroppedURL(URL(string: pasteboardItem!.rawValue)!)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;lt;figure&amp;gt;
&amp;lt;img src=&quot;/assets/posts/file-drops-on-macos-and-ios-with-swiftui/mac_with_nspasteboard.png&quot;&amp;gt;
&amp;lt;figcaption&amp;gt;macOS app after the updated: Being able to read the correct file name and contents&amp;lt;/figcaption&amp;gt;
&amp;lt;/figure&amp;gt;&lt;/p&gt;
&lt;h2&gt;Bonus&lt;/h2&gt;
&lt;p&gt;One last finding I made during testing was that the dropped data was different from whether the item was dragged from within the Finder&apos;s tree view compared to when it was dragged from the title bar 🤔&lt;/p&gt;
&lt;p&gt;&amp;lt;video src=&quot;/assets/posts/file-drops-on-macos-and-ios-with-swiftui/finder_drop_test.mov&quot; autoplay=&quot;false&quot;&amp;gt;&lt;/p&gt;
&lt;p&gt;Luckily the final implementation works just fine with either of these 🤗&lt;/p&gt;
</content:encoded></item><item><title>`usePromise`: A React hook for async data loading with server-side rendering (SSR) support</title><link>https://timm.preetz.xyz/p/usepromise-react-hook-for-async-operations</link><guid isPermaLink="true">https://timm.preetz.xyz/p/usepromise-react-hook-for-async-operations</guid><pubDate>Sun, 29 Sep 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&amp;lt;div class=&quot;note&quot;&amp;gt;&amp;lt;b&amp;gt;Out now:&amp;lt;/b&amp;gt; This post explores the background behind a new library, usePromise, that is now &amp;lt;a href=&quot;https://www.npmjs.com/package/@timm/use-promise&quot;&amp;gt;available on NPM&amp;lt;/a&amp;gt;. The source code and examples are available on &amp;lt;a href=&quot;https://github.com/tp/use-promise&quot;&amp;gt;GitHub at tp/use-promise&amp;lt;/a&amp;gt;.&amp;lt;/div&amp;gt;&lt;/p&gt;
&lt;p&gt;React hooks can help build components made up of re-usable smaller helpers while still staying readable and clear even when a bunch of features are combined. This is a nice contrast to the previous lifecycle methods across in which multiple &quot;extensions&quot; wheren&apos;t always clearly visible - might it be because they only appeared in some methods, or because they appeared in a different order in each one and hence weren&apos;t as easily scannable.&lt;/p&gt;
&lt;p&gt;So when looking at a component design that would allow for 100% custom components to be injected into an app skeleton, fetching data via hooks seemed like a great solution. In contrast to render props and similar approaches, it doesn&apos;t limit the consumer to what is provided by the outside helper in one pattern, and then force one to use a possibly different approach to load further data. (Or use nested render props components, which IMHO don&apos;t read that well and still require manual passing of the props.)&lt;/p&gt;
&lt;p&gt;So I was a little surprised to find out that as of now (React 16.8) one couldn&apos;t easily compose a new hook for async data loading (with SSR support) for 2 reasons:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;State managed using the &lt;code&gt;setState&lt;/code&gt; hook couldn&apos;t be read out and be transferred to the client&lt;/li&gt;
&lt;li&gt;Loading data asynchronously, and hence calling &lt;code&gt;setState&lt;/code&gt; after the initial render on the server, doesn&apos;t work with the current default model, which only renders once.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Point #2 seems like a reasonable general limitation, because when you trigger the data loading in the component to be rendered, one for sure needs to attempt to render that component again after the data has been loaded. Rendering &lt;code&gt;n + 1&lt;/code&gt; times (&lt;em&gt;n&lt;/em&gt; for each data loading operation and then once for the final render to find out that there is nothing new to fetch) is an overhead not to take lightly, but &lt;a href=&quot;https://reactjs.org/blog/2019/08/08/react-v16.9.0.html#an-update-to-the-roadmap&quot;&gt;luckily React is working on a remedy to make this more lightweight with &lt;code&gt;Suspense&lt;/code&gt; in the future&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So while waiting on React to support #2 by default and at the same time adding a solution for #1 for the specific context of data-loading which does not require learning and setting up any state-management solution, I looked into building a small hook that would accomplish this.&lt;/p&gt;
&lt;p&gt;The challenge, as mentioned before, is that any component in the tree could trigger a data-fetching operation, and then rendering would need to halt until that &lt;code&gt;Promise&lt;/code&gt; is resolved. In lieu of &lt;code&gt;Suspense&lt;/code&gt; the best I could come up with was to use the approach of rendering the whole tree again (something I also observed Apollo do) after each individual data loading operation has completed. Taking another page from the current &lt;code&gt;Suspense&lt;/code&gt; playbook, whenever a component wants to load data via this new hook, it &lt;code&gt;throw&lt;/code&gt;s that &lt;code&gt;Promise&lt;/code&gt;, which the library then &lt;code&gt;await&lt;/code&gt;s before attempting to render again. Once a render completed without any new &lt;code&gt;Promise&lt;/code&gt; being scheduled (&lt;code&gt;throw&lt;/code&gt;n), that rendering is taken as the final result and sent to the client.&lt;/p&gt;
&lt;p&gt;In standard hooks fashion the library builds up an array holding the data of the single ongoing and potentially many completed &lt;code&gt;Promise&lt;/code&gt;s. This data is then distributed on each rendering attempt to the hooks in order. Since this is only needed on the server (in an unchanging render tree) and then once for rehydration on the client, there is no issue with using this one global array (scoped to the current request) for the whole page (instead of a per component array which React itself uses).&lt;/p&gt;
&lt;p&gt;The final data of all Promises is then serialized into the HTML send to the client, where it&apos;s used for the initial rehydration, after which it switches to rely on React&apos;s &lt;code&gt;setState&lt;/code&gt; for managing further mutations.&lt;/p&gt;
&lt;p&gt;In then end the usage looks like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function WhatToWear() {
    const {loading, error, data} = usePromise(() =&amp;gt; weatherApi.getCurrentWeatherAsync());

    if (loading) {
        return &amp;lt;div&amp;gt;Loading…&amp;lt;/div&amp;gt;
    }

    if (error) {
        return &amp;lt;div&amp;gt;An error occured…&amp;lt;/div&amp;gt;
    }

    return &amp;lt;div&amp;gt;Recommended outfit: {weather.temp &amp;gt; 19 ? &apos;👚&apos; : &apos;🧥&apos;}&amp;lt;/div&amp;gt;;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The plan is now to take the &lt;code&gt;usePromise&lt;/code&gt; helper and build up hooks for the specific domain, so the consumer wouldn&apos;t have to deal with providing the &lt;code&gt;Promise&lt;/code&gt; creating function herself.&lt;/p&gt;
&lt;p&gt;In the end the resulting API is really small, just one line to pull in a some fully typed data and have the library taking care of data loading on the server. Additionally the consumer now has to take care of rendering the &lt;code&gt;loading&lt;/code&gt; and &lt;code&gt;error&lt;/code&gt; cases, but that would be something they will have to deal with in any case, unless they&apos;re fine with rendering some default message, which could easily be achieved with a helper component.&lt;/p&gt;
&lt;p&gt;Overall I am quite happy how this turned out on the usage side, even though the implementation has some rough edges and overhead at the moment. Possibly the overhead can be reduced in the future with &lt;code&gt;Suspense&lt;/code&gt; – if this library will not be made obsolete outright by it. In either case, the transition to some future React version should be smooth, very likely allowing us to keep the same outside API.&lt;/p&gt;
&lt;p&gt;For now this is exactly what was needed and building up on so much great technology and inspiration I was happy to see how it could be achieved in a short amount of time.&lt;/p&gt;
&lt;h2&gt;Thoughts on API design&lt;/h2&gt;
&lt;p&gt;Initially the library followed the &lt;code&gt;useState&lt;/code&gt; approach and returned an array of type &lt;code&gt;[boolean, T, unknown]&lt;/code&gt;, which could be used for example as &lt;code&gt;[completed, weather, error]&lt;/code&gt; (in the example case of fetching the current weather). The interesting bit here is how the array model doesn&apos;t even suggest default names, and the user is forced to pick some for his use-case. But just having the types might be confusing in 2 cases: When not using / seeing the types immediately in the editor, or when the return type is &lt;code&gt;boolean&lt;/code&gt; or anything unspecific like the &lt;code&gt;unkown&lt;/code&gt; error type. In those cases it might not be obvious at which index the result is stored, especially if the library is not very familiar to the user (unlike &lt;code&gt;setState&lt;/code&gt; which one probably interacts with daily in a hooks-using codebase).&lt;/p&gt;
&lt;p&gt;The array approach was then debated, and since the primary use case was data loading, the API was changed to match Apollo&apos;s &lt;code&gt;useQuery&lt;/code&gt; (&lt;a href=&quot;https://github.com/tp/use-promise/blob/b0dab8d5dfce28d45a6667a180e15f0fa92c1d7b/src/index.ts#L4&quot;&gt;the actual types are more specific&lt;/a&gt; than the example below):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  loading: boolean;
  data: T;
  error: Error;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, it&apos;s now an object which provides explicit names for each field. &lt;code&gt;completed&lt;/code&gt; flipped to &lt;code&gt;loading&lt;/code&gt;, which makes writing early returns much nicer. &lt;code&gt;error&lt;/code&gt; is now limited to &lt;code&gt;Error&lt;/code&gt;, but that might just be a temporary solution. What I wanted to achieve there was that &lt;code&gt;error&lt;/code&gt; could be checked with a simple &lt;code&gt;if&lt;/code&gt;, and if it was falsy the &lt;code&gt;Promise&lt;/code&gt; would have resolved successfully and &lt;code&gt;data&lt;/code&gt; would contain the result.&lt;/p&gt;
&lt;p&gt;Remapping the names to something specific is still easily possibly.&lt;/p&gt;
&lt;p&gt;One further consideration was how use the hook multiple times in a row. Then having multiple &lt;code&gt;loading&lt;/code&gt; and &lt;code&gt;error&lt;/code&gt; states might get very cumbersome, especially since you musn&apos;t return early for any &lt;code&gt;Promise&lt;/code&gt; rejection.&lt;/p&gt;
&lt;p&gt;In the end the current design and documentation hopefully leads people to write a single helper function loading all relevant data for a component. This is a lot more efficient with the current implmentation detailed above, as well as making the component clearer as it has less states to think about.&lt;/p&gt;
&lt;p&gt;If you have any feedback on the API design, for example feeling it&apos;s now to focused on data loading, or any other suggestions &lt;a href=&quot;https://github.com/tp/use-promise/issues&quot;&gt;feel free to open a ticket with your feedback&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Closing Thoughts&lt;/h2&gt;
&lt;p&gt;One thought that always pops up in my head when working on components which trigger or manage their own data loading – especially whenn this done across multiple layers of components – is whether it&apos;s desirable and should be done that way at all.&lt;/p&gt;
&lt;p&gt;I think it&apos;s always worth to imagine what the alternative design of having a storage &amp;amp; side-effect solution outside of the component tree would look like and what benefits one might gain from it. Compared to the above example, one clear benefit would be that one could do the data loading first, and then be done after a single render. On the other hand that forces one to combine all data-fetching logic into a single step on this &quot;other side&quot; – which might or might not be a good thing.&lt;/p&gt;
&lt;p&gt;In the end this boils down to picking what&apos;s right for the problem at hand. In the above case the goal was to make it easy to insert 1 or 2 data loading hooks across a page, and for that it seems far more approachable than learning any specific store system and hooking into it.&lt;/p&gt;
&lt;p&gt;&amp;lt;div class=&quot;alert&quot;&amp;gt;👨🏼‍💻If you strive to make life developing web applications easier and enjoy exploring beyond the known solutions &amp;lt;a href=&quot;https://corporate.aboutyou.de/de/jobs/senior-frontend-developer&quot;&amp;gt;this might job might fancy your interest&amp;lt;/a&amp;gt;.&amp;lt;/div&amp;gt;&lt;/p&gt;
</content:encoded></item><item><title>Rendering a combined list view from multiple list using Flutter&apos;s `SliverList`s</title><link>https://timm.preetz.xyz/p/flutter-sliver-list-view</link><guid isPermaLink="true">https://timm.preetz.xyz/p/flutter-sliver-list-view</guid><pubDate>Fri, 20 Sep 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;The &lt;a href=&quot;/p/nested-listviews-in-flutter&quot;&gt;previous post&lt;/a&gt; showed how to flatten grouped data with a header above the items so it can be rendered in a single &lt;a href=&quot;https://api.flutter.dev/flutter/widgets/ListView-class.html&quot;&gt;&lt;code&gt;ListView&lt;/code&gt;&lt;/a&gt; widget. Now I want to look at a diffent use-case: Rendering lists from distinct data sources after each other. This implementation will use a &lt;a href=&quot;https://api.flutter.dev/flutter/widgets/CustomScrollView-class.html&quot;&gt;&lt;code&gt;CustomScrollView&lt;/code&gt;&lt;/a&gt; and &lt;a href=&quot;https://api.flutter.dev/flutter/widgets/SliverList-class.html&quot;&gt;&lt;code&gt;SliverList&lt;/code&gt;s&lt;/a&gt;. If you&apos;re unfamiliar with slivers, I would recommend reading &lt;a href=&quot;https://medium.com/flutter/slivers-demystified-6ff68ab0296f&quot;&gt;Slivers, Demystified&lt;/a&gt; first, as the below example will just focus on this one narrow use-case, while the overall setup supports much more.&lt;/p&gt;
&lt;h2&gt;The Example&lt;/h2&gt;
&lt;p&gt;For this demo I want to render a single list showing the user&apos;s favorite items, then some static content, and below that recommendations of similiar things. Since this simple example only has 3 row types, we could implement it using the &lt;code&gt;ListView&lt;/code&gt; approach shown before. But as the row types are never mixed together and since in this example there are only 3 sections (favorites list, static content, recommendations list) I think it&apos;s a good case to create a widget for each section of the scroll view and then combine those into one scrollable list using &lt;code&gt;CustomScrollView&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/assets/posts/flutter-sliver-list-view/sliverlists.gif&quot; alt=&quot;Example scroll view showing a list made up from 3 different sources&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;div class=&quot;note&quot;&amp;gt;The demo app and code for is available on &amp;lt;a href=&quot;https://github.com/tp/nested_listviews&quot;&amp;gt;GitHub at tp/nested_listviews&amp;lt;/a&amp;gt;.&amp;lt;/div&amp;gt;&lt;/p&gt;
&lt;p&gt;On the top-level, the widget that sets up the list as a &lt;code&gt;CustomScrollView&lt;/code&gt; is nicely readable and gives a nice overview of what will be shown in it:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Widget build(BuildContext context) {
  return CustomScrollView(
    slivers: &amp;lt;Widget&amp;gt;[
      Favorites(),
      Static(),
      Recommendations(),
    ],
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now onto each sliver itself:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Favorites&lt;/code&gt; renders a &lt;code&gt;SliverList&lt;/code&gt; with a &lt;code&gt;SliverChildBuilderDelegate&lt;/code&gt;; so it could handle a large amount of items&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Static&lt;/code&gt; uses a &lt;code&gt;SliverChildListDelegate&lt;/code&gt; in its &lt;code&gt;SliverList&lt;/code&gt; as it renders just one very simple widget&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Recommendations&lt;/code&gt; uses the same approach a &lt;code&gt;Favorites&lt;/code&gt;, just with a different widget for its rows&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So the &lt;code&gt;Favorites&lt;/code&gt; and &lt;code&gt;Recommendation&lt;/code&gt; builder methods look both roughly like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Widget build(BuildContext context) {
  return SliverList(
    delegate: SliverChildBuilderDelegate(
      (context, index) {
        return XyzRow(data: index); // might be `data[index]` in practice
      },
      childCount: 100, // might be `data.length` in practice
    ),
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Overall &lt;a href=&quot;https://github.com/tp/nested_listviews/blob/8220c3d768a094a85ed5cef7834137a010b02114/lib/slivers/list_from_slivers.dart&quot;&gt;the whole source code for this example&lt;/a&gt; looks to me a lot simpler than what we had in the previous case even though it seems like a more niche use case than rendering a grouped list. I think that stems from the fact that this &quot;lists below each other&quot; is nicely supported by the framework, while the grouped display was not.&lt;/p&gt;
&lt;p&gt;In a real app one might need to combine the 2 approaches: Render a grouped list view from a flattened list with a &lt;code&gt;SliverChildBuilderDelegate&lt;/code&gt; inside a &lt;code&gt;CustomScrollView&lt;/code&gt; which also contains other lists. That is left as an exercise to the interested reader though 😉&lt;/p&gt;
&lt;p&gt;&amp;lt;div class=&quot;alert&quot;&amp;gt;👨🏾‍💻 If you love working with Flutter and like to dig deep to find the best approach to each problem, &amp;lt;a href=&quot;https://corporate.aboutyou.de/de/jobs/dart-developer-shop-applications&quot;&amp;gt;we might just have the perfect job for you&amp;lt;/a&amp;gt;.&amp;lt;/div&amp;gt;&lt;/p&gt;
</content:encoded></item><item><title>Nested `ListView`s in Flutter</title><link>https://timm.preetz.xyz/p/nested-listviews-in-flutter</link><guid isPermaLink="true">https://timm.preetz.xyz/p/nested-listviews-in-flutter</guid><pubDate>Wed, 18 Sep 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;If you&apos;ve ever tried rendering a simple &lt;code&gt;ListView&lt;/code&gt; inside the &lt;code&gt;itemBuilder&lt;/code&gt; method of another &lt;code&gt;ListView&lt;/code&gt; you&apos;ll most certainly have encountered the &lt;em&gt;Vertical viewport was given unbounded height.&lt;/em&gt; exception.&lt;/p&gt;
&lt;p&gt;The simple fix (which ranks up top on Google) is to add the &lt;code&gt;shrinkWrap: true&lt;/code&gt; property to the inner &lt;code&gt;ListView&lt;/code&gt;s. Once that is changed the initial screen renders fine, until you try to scroll the overall list, which is not possible because any drag actions on top of the inner &lt;code&gt;ListView&lt;/code&gt;s just scrolls them (even though they might be &quot;fully&quot; rendered). The fix for that issue is then to add &lt;code&gt;physics: ClampingScrollPhysics()&lt;/code&gt; to the innner &lt;code&gt;ListView&lt;/code&gt;s.&lt;/p&gt;
&lt;p&gt;With those 2 lines added to the inner &lt;code&gt;ListView&lt;/code&gt; the initial issue is solved and one might consider it done. I would like to disagree and suggest some alternatives. In this I&apos;ll article explain why there is no need to nest &lt;code&gt;ListView&lt;/code&gt;s in the first place, how nesting them can be misleading about their performance characteristics (which are bad in practice), and how &lt;code&gt;SliverList&lt;/code&gt; is a better approach should you ever have the need to render multiple list below one another.&lt;/p&gt;
&lt;p&gt;&amp;lt;div class=&quot;note&quot;&amp;gt;The demo app and code for each approach is available on &amp;lt;a href=&quot;https://github.com/tp/nested_listviews&quot;&amp;gt;GitHub at tp/nested_listviews&amp;lt;/a&amp;gt;.&amp;lt;/div&amp;gt;&lt;/p&gt;
&lt;h2&gt;Performance characteristics of nested &lt;code&gt;ListView&lt;/code&gt;s&lt;/h2&gt;
&lt;p&gt;All of the nested &lt;code&gt;ListView&lt;/code&gt; code I have seen in the wild recently used the seemingly performant &lt;a href=&quot;https://api.flutter.dev/flutter/widgets/ListView/ListView.builder.html&quot;&gt;&lt;code&gt;ListView.builder&lt;/code&gt; constructor&lt;/a&gt; for the outer and inner &lt;code&gt;ListView&lt;/code&gt;s. So it seems like developers are aware that it exists and should be used, and the documentation clearly states the advantages of it:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This constructor is appropriate for list views with a large (or infinite) number of children because the builder is called only for those children that are actually visible.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Unfortunately though, that is not true anymore for the inner &lt;code&gt;ListView&lt;/code&gt;s. Because the outer view needs to know how tall the inner &lt;code&gt;ListView&lt;/code&gt;s are, the inner ones will get rendered in full until the height is filled. But at the very least the first list view will get rendered in full, which is already bad should that contain many items. This behavior can easily be verified by putting a &lt;code&gt;print&lt;/code&gt; in the &lt;code&gt;itemBuilder&lt;/code&gt; of the inner &lt;code&gt;ListView&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/assets/posts/nested-listviews-in-flutter/flutter_listviews_inner_fully_rendered.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;As you can see in the example above, the 1000 items for the first inner &lt;code&gt;ListView&lt;/code&gt; were build, even though only 50 are visible on the screen.&lt;/p&gt;
&lt;p&gt;Whether or not this is an issue in your application depends on the maximum amount of items in the inner &lt;code&gt;ListView&lt;/code&gt;s. Just from reading the code one might think though that it behaves efficiently – meaning it really only renders visible items – which it does not. Hence I would find it more &lt;em&gt;honest&lt;/em&gt; to use a &lt;code&gt;Column&lt;/code&gt; and plainly map the items to widgets. Also in the general case that reads nicer than retrieving the item by index from the underlying storage as has to be done with the &lt;code&gt;itemBuilder&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// [... wrapping ListView.builder omitted]
return Column(
  children: &amp;lt;Widget&amp;gt;[
    ...List.generate(
      1000,
      (innerIndex) {
        return Text(&apos;Outer = $outerIndex, Inner = $innerIndex&apos;);
      },
    ),
  ],
);
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;The flattened list approach&lt;/h2&gt;
&lt;p&gt;So far we&apos;ve only seen how a nested &lt;code&gt;ListView&lt;/code&gt; is as much work to render as a &lt;code&gt;Column&lt;/code&gt; or a similar widget. One approach I would like to suggest, for most cases, is to &lt;em&gt;unnest&lt;/em&gt; the rendering and make do with a single list view. This can be achieved in a variety of ways, but the simple approach of flattening the data structure into a single array should work up to a huge number of items. Just make sure not to compute that flattened array in the &lt;code&gt;builder&lt;/code&gt; method, but rather once initially and on updates and keep it stored in some state.&lt;/p&gt;
&lt;p&gt;Suppose we&apos;d wanted to build a todo app. Let&apos;s assume our API returns us a list of sorted groups (for example by day) in some kind of &lt;code&gt;Section&lt;/code&gt; type:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@immutable
class Section {
    Section(this.title, this.items);

    final String title;

    final List&amp;lt;String&amp;gt; items;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now instead of rendering the outer &lt;code&gt;ListView&lt;/code&gt; with the &lt;code&gt;Section&lt;/code&gt;s as items and then an inner &lt;code&gt;ListView&lt;/code&gt; for each section, we can flatten the &lt;code&gt;Section&lt;/code&gt;s into a list of &lt;code&gt;Row&lt;/code&gt;s (a new type we define for this case).&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@immutable
abstract class Row {} // approximation of a union type in Dart

class HeaderRow implements Row {
  HeaderRow(this.title);

  final String title;
}

class ItemRow implements Row {
  ItemRow(this.description);

  final String description;
}


// tasksByDay is a List&amp;lt;Section&amp;gt;
final items = tasksByDay.expand&amp;lt;Row&amp;gt;((section) {
  return [
    HeaderRow(section.title),
    ...section.items.map((item) =&amp;gt; ItemRow(item)),
  ];
}).toList();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And then that &lt;code&gt;items&lt;/code&gt; list can be rendered with a single &lt;code&gt;ListView&lt;/code&gt; which renders a specific widget dependening on each item&apos;s type:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ListView.builder(
  itemBuilder: (context, index) {
    final item = items[index];

    if (item is HeaderRow) {
      return Text(item.title,
          style: TextStyle(fontWeight: FontWeight.bold));
    }

    if (item is ItemRow) {
      return Text(item.description);
    }
  },
  itemCount: items.length,
);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With this approach a little upfront work is required, but then only the rows visbile on screen (+ some small amount of extra rows rendered by the framework) are built:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/assets/posts/nested-listviews-in-flutter/flattened_list.png&quot; alt=&quot;The flattened list builds only the minimum amount of items&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;&lt;code&gt;SliverList&lt;/code&gt;s inside a &lt;code&gt;CustomScrollView&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;The above approach of flattening the list is in my opinion a good approach to render such a grouped list view, but it&apos;s only suitable for lists that have few row types. Should you ever have the need to render lists from different domains in a single list after another, then a &lt;code&gt;CustomScrollView&lt;/code&gt; with &lt;code&gt;SliverList&lt;/code&gt;s for each specific type of list seem like a better approach in my opinion. I&apos;ll write up an explanation and code example on those in a follow up post.&lt;/p&gt;
&lt;h2&gt;Recap&lt;/h2&gt;
&lt;p&gt;I hope I was able to show how nesting &lt;code&gt;ListView&lt;/code&gt;s inside one another might not be a good idea for the problem at hand, and what other implementations are available. You can either use a &lt;code&gt;Column&lt;/code&gt; or any other &quot;simple&quot; widget for the inner lists, or flatten the whole list for rendering and by through that achieve the &lt;code&gt;ListView.builder&lt;/code&gt;&apos;s promise of only rendering items which are visible on screen.&lt;/p&gt;
&lt;p&gt;&amp;lt;div class=&quot;alert&quot;&amp;gt;👩‍💻 If you love working with Flutter and enjoy sweating the details, &amp;lt;a href=&quot;https://corporate.aboutyou.de/de/jobs/dart-developer-shop-applications&quot;&amp;gt;we might just have the perfect job for you&amp;lt;/a&amp;gt;.&amp;lt;/div&amp;gt;&lt;/p&gt;
</content:encoded></item><item><title>Making HTTP Requests in Flutter Tests</title><link>https://timm.preetz.xyz/p/http-request-flutter-test</link><guid isPermaLink="true">https://timm.preetz.xyz/p/http-request-flutter-test</guid><pubDate>Fri, 03 May 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;By default all HTTP request made in a test invoked with &lt;code&gt;flutter test&lt;/code&gt; &lt;a href=&quot;https://github.com/flutter/flutter/blob/63aa5b3647dbd912a02f7545fc0101003cb3adc4/packages/flutter_test/lib/src/binding.dart#L1570&quot;&gt;result in an empty response with status code 400&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Generally that seems like a good default behavior to avoid external dependencies and hence reduce flakyness in tests. But what if you really want to make HTTP requests in your tests?&lt;/p&gt;
&lt;p&gt;&amp;lt;div class=&quot;note&quot;&amp;gt;HTTP requests are disabled for a good reason. Before enabling them, think about whether you have an even better reason to revert that behavior.&amp;lt;/div&amp;gt;&lt;/p&gt;
&lt;p&gt;Since making outgoing requests in tests is discouraged, the usual advice is to use a mock client (for example &lt;a href=&quot;https://pub.dartlang.org/documentation/http/latest/testing/MockClient-class.html&quot;&gt;&lt;code&gt;MockClient&lt;/code&gt;&lt;/a&gt; from the &lt;code&gt;http&lt;/code&gt; package).&lt;/p&gt;
&lt;p&gt;But how does one then efficiently and correctly create mock responses and assertions for incoming requests? For that we&apos;ve written a request/response recording HTTP client.&lt;/p&gt;
&lt;p&gt;Tests get run once with recording enabled, which writes the requests and responses as JSON files to disk. On subsequent runs the recording can then be disabled and all requests will be served form those files.&lt;/p&gt;
&lt;p&gt;So that&apos;s why we needed to enable HTTP requests during tests in this specific case. How does one go about enabling them?&lt;/p&gt;
&lt;p&gt;Turns out there is a discussion about this exact behavior on &lt;a href=&quot;https://github.com/flutter/flutter/issues/19588#issuecomment-406771070&quot;&gt;Flutter&apos;s GitHub Issues&lt;/a&gt; which I was lucky to find after some searching. The simplified version of that solution, shown here as part of a test, is this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import &apos;dart:io&apos;;
import &apos;package:http/http.dart&apos; as http;
// [...] other testing imports

Future&amp;lt;void&amp;gt; main() async {
  HttpOverrides.global = _MyHttpOverrides(); // Setting a customer override that&apos;ll use an unmocked HTTP client

  testWidgets(
    &apos;Test with HTTP enabled&apos;,
    (tester) async {
      await tester.runAsync(() async { // Use `runAsync` to make real asynchronous calls
        expect(
          (await http.Client().get(&apos;https://www.google.com/&apos;)).statusCode,
          200,
        );
      });
    },
  );
}

class _MyHttpOverrides extends HttpOverrides {}
&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>Page Generator TypeScript Rewrite</title><link>https://timm.preetz.xyz/p/page-generator-typescript-rewrite</link><guid isPermaLink="true">https://timm.preetz.xyz/p/page-generator-typescript-rewrite</guid><pubDate>Sun, 06 Jan 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;After switching away from Jekyll (since I have no familiarity with Ruby and was running into limitations of how to structure this site), I wrote my custom static page generator in Swift. I choose Swift because I had been meaning to explore the language, but had no Apple-platform project on the horizon and thought it might be as good as any language to convert Markdown and write some static files.&lt;/p&gt;
&lt;p&gt;But after the initial creation I never touched it much. Development always felt a little heavy and slow and I wasn&apos;t content with the libraries and approach I picked.&lt;/p&gt;
&lt;p&gt;So this weekend I took the to rewriting the page generation to TypeScript. Since it&apos;s currently my main development environment, it was quick to get the basics up and running. For now it&apos;s just a static site generation, with no client side rendering.&lt;br /&gt;
Though I&apos;d love to add that in the future to have a personal project with SSR + CSR to better explore different approaches here.&lt;/p&gt;
&lt;p&gt;I was delighted how for every problem I had (React instead of templating, Markdown, code syntax highlighting, file access) there were already solid libraries to choose from. Some I&apos;d liked to be a little different, but overall this toolset is extremely practical.&lt;/p&gt;
&lt;p&gt;In the end the whole code base is just 515 lines (in its first draft, without any code-level compression applied) and contains all the flexibility and customization I desire. And I can build and run the application to generate all pages in under a second 😀.&lt;/p&gt;
&lt;p&gt;&amp;lt;div class=&quot;note&quot;&amp;gt;All code is available in &amp;lt;a href=&quot;https://github.com/tp/page/tree/master/src&quot;&amp;gt;this GitHub repository.&amp;lt;/a&amp;gt;&amp;lt;/div&amp;gt;&lt;/p&gt;
</content:encoded></item><item><title>TypeScript: `ReturnType` for `async` `function`s</title><link>https://timm.preetz.xyz/p/typescript-async-function-return-value</link><guid isPermaLink="true">https://timm.preetz.xyz/p/typescript-async-function-return-value</guid><pubDate>Mon, 27 Aug 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Since the introduction of the &lt;code&gt;ReturnType&lt;/code&gt; in &lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html&quot;&gt;TypeScript 2.8&lt;/a&gt;, we can build up types based on the results of functions, without mentioning the types explicitly:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function createContext&amp;lt;T extends () =&amp;gt; any&amp;gt;(
  configProvider: T,
): { config: ReturnType&amp;lt;T&amp;gt; } {
  return {
    config: configProvider(),
  };
}

function apiConfig() {
  return {
    endpoint: &quot;https://www.example.com&quot;,
  };
}

/**
 * context has type `{ config: { endpoint: string; }; }`
 */
const context = createContext(apiConfig);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href=&quot;https://www.typescriptlang.org/play/#src=%0D%0A%0D%0Afunction%20createContext%3CT%20extends%20()%20%3D%3E%20any%3E(configProvider%3A%20T)%3A%20%7B%20config%3A%20ReturnType%3CT%3E%20%7D%20%7B%0D%0A%20%20%20%20return%20%7B%0D%0A%20%20%20%20%20%20%20%20config%3A%20configProvider()%2C%0D%0A%20%20%20%20%7D%0D%0A%7D%0D%0A%0D%0Afunction%20apiConfig()%20%7B%0D%0A%20%20%20%20return%20%7B%0D%0A%20%20%20%20%20%20%20%20endpoint%3A%20&apos;https%3A%2F%2Fwww.example.com&apos;%0D%0A%20%20%20%20%7D%0D%0A%7D%0D%0A%0D%0A%2F**%0D%0A%20*%20context%20has%20type%20%60%7B%20config%3A%20%7B%20endpoint%3A%20string%3B%20%7D%3B%20%7D%60%0D%0A%20*%2F%0D%0Aconst%20context%20%3D%20%20createContext(apiConfig)&quot;&gt;Playground&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now that &lt;code&gt;async&lt;/code&gt; functions are becoming more prevalent in the code I work with, I have been wondering whether a similar helper can be employed to get the type of a successfully resolved &lt;code&gt;Promise&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;As a first building block I wrote a type to extract the &lt;code&gt;Promise&lt;/code&gt;&apos;s resolved type:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type PromiseResolvedType&amp;lt;T&amp;gt; = T extends Promise&amp;lt;infer R&amp;gt; ? R : never;

// Type is currently Promise&amp;lt;number&amp;gt;
const promise = Promise.resolve(3);

// value has type `number`, will stay in sync with type of `promise` variable
let comparisionValue: PromiseResolvedType&amp;lt;typeof promise&amp;gt; = 5;

promise.then((value) =&amp;gt;
  console.log(`Value equal to comparison?`, value === comparisionValue),
);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href=&quot;https://www.typescriptlang.org/play/#src=type%20PromiseResolvedType%3CT%3E%20%3D%20T%20extends%20Promise%3Cinfer%20R%3E%20%3F%20R%20%3A%20never%3B%0D%0A%0D%0A%2F%2F%20Type%20is%20currently%20Promise%3Cnumber%3E%0D%0Aconst%20promise%20%3D%20Promise.resolve(3)%3B%0D%0A%0D%0A%2F%2F%20value%20has%20type%20%60number%60%2C%20will%20stay%20in%20sync%20with%20%60promise%60%20variable%0D%0Alet%20comparisionValue%3A%20PromiseResolvedType%3Ctypeof%20promise%3E%20%3D%205%3B%0D%0A%0D%0Apromise.then(value%20%3D%3E%20console.log(%60Value%20equal%20to%20comparison%3F%60%2C%20value%20%3D%3D%3D%20comparisionValue))%3B&quot;&gt;Playground&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;That works nicely to limit our comparision value to the same type as the &lt;code&gt;Promise&lt;/code&gt; instance might eventually resolve to. That way we can ensure consistency. If the types were not matching, the comparison will definitely fail, so we get faster feedback by moving that first check to the compile time of the program.&lt;/p&gt;
&lt;p&gt;The final step is now to return the &lt;code&gt;ReturnType&lt;/code&gt; with the &lt;code&gt;PromiseResolvedType&lt;/code&gt; to access the success value of a Promise returned by a function:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type PromiseResolvedType&amp;lt;T&amp;gt; = T extends Promise&amp;lt;infer R&amp;gt; ? R : never;
type ReturnedPromiseResolvedType&amp;lt;T&amp;gt; = PromiseResolvedType&amp;lt;ReturnType&amp;lt;T&amp;gt;&amp;gt;;
// or flattened: type ReturnedPromiseResolvedType&amp;lt;T&amp;gt; = T extends (...args: any[]) =&amp;gt; Promise&amp;lt;infer R&amp;gt; ? R : never;

async function random(): Promise&amp;lt;number&amp;gt; {
  return Math.random();
}

type RandomFuncResolvedType = ReturnedPromiseResolvedType&amp;lt;typeof random&amp;gt;; // number
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href=&quot;https://www.typescriptlang.org/play/#src=type%20PromiseResolvedType%3CT%3E%20%3D%20T%20extends%20Promise%3Cinfer%20R%3E%20%3F%20R%20%3A%20never%3B%0D%0Atype%20ReturnedPromiseResolvedType%3CT%3E%20%3D%20PromiseResolvedType%3CReturnType%3CT%3E%3E%0D%0A%2F%2F%20or%20flattened%3A%20type%20ReturnedPromiseResolvedType%3CT%3E%20%3D%20T%20extends%20(...args%3A%20any%5B%5D)%20%3D%3E%20Promise%3Cinfer%20R%3E%20%3F%20R%20%3A%20never%3B%0D%0A%0D%0Aasync%20function%20random()%3A%20Promise%3Cnumber%3E%20%7B%0D%0A%20%20return%20Math.random()%3B%0D%0A%7D%0D%0A%0D%0Atype%20RandomFuncResolvedType%20%3D%20ReturnedPromiseResolvedType%3Ctypeof%20random%3E%3B%20%2F%2F%20number&quot;&gt;Playground&lt;/a&gt;&lt;/p&gt;
</content:encoded></item><item><title>Custom Cursors: Creating CUR Files from Canvas</title><link>https://timm.preetz.xyz/p/creating-cur-files-from-canvas</link><guid isPermaLink="true">https://timm.preetz.xyz/p/creating-cur-files-from-canvas</guid><pubDate>Sat, 21 Apr 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;A recent product design required switching various custom, dynamic cursors at runtime. These were prepared at runtime and drawn onto a &lt;code&gt;Canvas&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&amp;lt;video src=&quot;/assets/posts/creating-cur-files-from-canvas/cursor-example.mov&quot; autoplay=&quot;true&quot; loop=&quot;true&quot; muted=&quot;true&quot; width=&quot;108&quot;&amp;gt;&amp;lt;/video&amp;gt;&lt;/p&gt;
&lt;p&gt;In Chrome and Firefox those canvases can be used as a cursor by setting the &lt;code&gt;cursor&lt;/code&gt; property in CSS to &lt;code&gt;url(canvas.toDataURL())&lt;/code&gt;. The data URL is guaranteed to contain a &lt;code&gt;base64&lt;/code&gt; encoded &lt;code&gt;PNG&lt;/code&gt; image of the canvas.&lt;/p&gt;
&lt;p&gt;Edge though currently only supports &lt;a href=&quot;https://en.wikipedia.org/wiki/ICO_(file_format)&quot;&gt;&lt;code&gt;CUR&lt;/code&gt; files&lt;/a&gt;. Those files wrap the cursor image, optionally at different sizes, with some metadata. Luckily for us, a newer version of the CUR file format allows embedding &lt;code&gt;PNG&lt;/code&gt; file data directly.&lt;/p&gt;
&lt;p&gt;So I wrote a small library that reads a canvas into &lt;code&gt;PNG&lt;/code&gt; blob and then inserts this data into a new &lt;code&gt;Blob&lt;/code&gt; that builds up the &lt;code&gt;CUR&lt;/code&gt; file. We can then create an &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL&quot;&gt;&quot;&lt;code&gt;object URL&lt;/code&gt;&quot;&lt;/a&gt; of that &lt;code&gt;CUR&lt;/code&gt; file which can be used in CSS similarly to the above method.&lt;/p&gt;
&lt;p&gt;Example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// call the `curObjectURLFromCanvas` function to retrieve an object URL pointing to a `CUR` file containing the canvas&apos; image
const cursorObjectURL = curObjectURLFromCanvas(canvas);

// Use this URL in your inline style (or in a programatically created `StyleSheet`)
body.style.cursor = `url(${cursorObjectURL}), pointer`;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The library is called &lt;code&gt;cursor-utilities&lt;/code&gt; and is available on &lt;a href=&quot;https://www.npmjs.com/package/cursor-utilities&quot;&gt;npm&lt;/a&gt;, and the source is on &lt;a href=&quot;https://github.com/tp/cursor-utilities&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
</content:encoded></item><item><title>WebGL: Smooth Edges on Transparent Canvases</title><link>https://timm.preetz.xyz/p/webgl-smooth-edges-on-transparent-canvases</link><guid isPermaLink="true">https://timm.preetz.xyz/p/webgl-smooth-edges-on-transparent-canvases</guid><pubDate>Sun, 18 Mar 2018 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Task&lt;/h2&gt;
&lt;p&gt;For a client project I needed to draw text on a transparent &lt;code&gt;WebGL&lt;/code&gt; canvas, which was overlaying a video playing in the background of the page.&lt;/p&gt;
&lt;p&gt;After having a hard time with some of the more elaborate &lt;code&gt;Three.js&lt;/code&gt; based examples, I was able to quickly gain an initial understanding of the underlying plumbing when studying &lt;a href=&quot;http://tehmou.github.io/WebGL-from-Scratch/explain.html#mouse_ripple&quot;&gt;this WebGL-from-Scratch example&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The effect came together quickly and looked great, but unfortunately it didn&apos;t render the same across all browsers. In Safari the partially transparent edges of the text where leading to while artifacts, as to can see here around the highlighted arc of the letter &lt;code&gt;e&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/assets/posts/webgl-smooth-edges-on-transparent-canvases/Safari_before.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;At first I thought the &lt;code&gt;alpha&lt;/code&gt; property of the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/getContext&quot;&gt;&lt;code&gt;contextAttributes&lt;/code&gt;&lt;/a&gt; hadn&apos;t been honored, but when switching to a partially transparent font I would be able to see through the letters just fine.&lt;/p&gt;
&lt;h2&gt;Solution&lt;/h2&gt;
&lt;p&gt;Since I was already investigating the context properties, I tried my hand at the next one that could be related related to the transparency issue: &lt;code&gt;premultipliedAlpha&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Simply changing this from &lt;code&gt;false&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt; didn&apos;t improve anything for me in Safari. That was not entirely unexpected, since I assumed that I would have to actually &quot;pre-multiply&quot; the alpha for the setting to work correctly.&lt;/p&gt;
&lt;p&gt;I didn&apos;t know how to actually do this, and whether or not this could even be done with information from the canvas alone (or whether it would require knowing what is underneath it), so I just implemented this first attempt in the shader:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;vec4 pixel = texture2D(tex0, uv).xyzw;

gl_FragColor = vec4(pixel.x * pixel.w, pixel.y * pixel.w, pixel.z * pixel.w, pixel.w);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Luckily that did indeed solve the white marks on the edges, which are now very smooth:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/assets/posts/webgl-smooth-edges-on-transparent-canvases/Safari_after.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Next Steps&lt;/h2&gt;
&lt;p&gt;While the edges are now smooth across the 3 browser listed below, you can see that the rendering color differs across them:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/assets/posts/webgl-smooth-edges-on-transparent-canvases/comparison.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Next, I&apos;ll have to look into how not only to achieve smooth but also color correct renderings.&lt;/p&gt;
&lt;h2&gt;Further Reading&lt;/h2&gt;
&lt;p&gt;A sample project containing the code used for this post is available on GitHub at &lt;a href=&quot;https://github.com/tp/webgl-premultipliedAlpha&quot;&gt;&lt;code&gt;tp/webgl-premultipliedAlpha&lt;/code&gt;&lt;/a&gt;. You can view the demo in browser &lt;a href=&quot;https://cdn.rawgit.com/tp/webgl-premultipliedAlpha/ee3190f9/index.html&quot;&gt;using this link&lt;/a&gt;.&lt;/p&gt;
</content:encoded></item><item><title>7 Days Without Recreational Media</title><link>https://timm.preetz.xyz/p/week-without-recreational-media</link><guid isPermaLink="true">https://timm.preetz.xyz/p/week-without-recreational-media</guid><pubDate>Fri, 23 Feb 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;If I didn’t write this today—right now even—I’d never do it.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Over that last 7 days I’ve been going on a “recreational media hiatus”—meaning not reading, listening to, or watching anything that is not &lt;em&gt;directly applicable&lt;/em&gt; to the work at hand.&lt;/p&gt;
&lt;p&gt;While there is a current trend to ignore specific social networks for a while, this included every single &lt;em&gt;leisurely used&lt;/em&gt;[^0] information source, such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Books not concerned with the current day’s task&lt;/li&gt;
&lt;li&gt;Any Blogs, News Site, Aggregators (&quot;push&quot; content)&lt;/li&gt;
&lt;li&gt;Podcasts and Audio Books&lt;/li&gt;
&lt;li&gt;E-Mail Newsletters[^1]&lt;/li&gt;
&lt;li&gt;TV, Movies, and Radio when alone&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The only two exceptions I allowed myself was using the Calm app&apos;s sleep stories, and the &lt;a href=&quot;https://www.amazon.com/The-Pema-Chodron-Audio-Collection/dp/B000BGZQWA/ref=nav_custrec_signin?ie=UTF8&amp;amp;qid=1519425072&amp;amp;sr=8-2&amp;amp;keywords=pema+chodron+collection&amp;amp;&quot;&gt;Pema Chödrön meditations collection&lt;/a&gt;. I anticipated that I wouldn’t want to spent every minute alone doing work or nothing at all, so getting deeper into meditation seemed like a worthwhile endeavor, one that would hopefully further unclutter and calm my mind.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;I made the decision to try this for a week, while sitting on a train and skipping into the third audiobook on 1 hour ride. I somehow felt that something must be wrong when I couldn’t even keep my attention on an audiobook that I chose myself and wanted to, or at least aspired to, listen to.&lt;/p&gt;
&lt;p&gt;Similarly I noticed that while taking a break during work (🍅), I would often get lost on a tangent like some interesting but obscure technology or some new open source project, which would then far exceed the 5 minute goal time.&lt;br /&gt;
While getting input from outside my immediate area of work and interest is generally an inspiring source, oftentimes nothing sticks out and I wouldn’t have been able to recite half of the topics I scratched that day when asked about it before bedtime.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Here are some unordered observations I made throughout the week:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;As there were much less inputs, every single one of them left way more of an impression, and got more time and thorough thought than in any previous week&lt;/li&gt;
&lt;li&gt;The meditation felt much easier, more fruitful as my mind was not cluttered with technical trivia. Instead I was able to better listen to the teachings and myself&lt;/li&gt;
&lt;li&gt;A lot of times at night I had neither energy to work on anything specific nor the willingness to listen to mediations, so I just ended up doing nothing—just sitting and thinking&lt;/li&gt;
&lt;li&gt;In the course of the week, snacking emerged as an alternative distraction/feel good mechanism. Apparently there were some voids to fill&lt;/li&gt;
&lt;li&gt;Every bit of personal interaction got more valuable. Before I was often so focused on my reading etc. that I would view everyone else nearby as a distraction. Now I was grateful for conversations&lt;/li&gt;
&lt;li&gt;The insights I gained during meditation and the “just sitting” times were profunder than anything I have ever experienced. Instead of just hearing the teachers opinions/experiences/facts, I had some very deep insights emerge from within[^2]&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;p&gt;If I ever get to do this again (who knows, maybe by this time tomorrow I am so exhausted from my “cheat day”, that I&apos;ll plan doing this regularly), I will definitely prepare myself to not fall into the next trap, i.e. stock up on healthy, boring food.&lt;/p&gt;
&lt;p&gt;Other than that I appreciated the change this week, and how it allowed me to reevaluate my day-to-day behavior and see this media consumption in a more honest light: it&apos;s primarily distractions and rewards, which I was voluntarily seeking out–craving even. Only secondarily were they are source of information, often neither actionable or acted upon.&lt;/p&gt;
&lt;p&gt;[^0]: This is an important distinction to make. While often those media are deeply technical in some field, aspirational, or otherwise of importance to some, I often would just read them for recreational purposes: satisfaction and distraction.&lt;/p&gt;
&lt;p&gt;[^1]: Yep, it’s not enough these days to ignore specific apps and not visiting specific sites, somehow I justified for a while now to clutter my inbox with non-critical information. If some site only offers e-mail updates, I will not subscribe to them anymore. The overall downside just outweighs any single of those sources. Side-note: &lt;a href=&quot;https://feedbin.com&quot;&gt;Feedbin&lt;/a&gt; has a great service where you can have newsletters/mails shown alongside your RSS subscriptions.&lt;/p&gt;
&lt;p&gt;[^2]: I think this stems from a mix of the longer time spent doing meditation as well as the different style used on the above mentioned audio collection. It’s meditation practices framed by teachings into hour-long sessions. This additional time compared to the short 5-15 minute sessions others offer might’ve been a major contributor to this.&lt;/p&gt;
</content:encoded></item><item><title>An Asynchronous Web API in 1994</title><link>https://timm.preetz.xyz/p/asynchronous-web-api-1994</link><guid isPermaLink="true">https://timm.preetz.xyz/p/asynchronous-web-api-1994</guid><pubDate>Tue, 12 Dec 2017 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;After going down a &lt;a href=&quot;https://news.ycombinator.com/item?id=15898919&quot;&gt;Hacker News&lt;/a&gt; initiated rabbit hole, I crossed &lt;a href=&quot;https://www.youtube.com/watch?v=BxQw4CdxLr8&quot;&gt;Donald Knuth&apos;s 2017 Christmas Lecture&lt;/a&gt; and from there ended up on the &lt;a href=&quot;http://oeis.org/&quot;&gt;Online Encyclopedia of Integer Sequences&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For every integer sequence you provide, it lists the known occurrences and, if available, formulae that can be used to generate them.&lt;/p&gt;
&lt;p&gt;One interesting detail is, that every page still had a &quot;generated in &lt;em&gt;N&lt;/em&gt; seconds&quot; footer, where &lt;em&gt;N&lt;/em&gt; often was &amp;gt; 5s for my test queries. So it seems like searching 295.000 possible sequences still takes a little computing time, even on modern hardware.&lt;/p&gt;
&lt;p&gt;But while getting an answer on modern hardware in a few seconds is acceptable, let&apos;s image how much longer this might&apos;ve taken a few year back.&lt;/p&gt;
&lt;p&gt;In order to offer advanced searches and explain sequences a new service was established in 1994: &lt;a href=&quot;http://oeis.org/ol.html&quot;&gt;&quot;Superseeker&quot;&lt;/a&gt;. As this services does some &quot;serious computing&quot;, we can take a guess at how much longer it must&apos;ve taken to complete a query.&lt;/p&gt;
&lt;p&gt;So in order to offer this at that time (where homes still had per-minute dial-up), the search API was implemented on top of plain e-mail.&lt;/p&gt;
&lt;p&gt;That way the server could take as long as it needed to generate a response, and the sender would be notified as soon as possible once the calculation was done. What a beautifully simple approach.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Software based on the original bunch of shell scripts from back then is still in use and it&apos;s source code is available &lt;a href=&quot;http://oeis.org/ol_source.txt&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
</content:encoded></item><item><title>Sam Harris: Lying</title><link>https://timm.preetz.xyz/p/lying</link><guid isPermaLink="true">https://timm.preetz.xyz/p/lying</guid><pubDate>Sun, 27 Aug 2017 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&quot;We often behave in ways that are guaranteed to make us unhappy.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Q: What is lying?&lt;br /&gt;
A: &quot;To lie is to intentionally mislead others when they expect honest communication.&quot;[^1]&lt;/p&gt;
&lt;p&gt;At this point it is important to differentiate between telling the truth and being truthful. In my understanding of Harris&apos; text, one is lying when &quot;believing one thing while intending to communicate another&quot; (i.e. not truthful). I am unclear on what is made of uttering statements one believes to be true, but which are objectively false.&lt;/p&gt;
&lt;p&gt;Harris further advocates for telling the truth, as it is just easier. Instead of keeping track of a made-up story, &quot;we can simply be ourselves&quot;.&lt;/p&gt;
&lt;h2&gt;2 Types of Lies&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Acts of comission: &quot;Bad things we do&quot;&lt;/li&gt;
&lt;li&gt;Acts of omission: &quot;Good things we fail to do&quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;According to Harris the former are viewed more harshly than the latter. Also it could be impractical or infeasible to clarify every (unimportant) misunderstanding in which case an act of omission might be justifiable.&lt;/p&gt;
&lt;h2&gt;On &quot;White Lies&quot;&lt;/h2&gt;
&lt;p&gt;Often times people think they&apos;re helping by telling these, but Harris lists a plethora of examples were white lies have a detrimental effect not only on the receiver, but also the sender.&lt;/p&gt;
&lt;p&gt;A common area of this seems to be around medical issues, where family members keep each other in the dark about the actual situation, leading to lost &quot;opportunities for deepening love, compassion, forgiveness, and understanding&quot;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&quot;Children do not learn to tell white lies until around the age of four, after they have achieved a hard-won awareness of the mental states of others.&quot;&lt;/li&gt;
&lt;li&gt;&quot;False encouragement is a kind of theft: it steals time, energy, and motivation a person could put toward some other purpose.&quot;[^2]&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Illusory Truth Effect&lt;/h2&gt;
&lt;p&gt;&quot;[...] people will recall [something] as fact [...] even if they were first exposed to it in the context of its debunking.&quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;By lying, we deny others a view of the world as it is. Our dishonesty not only influences the choices they make, it often determines the choices they can make — and in ways we cannot always predict. Every lie is a direct assault upon the autonomy of those we lie to.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;The whole book is a short read.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;[^1]: According to studies quoted in the book, &quot;10% of communication between spouses is deceptive&quot;, and &quot;38% of encounters among college students contain lies&quot;.&lt;/p&gt;
&lt;p&gt;[^2]: This to me is currently a major argument against acts of omission, and forces my conscience to consider clarifying implicit but also incorrect understandings and assumptions.&lt;/p&gt;
</content:encoded></item><item><title>Rich Hickey: Step Away from the Computer</title><link>https://timm.preetz.xyz/p/step-away-from-the-computer</link><guid isPermaLink="true">https://timm.preetz.xyz/p/step-away-from-the-computer</guid><pubDate>Sat, 26 Aug 2017 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;Also known as &lt;a href=&quot;https://www.youtube.com/watch?v=f84n5oFoZBc&quot;&gt;Hammock Driven Development&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Opening Question: When was the last time you thought hard about something for&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;an hour?&lt;/li&gt;
&lt;li&gt;a day?&lt;/li&gt;
&lt;li&gt;over the course of a month?&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;p&gt;&quot;Key Note&quot; talk by Rich Hickey focussing on the problem solving aspect of programming, which in his experience is influenced and successful due to a lot of thinking without the computer at hand.&lt;/p&gt;
&lt;p&gt;He starts out with the well-established data point that bugs are most costly when they have to fixed in production and that it would be preferable to fix them during development.&lt;br /&gt;
Then he goes backwards one step further and suggest that bugs are least expensive to prevent in the &lt;em&gt;design&lt;/em&gt; of the software.&lt;br /&gt;
Relating to this, it is his understanding that &quot;the biggest problems in software are problems of misconceptions&quot;. When not the actual problems at hand are solved, but rather an attempt is made at solving perceived problems or problems arising solely from the suggested &quot;solution&quot;.&lt;/p&gt;
&lt;p&gt;Another interesting section was about tradeoffs, a word often used to justify a rushed or not fully tested implementation. According to Hickey a real tradeoff requires at least 2 possible solutions, which are then weighed and, finally, one is picked. Once you made a tradeoff, he suggests to record your reasoning and the decision in writing.&lt;/p&gt;
&lt;p&gt;The major problem this talk focuses on, going back to the opening question, is that not enough &lt;em&gt;thought&lt;/em&gt; is put into the problem solving aspect of software development (which after all is the whole purpose of writing programs commercially).&lt;/p&gt;
&lt;p&gt;Speaking of the mind Hickey starts out describing it as two parts: the &quot;Waking Brain&quot; and the &quot;Background Brain&quot;. According to Hickey the first one is very tactical, while the second one is strategical, abstracts, has a great ability to synthesize. Unfortunately the &quot;Background Brain&quot; can&apos;t be used directly, but rather will work on what is most prominent in the &quot;Waking Brain&quot;. The way to get the &quot;Background Brain&quot; to work on what one desires, is to &quot;load it up&quot;.&lt;/p&gt;
&lt;p&gt;In order to do this, one foremost has to be aware that the &quot;Background Brain&quot; can only work on 7±2 problems. So how does one deal with designs that have more than 9 parts? According to Hickey a limited subset of problems should be picked and focused on those.&lt;br /&gt;
Once the problems to be uploaded are picked, the currently proposed solution (from the &quot;Waking Brain&quot;) should be written down.&lt;/p&gt;
&lt;p&gt;Then one should go over the picked problems in varying orders.&lt;/p&gt;
&lt;p&gt;With all this preparation done, now the hammock comes into play. This &quot;mind&apos;s eye time&quot; — lying down with your eyes closed and thinking uninterruptedly — is an integral part of the process.&lt;/p&gt;
&lt;p&gt;Whenever you &quot;hear back&quot; from your &quot;Background Brain&quot;, depending on the situation you might want to act on it immediately, or just take note of the proposed solution. Preferably in writing.&lt;/p&gt;
</content:encoded></item><item><title>Fetching Potentially Compressed Webpages That Might Not be UTF-8 Encoded in Rust</title><link>https://timm.preetz.xyz/p/fetching-compressed-websites-in-rust</link><guid isPermaLink="true">https://timm.preetz.xyz/p/fetching-compressed-websites-in-rust</guid><pubDate>Sun, 07 Aug 2016 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; This write-up explains how I build my first Rust crate to fetch compressed, non-UTF-8 encoded webpages.
If you want to get straight to the code grab the &lt;a href=&quot;https://crates.io/crates/fetch&quot;&gt;final &lt;code&gt;fetch&lt;/code&gt; crate on crates.io&lt;/a&gt; or &lt;a href=&quot;https://github.com/tp/fetch-rs&quot;&gt;view the source on Github&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;For a side-project I needed to download some arbitrary webpages (HTML or plain text only). In absence of a targeted shipping date, I decided to use this opportunity to write this piece of software in &lt;a href=&quot;https://www.rust-lang.org/&quot;&gt;Rust&lt;/a&gt; which I have interestedly observed for a long time but never actually used.&lt;/p&gt;
&lt;h2&gt;Preparation&lt;/h2&gt;
&lt;p&gt;Since there is no http client in the &lt;a href=&quot;https://doc.rust-lang.org/std/&quot;&gt;Rust standard library&lt;/a&gt; I picked the currently most popular http library on &lt;a href=&quot;https://crates.io/search?q=http&amp;amp;sort=downloads&quot;&gt;crates.io&lt;/a&gt;: &lt;a href=&quot;https://github.com/hyperium/hyper&quot;&gt;hyper&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;http://hyper.rs/hyper/v0.9.10/hyper/client/index.html#get&quot;&gt;basic client example&lt;/a&gt; looked fine initially but quickly turned out to be insufficient when testing with a variety of sites.
Many sites send compressed or non-UTF-8 encoded data, and while the former could often be solved by setting the &lt;code&gt;Accept-Encoding&lt;/code&gt; header to &lt;code&gt;identity&lt;/code&gt;, the latter required some more changes to the program since strings are always &lt;a href=&quot;https://doc.rust-lang.org/std/string/struct.String.html#utf-8&quot;&gt;UTF-8 encoded in Rust&lt;/a&gt; and thus needed to be converted.&lt;/p&gt;
&lt;p&gt;So I expanded my list of dependencies to the following set of crates:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/hyperium/hyper&quot;&gt;hyper&lt;/a&gt;: &lt;a href=&quot;http://hyper.rs/hyper/v0.9.10/hyper/client/index.html&quot;&gt;http client&lt;/a&gt; to retrieve the data from the server&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/alexcrichton/flate2-rs&quot;&gt;flate2&lt;/a&gt;: compression library that is used to decode &lt;a href=&quot;https://en.wikipedia.org/wiki/Gzip&quot;&gt;gzip&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/DEFLATE&quot;&gt;DEFLATE&lt;/a&gt; compressed responses&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/lifthrasiir/rust-encoding&quot;&gt;encoding&lt;/a&gt;: character set conversion from various encodings to Rust strings&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;p&gt;First let&apos;s look at how easily the current implementation make it to fetch a pages body as &lt;code&gt;String&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;let body = fetch::fetch_page(&quot;https://www.rust-lang.org/en-US/&quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;The final project used for the prototype and this blog post is available on Github at &lt;a href=&quot;https://github.com/tp/fetch-rs&quot;&gt;tp/fetch-rs&lt;/a&gt;. It has also been publish as the &lt;a href=&quot;http://crates.io/crates/fetch&quot;&gt;&lt;code&gt;fetch&lt;/code&gt; crate on crates.io&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Like alluded to above, I started out with a simple &lt;code&gt;hyper&lt;/code&gt; client that worked fine for the first few manual fetches. I could just read the response into a string using:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;let mut body_buffer = String::new();

response.read_to_string(&amp;amp;mut body_buffer);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But this would fail when the page was not encoded in UTF-8 or would just return garbled output for compressed content.&lt;/p&gt;
&lt;p&gt;So I went looking for an encoding and a decompression library, which let me to &lt;code&gt;encoding&lt;/code&gt; and &lt;code&gt;flate2&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now things became a little more involved since I had to explore the 2 new crates, which had to be done differently from how I would normally approach this, since full autocompletion for crates &lt;a href=&quot;https://github.com/phildawes/racer/issues/551&quot;&gt;is not yet available&lt;/a&gt;. But thanks to the pervasive use of &lt;a href=&quot;https://doc.rust-lang.org/book/documentation.html#about-rustdoc&quot;&gt;&lt;code&gt;rustdoc&lt;/code&gt;&lt;/a&gt; there is a good amount of documentation on every crate that I encountered.&lt;/p&gt;
&lt;p&gt;So after a while of reading the API documentations, I was able to unzip the response body&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;let mut unzipped_body_buffer = Vec::new();
GzDecoder::new(body_buffer.as_slice());
d.read_to_end(&amp;amp;mut unzipped_body_buffer);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and also convert the given charset to UTF-8:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;let decoder = encoding_from_whatwg_label(charset).unwrap();
return decoder.decode(&amp;amp;unzipped_body_buffer, DecoderTrap::Strict)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;[Please note that the examples above are abbreviated excerpts from the actual source code and do not contain proper error handling. Please look at the &lt;a href=&quot;https://github.com/tp/fetch-rs/blob/master/src/lib.rs&quot;&gt;source&lt;/a&gt; to see how errors are currently handled.]&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Once my spot checks succeeded, I wanted to try the Rust testing facilities to ship some tests with the library. As it turns out, testing your code is super easy: Just annotate test functions in your library with &lt;code&gt;#[test]&lt;/code&gt; and run &lt;code&gt;cargo test&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Currently I just check whether the fetch returns a &lt;a href=&quot;https://doc.rust-lang.org/std/result/enum.Result.html&quot;&gt;success value&lt;/a&gt;, but as a next step I want to setup a test server and compare the whole response body to a reference file.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#[test]
fn fetch_deflate_compressed_page() {
    fetch_page(&quot;http://httpbin.org/deflate&quot;).expect(&quot;Fetch to succeed&quot;);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After all tests passed[^1] I was satisfied with the initial scope of library and went on to publish it to crates.io.&lt;/p&gt;
&lt;p&gt;This turned out to be a little bit trickier than it probably should have been, due to me initially naming the crate “http-fetch”.&lt;/p&gt;
&lt;p&gt;When integration testing the crate with another project I soon found out that while your crate name on crates.io can contain a hyphen, you have to import it with a &lt;a href=&quot;http://stackoverflow.com/questions/31846789/crate-name-with-hyphens-not-being-recognized&quot;&gt;different&lt;/a&gt; &lt;a href=&quot;https://m.reddit.com/r/rust/comments/4rlom7/what_characters_are_allowed_in_a_crate_name/d52bdyp&quot;&gt;name&lt;/a&gt; when using it in Rust code. Not wanting to explain this (confusing) behavior in the README I decided to rename the crate (which I had already published). Since it was not possible to rename from “http-fetch” to “http_fetch” for some reason (cargo would not allow this), I created a new crate named “&lt;a href=&quot;crates.io/crates/fetch&quot;&gt;fetch&lt;/a&gt;”.&lt;/p&gt;
&lt;h2&gt;Retrospection&lt;/h2&gt;
&lt;p&gt;Though this project is small and in a functional state right now, there are already a number of points that I need to dig into deeper before writing more complex programs in Rust:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Error handling&lt;/strong&gt;: In order to return errors from &lt;code&gt;fetch&lt;/code&gt; using the &lt;a href=&quot;https://doc.rust-lang.org/std/result/enum.Result.html&quot;&gt;Result&lt;/a&gt; type which requires a common interface for all possible errors I am currently transforming all errors and replace them with a string containing a short description of where the error occurred. Sadly this looses the original error, which the call side might want to evaluate to help with debugging etc.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://doc.rust-lang.org/book/references-and-borrowing.html#borrowing&quot;&gt;Borrowing&lt;/a&gt; and Ownership&lt;/strong&gt;: When reading into the buffer a second time I would get &lt;a href=&quot;https://doc.rust-lang.org/error-index.html#E0506&quot;&gt;error E0506&lt;/a&gt; reported by the compiler. While I don&apos;t yet fully understand the reason for this, the suggested solution of just scoping offending code in its on &lt;code&gt;{ }&lt;/code&gt; block works.&lt;/p&gt;
&lt;p&gt;A lack of understanding &lt;a href=&quot;https://doc.rust-lang.org/book/lifetimes.html&quot;&gt;lifetimes&lt;/a&gt; has also so far prevented me from breaking the code up into smaller functions, which would require some special annotations (I assume).&lt;/p&gt;
&lt;p&gt;All in all I was highly rewarded for this experiment by being exposed to new concepts and different approaches to API design and programming altogether. Furthermore I was positively surprised how quick I could pursue and find my way around the crates given the lack of full code completion. Thanks to great documentation being available for all crates used, this was not as big of a slowdown as I would have expected initially.&lt;/p&gt;
&lt;p&gt;Now I am looking forward to writing more code in Rust and get a better understanding of and write future-proof solutions for the issues mentioned above.&lt;/p&gt;
&lt;p&gt;[^1]: Which was did not succeed immediately, since I had an error with DEFLATE compressed responses. Turns out you have to run them through the &lt;a href=&quot;http://alexcrichton.com/flate2-rs/flate2/read/struct.ZlibDecoder.html&quot;&gt;&lt;code&gt;ZlibDecoder&lt;/code&gt;&lt;/a&gt; instead of the &lt;a href=&quot;http://alexcrichton.com/flate2-rs/flate2/read/struct.DeflateDecoder.html&quot;&gt;&lt;code&gt;DeflateDecoder&lt;/code&gt;&lt;/a&gt; which I assumed at first (given the name). So, lesson learned, always test your code 🤗&lt;/p&gt;
</content:encoded></item><item><title>Using RubaXa Sortable with Ember.js</title><link>https://timm.preetz.xyz/p/using-rubaxa-sortable-with-emberjs</link><guid isPermaLink="true">https://timm.preetz.xyz/p/using-rubaxa-sortable-with-emberjs</guid><pubDate>Thu, 16 Apr 2015 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&amp;lt;img src=&quot;/assets/posts/Sortable.gif&quot; width=&quot;314&quot;&amp;gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://rubaxa.github.io/Sortable/&quot;&gt;Sortable by RubaXA&lt;/a&gt; is a great library for visually sorting elements in HTML apps.
Sadly it has &lt;a href=&quot;https://github.com/RubaXa/Sortable/issues/175&quot;&gt;no built-in support for Ember.js&lt;/a&gt;, so I thought I would elaborate here how I added it to a client&apos;s &lt;a href=&quot;http://emberjs.com/&quot;&gt;Ember.js&lt;/a&gt; app.&lt;/p&gt;
&lt;h2&gt;Creating a SortableList component&lt;/h2&gt;
&lt;p&gt;app/components/sortable-list.js:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import Ember from &quot;ember&quot;;
import Sortable from &quot;npm:sortablejs&quot;; // this requires Ember CLI with ember-browserify, which is great!

export default Ember.Component.extend({
  init: function () {
    this._super();

    Ember.assert(
      &quot;required `viewModels` param is set&quot;,
      !Ember.isNone(this.get(&quot;viewModels&quot;)),
    );
  },
  tagName: &quot;ul&quot;,
  classNames: [&quot;sortableList&quot;],
  actions: {
    removeItem: function (index) {
      this.sendAction(&quot;removeItem&quot;, index);
    },
  },
  didInsertElement: function () {
    console.debug(&quot;Setup Sortable in didInsertElement&quot;);

    let s = Sortable.create(document.getElementById(this.get(&quot;elementId&quot;)), {
      draggable: &quot;.sortableTopicListItem&quot;,
      onSort: (evt) =&amp;gt; {
        if (evt.type !== &quot;sort&quot;) {
          console.debug(&quot;Skipping event that is not sort.&quot;);
          return;
        }

        if (evt.oldIndex === evt.newIndex) {
          console.debug(
            &quot;NOOP, evt.oldIndex === evt.newIndex; not sending action; not removing element&quot;,
          );
          return;
        }

        console.debug(
          `evt.oldIndex = ${evt.oldIndex} -&amp;gt; evt.newIndex = ${evt.newIndex}`,
        );

        let dragItem = evt.item;
        dragItem.parentNode.removeChild(dragItem);

        this.sendAction(&quot;itemMoved&quot;, evt.oldIndex, evt.newIndex);
      },
    });

    this.set(&quot;Sortable&quot;, s); // for later destruction
  },
  willDestroyElement: function () {
    console.debug(&quot;destroying Sortable in willDestroyElement&quot;);
    this.get(&quot;Sortable&quot;).destroy();
  },
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;app/templates/components/sortable-list.hbs:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{{#each viewModels as |viewModel index|}}
  &amp;lt;li class=&quot;sortableTopicListItem&quot;&amp;gt;
    {{viewModel.displayName}}
    &amp;lt;i {{action removeItem index}} class=&quot;remove&quot;&amp;gt;✖&amp;lt;/i&amp;gt;
  &amp;lt;/li&amp;gt;
{{/each}}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Using the SortableList component&lt;/h2&gt;
&lt;p&gt;Showing items with a SortableList is now very easy. All you have to do is supply some &lt;code&gt;viewModels&lt;/code&gt; which have &lt;code&gt;displayName&lt;/code&gt; property.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{{sortable-list
  viewModels=viewModels
  itemMoved=&quot;moveItem&quot;
  removeItem=&quot;removeItem&quot;
}}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It get&apos;s a little more complicated, when you want to reflect the actions that took place in the DOM in your internal data model.&lt;/p&gt;
&lt;p&gt;For this the work the enclosing component has to implement &lt;code&gt;moveItem&lt;/code&gt; and &lt;code&gt;removeItem&lt;/code&gt; actions where it recreates the changes in it&apos;s internal store.&lt;/p&gt;
&lt;p&gt;This is the relevant part from one of my enclosing components:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;actions: {
  moveItem: function(oldIndex, newIndex) {
    Ember.assert(&apos;required `oldIndex` param is set&apos;, !Ember.isNone(oldIndex));
    Ember.assert(&apos;required `newIndex` param is set&apos;, !Ember.isNone(newIndex));

    console.debug(`oldIndex = ${oldIndex} -&amp;gt; newIndex = ${newIndex}`);

    let references = this.get(&apos;value&apos;); // Your underlying array

    let movingReference = references.objectAt(oldIndex);

    references.removeAt(oldIndex, 1);
    references.insertAt(newIndex, movingReference);
  },
  removeItem: function(index) {
    Ember.assert(&apos;required `index` param is set&apos;, !Ember.isNone(index));

    let references = this.get(&apos;value&apos;);
    references.removeAt(index, 1);
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I hope this is helpful for everyone looking to solve a similar problem.&lt;/p&gt;
</content:encoded></item><item><title>Increase Video Playback Speed on Netflix</title><link>https://timm.preetz.xyz/p/increase-netflix-video-playback-speed</link><guid isPermaLink="true">https://timm.preetz.xyz/p/increase-netflix-video-playback-speed</guid><pubDate>Wed, 04 Mar 2015 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Like some other &lt;a href=&quot;http://www.reddit.com/r/netflix/comments/2ikk00/questionmeta_can_i_speed_up_the_playback_of_movies/&quot;&gt;people on the internet&lt;/a&gt; I was frustrated that I couldn&apos;t speed up the playback speed of Netflix videos like I got used to on YouTube.&lt;/p&gt;
&lt;p&gt;With this little peace of code one can easily increase the playback speed of the main video:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;document.getElementsByTagName(&apos;video&apos;)[0].playbackRate = 1.2
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Turns out it is not as generally useful as increasing &lt;a href=&quot;/2015/02/22/increased-podcast-playback-speeds.html&quot;&gt;podcast playback speeds&lt;/a&gt;, though.&lt;br /&gt;
While speedier dialogues are great, the unnatural fast body movements at higher speeds distract me a lot.&lt;/p&gt;
</content:encoded></item><item><title>Waterproof Running Shoes</title><link>https://timm.preetz.xyz/p/waterproof-running-shoes</link><guid isPermaLink="true">https://timm.preetz.xyz/p/waterproof-running-shoes</guid><pubDate>Tue, 03 Mar 2015 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;No more bad-weather-excuses. Get out and run.&lt;/p&gt;
</content:encoded></item><item><title>Alex Payne on Mindfulness as a Performance Enhancing Tool</title><link>https://timm.preetz.xyz/p/alex-payne-mindfulness-performance-enhancing</link><guid isPermaLink="true">https://timm.preetz.xyz/p/alex-payne-mindfulness-performance-enhancing</guid><pubDate>Thu, 26 Feb 2015 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;why do I want to be better at my job?&lt;br /&gt;
who benefits if I’m more productive?&lt;br /&gt;
does my labor reduce suffering more than sitting in mindful contemplation?&lt;/p&gt;
&lt;p&gt;— from &lt;a href=&quot;https://al3x.net/2015/02/24/meditation-and-performance.html&quot;&gt;Meditation and Performance by Alex Payne&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded></item><item><title>Image (File) Input Component for Ember.js</title><link>https://timm.preetz.xyz/p/file-input-component-for-emberjs</link><guid isPermaLink="true">https://timm.preetz.xyz/p/file-input-component-for-emberjs</guid><pubDate>Mon, 23 Feb 2015 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In order to enable a great user experience I wanted to show the user&apos;s newly selected profile picture in one of our clients web apps right after she choose the desired file in her browser&apos;s file picker dialog.&lt;/p&gt;
&lt;p&gt;Unfortunately this is not yet as easy as a simple &lt;code&gt;&amp;lt;input type=&quot;file&quot; file={{file}}&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Having found &lt;a href=&quot;http://www.html5rocks.com/en/tutorials/file/dndfiles/&quot;&gt;this pure JavaScript implementation&lt;/a&gt; of similar behaviour on HTML5 Rocks, I set out to port it to Ember.&lt;/p&gt;
&lt;p&gt;Since I was not able to find any recent Ember-compatible code solving this problem, I created my own version using the latest Ember conventions: a &lt;a href=&quot;http://emberjs.com/api/classes/Ember.Component.html&quot;&gt;component&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;app/components/file-input.js:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import Ember from &quot;ember&quot;;

export default Ember.TextField.extend({
  type: &quot;file&quot;,
  change: function (e) {
    let self = this;

    var inputFiles = e.target.files;
    if (inputFiles.length &amp;lt; 1) {
      return;
    }

    let inputFile = inputFiles[0];

    let fileInfo = {
      name: inputFile.name,
      type: inputFile.type || &quot;n/a&quot;,
      size: inputFile.size,
      date: inputFile.lastModifiedDate
        ? inputFile.lastModifiedDate.toLocaleDateString()
        : &quot;n/a&quot;,
    };

    var fileReader = new FileReader();

    fileReader.onload = function (e) {
      let fileReader = e.target;
      fileInfo.dataURL = fileReader.result;

      self.sendAction(&quot;fileChanged&quot;, fileInfo);
    };

    let firstFile = e.target.files[0];
    fileReader.readAsDataURL(firstFile);
  },
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;app/components/image-input.js:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import Ember from &quot;ember&quot;;

export default Ember.Component.extend({
  file: null,
  actions: {
    fileSelectionChanged: function (file) {
      this.set(&quot;file&quot;, file);
    },
  },
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;app/templates/components/image-input.hbs:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;strong&amp;gt;Image Input&amp;lt;/strong&amp;gt;&amp;lt;br /&amp;gt;

{{#if file}}
&amp;lt;img src=&quot;{{file.dataURL}}&quot; width=&quot;300&quot; /&amp;gt;

&amp;lt;ul&amp;gt;
  &amp;lt;li&amp;gt;Name: {{file.name}}&amp;lt;/li&amp;gt;
  &amp;lt;li&amp;gt;Type: {{file.type}}&amp;lt;/li&amp;gt;
  &amp;lt;li&amp;gt;Size: {{file.size}} bytes&amp;lt;/li&amp;gt;
  &amp;lt;li&amp;gt;Last modified: {{file.date}}&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
{{/if}}

&amp;lt;br /&amp;gt;

{{ file-input fileChanged=&quot;fileSelectionChanged&quot;}}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now usage is as easy as &lt;code&gt;{{image-input}}&lt;/code&gt;!&lt;/p&gt;
&lt;p&gt;The result looks like this:&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- &lt;img src=&quot;/assets/posts/ember.js_image-input_component.png&quot; alt=&quot;image-input Ember component&quot; /&gt; --&amp;gt;
&amp;lt;img src=&quot;/assets/posts/ember.js_image-input_component.png&quot; width=&quot;314&quot;&amp;gt;&lt;/p&gt;
</content:encoded></item><item><title>Increased Podcast Playback Speeds</title><link>https://timm.preetz.xyz/p/increased-podcast-playback-speeds</link><guid isPermaLink="true">https://timm.preetz.xyz/p/increased-podcast-playback-speeds</guid><pubDate>Sun, 22 Feb 2015 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Just a quick thanks to Marco Arment for his Smart Speed feature in &lt;a href=&quot;https://overcast.fm/&quot;&gt;Overcast&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Smart Speed combined with regular playback speed-ups allows me to easily listen to interview podcasts at speeds greater than 1.5x.&lt;/p&gt;
&lt;p&gt;For example I was able to listen to &lt;a href=&quot;http://fourhourworkweek.com/2014/10/15/money-master-the-game/&quot;&gt;these two parts of the Tim Ferriss Show&lt;/a&gt; (2h07m total) and &lt;a href=&quot;http://www.jamesaltucher.com/2014/11/robbins/&quot;&gt;this episode of the James Altucher Show&lt;/a&gt; (1h04m) both interviewing &lt;a href=&quot;http://www.tonyrobbins.com/&quot;&gt;Tony Robbins&lt;/a&gt; about &lt;a href=&quot;http://www.amazon.de/gp/product/B00MZAIU4G/ref=as_li_tl?ie=UTF8&amp;amp;camp=1638&amp;amp;creative=19454&amp;amp;creativeASIN=B00MZAIU4G&amp;amp;linkCode=as2&amp;amp;tag=gummibaerchen-21&amp;amp;linkId=2NTA2WZFCGR66HJA&quot;&gt;his new book&lt;/a&gt; in the same amount of time than just listening to the former at 1x.&lt;/p&gt;
&lt;p&gt;For me personally I can confirm &lt;a href=&quot;http://www.marco.org/2015/02/17/listen-to-podcasts-at-whatever-speed-you-want&quot;&gt;Marco’s assumption&lt;/a&gt;, that listening to podcasts faster just makes me listen to more podcasts.&lt;/p&gt;
</content:encoded></item><item><title>Making HTTP requests beyond the 32MB urlfetch limit on Google App Engine</title><link>https://timm.preetz.xyz/p/large-http-requests-exceeding-the-urlfetch-limit</link><guid isPermaLink="true">https://timm.preetz.xyz/p/large-http-requests-exceeding-the-urlfetch-limit</guid><pubDate>Thu, 15 Jan 2015 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Since Google App Engine&apos;s &lt;code&gt;urlfetch&lt;/code&gt; service &lt;a href=&quot;https://cloud.google.com/appengine/docs/go/urlfetch/#Go_Quotas_and_limits&quot;&gt;imposes a 32MB response size limit&lt;/a&gt; on each request, one has to roll their own &lt;a href=&quot;http://golang.org/pkg/net/http/#Client&quot;&gt;http.Client&lt;/a&gt; implementation using &lt;code&gt;appengine/socket&lt;/code&gt; to make requests exceeding that limit.&lt;/p&gt;
&lt;p&gt;Sadly the &lt;code&gt;appengine/socket&lt;/code&gt; implementation is &lt;a href=&quot;https://code.google.com/p/googleappengine/issues/detail?id=11076&quot;&gt;not working with HTTP calls inside the local development server&lt;/a&gt;, such that one can not use the same solution and code in development and production.&lt;/p&gt;
&lt;p&gt;The two issues made me create the &lt;a href=&quot;http://godoc.org/timm.io/fetchall&quot;&gt;&lt;code&gt;fetchall&lt;/code&gt; package&lt;/a&gt;, a simple drop-in replacement for &lt;code&gt;urlfetch&lt;/code&gt; that gives you a &lt;code&gt;http.Client&lt;/code&gt; implementation that handles arbitrarily large HTTP requests (within the time limits of Google App Engine).&lt;/p&gt;
&lt;p&gt;When running in the development server, the implementation will simply use Go&apos;s &lt;code&gt;net&lt;/code&gt; package instead of &lt;code&gt;appengine/socket&lt;/code&gt; in order for request to work locally as well as in the cloud.&lt;/p&gt;
&lt;p&gt;To use this package simply replace &lt;code&gt;urlfetch.Client&lt;/code&gt; with &lt;code&gt;fetchall.Client&lt;/code&gt; in your Go code.&lt;/p&gt;
&lt;p&gt;GitHub: &lt;a href=&quot;https://github.com/tp/fetchall&quot;&gt;github.com/tp/fetchall&lt;/a&gt;&lt;br /&gt;
GoDoc: &lt;a href=&quot;http://godoc.org/timm.io/fetchall&quot;&gt;godoc.org/timm.io/fetchall&lt;/a&gt;&lt;/p&gt;
</content:encoded></item><item><title>Simple App Engine Datastore Entity Versioning With Go</title><link>https://timm.preetz.xyz/p/simple-app-engine-datastore-entity-versioning-with-go</link><guid isPermaLink="true">https://timm.preetz.xyz/p/simple-app-engine-datastore-entity-versioning-with-go</guid><pubDate>Mon, 20 Oct 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In a recent project we needed the ability to save every version of a &lt;code&gt;User&lt;/code&gt;&apos;s profile (type &lt;code&gt;UserProfile&lt;/code&gt;) in our database, so that we are able track changes over time and restore or review previous versions.&lt;/p&gt;
&lt;p&gt;Since there does not seem to be a standard way to do entity versioning with App Engine Datastore entities, I wrote up a quick sample below of how I solved this.&lt;/p&gt;
&lt;p&gt;I think there are two basically two way to achieve this whithout data normalization (i.e. storing the latest version in a special place):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Store an ever increasing version number with the entities. Pick the one with the highest version number when querying. Optionally this can be used to only allow successive saves (from version 3 to 4 to 5 etc.).&lt;/li&gt;
&lt;li&gt;Store the creation/save date with each entity. Pick the entity with the most recent creation date when querying.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;(I won&apos;t delve into &lt;a href=&quot;http://en.wikipedia.org/wiki/Delta_encoding&quot;&gt;delta compression&lt;/a&gt; here, which may be worth considering if your entities are sufficiently large or change a lot.)&lt;/p&gt;
&lt;p&gt;I opted for a solution based on the entity creation time instead of a entity versioning solution that requires successive entities versions since those can be created without reading the previous entities&apos; version number from the &lt;code&gt;datastore&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This also has the benefit that we’re able to restore the state of the whole database for any point in time since all changing entities are tagged with their creation date.&lt;/p&gt;
&lt;p&gt;And because writes to a single entity group (in our case the &lt;code&gt;User&lt;/code&gt;) are strongly consistend and &lt;a href=&quot;https://cloud.google.com/appengine/docs/go/datastore/#Go_Datastore_writes_and_data_visibility&quot;&gt;guaranteed to be executed before the next read&lt;/a&gt; of entities in that group, we are always seeing the most recently created &lt;code&gt;UserProfile&lt;/code&gt; in our queries.&lt;/p&gt;
&lt;h2&gt;Implemenation &amp;amp; Tests&lt;/h2&gt;
&lt;p&gt;main.go&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;package main

import (
	&quot;fmt&quot;
	&quot;time&quot;

	&quot;appengine&quot;
	&quot;appengine/datastore&quot;
)

const (
	KindUser        = &quot;user&quot;
	KindUserProfile = &quot;userprofile&quot;
)

func main() {}

type CreatedAtStruct struct {
	CreatedAt time.Time
}

func (c *CreatedAtStruct) SetCreatedAt(t time.Time) {
	c.CreatedAt = t
}

type CreationDateSetter interface {
	SetCreatedAt(t time.Time)
}

type User struct{}

type UserProfile struct {
	CreatedAtStruct

	Counter int
}

func putVersioned(c appengine.Context, kind string, parent *datastore.Key, v CreationDateSetter) (*datastore.Key, error) {
	if parent == nil {
		return nil, fmt.Errorf(&quot;parent must be set&quot;)
	}

	v.SetCreatedAt(time.Now())

	return datastore.Put(c, datastore.NewIncompleteKey(c, kind, parent), v)
}

func getLatest(c appengine.Context, kind string, parent *datastore.Key, v interface{}) error {
	q := datastore.NewQuery(kind).Ancestor(parent).Order(&quot;-CreatedAt&quot;).Limit(1)

	_, err := q.Run(c).Next(v)

	return err
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;main_test.go&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;package main

import (
	&quot;testing&quot;

	&quot;appengine/aetest&quot;
	&quot;appengine/datastore&quot;
)

func TestVersionedStorageAfterEachPut(t *testing.T) {
	c, err := aetest.NewContext(nil)
	if err != nil {
		t.Fatal(err)
	}

	userkey, err := datastore.Put(c, datastore.NewIncompleteKey(c, KindUser, nil), &amp;amp;User{})
	if err != nil {
		t.Fatal(err)
	}

	for i := 0; i &amp;lt; 10; i++ {
		p := &amp;amp;UserProfile{Counter: i}
		_, err := putVersioned(c, KindUserProfile, userkey, p)
		if err != nil {
			t.Fatal(err)
		}

		outputProfile := new(UserProfile)
		err = getLatest(c, KindUserProfile, userkey, outputProfile)
		if err != nil {
			t.Fatal(err)
		}

		if outputProfile.Counter != i {
			t.Fatalf(&quot;Expected Counter to be %d but it was %d&quot;, i, outputProfile.Counter)
		}
	}
}

func TestVersionedStorageAfterAllPuts(t *testing.T) {
	c, err := aetest.NewContext(nil)
	if err != nil {
		t.Fatal(err)
	}

	userkey, err := datastore.Put(c, datastore.NewIncompleteKey(c, KindUser, nil), &amp;amp;User{})
	if err != nil {
		t.Fatal(err)
	}

	upper := 10
	for i := 1; i &amp;lt;= upper; i++ {
		p := &amp;amp;UserProfile{Counter: i}
		_, err := putVersioned(c, KindUserProfile, userkey, p)
		if err != nil {
			t.Fatal(err)
		}
	}

	outputProfile := new(UserProfile)
	err = getLatest(c, KindUserProfile, userkey, outputProfile)
	if err != nil {
		t.Fatal(err)
	}

	if outputProfile.Counter != upper {
		t.Fatalf(&quot;Expected Counter to be %d but it was %d&quot;, upper, outputProfile.Counter)
	}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href=&quot;https://gist.github.com/tp/c1e25ae24d405a58f081&quot;&gt;See Gist on GitHub&lt;/a&gt;&lt;/p&gt;
</content:encoded></item></channel></rss>