 Hey, everyone. Welcome back to my Developer Diary series, where I'm talking about how I'm making a camera app. One of the things that I want to cover in this series is places where things didn't go quite right. One of the things that trips up a lot of developers, and I wanted to experience that pain along with you, is cross-browser support. So in particular, I really need to be able to support iOS and Android. So that's Chrome on Android and Safari on iOS. So last time I talked about capturing images in a way that works across lots of browsers, but now I need to be able to store them on the device. My initial thought was to use the cache storage API, which is part of the service worker spec. This is a very good way of storing resources against a URL, which is perfect because eventually these local resources will be uploaded to a server. So be able to just store them against the URL they will eventually have. Sadly, cache storage is not actually implemented on Safari. So instead, we have to fall back to something that is available on both platforms, IndexedDB, otherwise known as IDB. IDB isn't my favorite API, but it is very capable. So I just wrote a simple abstraction layer around it in order to do the things that I needed to do. So here is that abstraction layer. It's a simple class that wraps around IndexedDB, and I've called it ImageDB. You might notice at this point that I've actually written this in TypeScript. If you're not familiar with TypeScript, just take any of these parts that's like a colon and then a type and just pretend it's documentation. TypeScript is really just JavaScript with this little extra layer on top. That said, let's talk about what this is actually doing. So when you create an ImageDB, it creates the database and sets up these event handlers. Nothing particularly exciting there. I've got a method for storing this thing, which is called an image record. An image record is just a plain object that stores the images and any metadata that I need about those images. Then I can retrieve an image record from the database. I've got a method here called all, which just gets all of the image records that are in the database. This is used for the Browse page, where I show all of the images that are available. And then there's these sort of internal helpers here. The only real important one here is the create object store method, which actually creates the database the first time you go to the app or grades it if you've been there before with an odd version of the application. So this layer was working pretty great for me, but I soon ran into a problem. So the image record objects that I'm using, I was originally using blobs to store any image data. I mean, this made perfect sense. When I wanted to get an image through file upload, copy and paste, getting an image out of a canvas, they all gave me a blob. And when I wanted to display an image, I'd get a blob and get its URL and use that blob URL as the source of an image. Unfortunately, you can't store blobs in Safari on iOS at all. What you can do is store an array buffer. So instead of using blobs everywhere, I just need to do a little bit of conversion any time that I get a blob, turn it into an array buffer to store it and turn it back into a blob to use it. So let's have a look at that conversion. So if you have an array buffer and you want to turn it into a blob, that's pretty easy. You use the blob constrictor. You pass in the array buffer in an array as the first element, and then you just pass in the type that you want it to be. So here this will be something like image slash JPEG. To go the other way around is slightly more complicated. So I created a little helper here. If you want to take a blob and turn it into an array buffer, you can use the file reader API. So you create a file reader and then you say that you want to read as array buffer some blob and then eventually get this load end event. And here you can see I've wrapped it in a promise and I just resolve with the result. So there you go. It was kind of tricky to work out how to get around this, but in the end it was possible. Sure, you can't store blobs in IDB on iOS, but there was a way around it. And that's the story for a lot of web development nowadays. Modern web development is all about finding out what works across all the browsers. Hopefully this is getting easier over time, but these things will still happen. So hopefully that was useful to anyone who's coming across the same problem. And join me next time where we'll learn about something new. Thanks for watching. If you'd like to see more of our videos, click here and see you again. Cheers.