Open Source is beautiful. I use an open-sourced app called Gifski to create GIFs in my Pull Requests and JIRA tickets. And, because I use the app a lot, I had my list of things I would like to see in the upcoming versions, e.g.:
- better width/height controls
- removed “save panel” at the beginning of the conversion
- built-in trimming
- better support for small-sized GIFs
Normally I would just send an e-mail with suggestions on how to improve the product, but because the app is open-sourced, I could just implement all of it myself. Did I manage to do that? Almost!
It all started when I saw Sindre tweeting about Gifski and that it would use some contribution. I always wanted to contribute to Gifski one day, but it totally got off of my radar. I didn’t have bigger plans in the pipeline back then and so I knew that it was my time to help with the app.
I started looking around to see what tasks were available for a novice like me. A novice, because I had zero knowledge about GIFs underlying structure, macOS app development or the Gifski app itself. But then I saw a perfect task: a list of “quick fixes” across the app.
I think you get the idea. Most of these improvements were TODOs and code issues related to Swift - and this is really my comfort zone. Not only because I think I’m doing a good job with Swift, but also because this would allow me to explore the app.
I immediately “assigned” myself to it and started tinkering:
And for the next few days I was exploring the app… But it didn’t work out that well. I was stuck on one of the bullet points in the list (related to AppKit…) and I decided to stop and look around for some other issues instead.
I found two tasks that seemed to me like “low-hanging fruits”:
- QuickLook on the result GIF
- System Service support
I “finished” both of these on the same day and created two PRs (#79, #80):
… but they weren’t that good as well. I was still learning AppKit and I quickly realized that I didn’t fully understand some of the components I used. And so I had to spend some time after the PRs to read about differences in AppKit and UIKit (especially Responder Chain 😅).
Also this was my first time working with Sindre and it really felt different than all of the things I used to do in OSS before. Sindre has an eye for detail and his reviews were really spot on. We touched a lot more than just the context of a PR. He was keen to improve everything that didn’t feel good, even though it might not have been in the specs before. I know that it’s not something that everyone likes, but this is something I really appreciate - all in all we both wanted to create something great. And so we went back & forth with with comments, UX/UI changes and code cleanups. After 2 weeks of work and total of 63 comments, finally my first PRs were merged:
Implementing my personal wishlist
Given the confidence after two merged PRs, I was able to bring the big guns…
Better width/height controls
The biggest problem I had with Gifski was that I wasn’t able to precisely select width/height without spending a minute or two with a slider. And so the idea was to replace the sliders with text fields instead.
This was something that many people wanted as well and there was even a PR that was working. The problem was that the PR was abandoned, code was pretty “dirty” and there were some bugs/missing pieces. Oh, and also few Sindre’s comments that weren’t implemented as well. The author wanted to finish it, but didn’t have time to do so. So I had to gather all that info in one place, make a todo-list with a fresh PR and then make it work. Pretty simple, eh?
Yup. 112 comments, more than a month of work and about 2 times where I thought to myself that I don’t have much energy left for this one.
Why? I think my problem was that I started working on someone else’s code instead of writing it from scratch. There were many cases where I would be really confused about what is going on. I would add one feature and then it would break some other things. But finally I realized that I have to completely rewrite it so I can unit test the underlying logic. After that (and few other issues), the PR was merged as well:
(as you can see it was really hard one for both of us 😅)
Add Gifski metadata to the generated GIF
After the previous PR I was really exhausted and I needed another quick-win-PR that would boost my confidence (and so I can continue implementing the rest of the list). So I found a task for adding metadata that says “This GIF was created by Gifski”.
This task wasn’t something I needed but it sounded pretty straight-forward. Unfortunately, it wasn’t. I had to figure out what metadata type is supported by GIFs and what is the best way to do it in macOS. But in the end, it was still easier than the width/height one.
Removed “save panel” at the beginning of the conversion
Back to the big guns. Another problems I had with Gifski was that it wanted me to save the GIF before it was even created. I just wanted to be able to create a GIF, copy it and that’s it. No need for it to be sleeping on my desktop.
In terms of code this one was probably even harder than the width/height one. To achieve what we wanted, I had to completely rewrite the whole app view architecture to use separate view controllers instead of one view and showing/hiding things. And so this one also took about a month of work.
This is the last feature from my list that got into Gifski 2.0. I just wanted a quick way of trimming the video and make it a GIF.
What’s interesting in this part is that we had to scrap the view hierarchy to hide buttons and adjust it to our needs. Then use some KVO to get the trimming range. In the end this is something that is supposedly pretty common in AppKit development, but I’m still getting used to that. But the PR was a fast one this time and it closed the list of features I’ve managed to sneak into version 2. And this is the final product:
It was awesome to work on an app you use every day, especially in the open. Thanks again to Sindre for the guidance (and everything, really). I will for sure make another appearance on the Gifski PR tab. (Low-quality GIFs still needs to be done… ;-)