The GSoC Experience - feat. Zulip
The success of Open Source Software rests on the collaboration and goodwill of its community.
I spent the last few months contributing to Zulip, an Open Source team collaboration tool, as a part of Google Summer of Code 2024. As the program comes to an end, here's a look back on what I did throughout the summer, and what I gained from this experience. I had only started contributing to Zulip around February this year, and at the time of writing this I have got 20 pull requests merged (though it is the quality of contributions that matters more).
What I ended up doing during the program was quite different from my initial proposal. I had proposed to address a few issues around Zulip's overlays for streams and user groups. My contributions prior to the application period included some pull requests around this subject, but I ended up gravitating towards an entirely different set of issues during the program. There's no one area where I contributed - rather my contributions were scattered throughout various areas like the compose box, right sidebar, modals and user settings interfaces.
Since I had roughly 2 months to contribute before the application deadline, I was a bit uncertain about my selection, and I am glad I was selected into the program. I have since contributed zealously.
Contributions
My contributions have chiefly been through pull requests. You can find all the pull requests which I worked on during this summer's GSoC here. Many of these made it into the latest 9.0
release.
Notable pull requests
Among the many pull requests that have been merged so far, there are a few which stand out because of how much I learned through them and how significant they were in making Zulip better.
#30071 - composebox_typeahead: Avoid generating broken links
This pull request closes the issue #19873, which is about a long standing bug in Zulip's typeahead system, where their special #**channel>topic**
syntax won't produce the desired link to the topic under certain conditions. The problem was that the markdown parser used by Zulip in the backend did not properly parse the *
and the #
if the channel or topic name itself contained some special characters. This issue was a request by the rust
community, which added to its charm in my eyes.
There had been a couple rounds of reviews with Greg, one of the core maintainers of Zulip. I ended up learning a lot about testing, since I had to make sure that my solution actually addressed most of the real-world occurrences of this bug.
#29302 - compose: Implement formatting of channels and topics on paste
This pull requests adds a new feature, described in #29136, where we transform links to a stream or topic to Zulip's #**channel>topic**
syntax. Since we'd have to parse user input, we had to first validate the link before trying to transform it. Most notably, I came to know about the use-mention distinction pointed out by Anders, another core maintainer. Simply put, we had to avoid transforming the pasted URL if the purpose of putting the link in the message there is not to use it, rather just to mention it. I had to add many tests here too, since this code was supposed to deal with raw user input, which can be wild.
After a while, I had to make a followup to this pull request to accommodate the newly introduced channel
operator in Zulip's URLs. (#30906).
#30646 - user_status: Live update user status icon in recent conversations.
This pull request fixes a very sneaky bug - where the user presence indicators won't update according to the actual presence status of the users, making the user wrongly believe that someone is online/offline. This is not as "cool" as the other two, but in this PR, I learned about mocking modules for testing, since the tests in this PR involved using zjquery
, Zulip's mocked version of the popular JQuery
, which is used for testing UI-related code. The zjquery
library provides minimal versions of most jQuery
DOM manipulation functions, and has a convenient system for letting you set up return values for more complex functions.
Modals and toasts
Zulip has its own set of components for rendering modals and toasts, so working on those issues was relatively easy.
#29725 - message_move: Show confirmation toast.
#29426 - popovers: Convert invite modal to tabbed format.
#29142 - Go to newly created stream.
Bug fixes
#29225 - Compose Box: Unresolve empty topics.
Very early on during the contribution period, I had reported a bug here. I had stumbled upon it while tinkering with the Zulip web app. Apparently, marking a topic with no messages unresolved resulted in an unhandled exception, since it is assumed that it is not possible to have empty topics, which is not the case. Though it is quite improbable to come up in real world usage, it is not a good idea to leave bugs unfixed. I had opened #29182 to report this, which was merged after a couple review rounds. This was worked on before the official start of the program.
#30464 - dropdown_widget: Fix bug in disable_for_spectators
.
This was a minor UI glitch where a spectator had access to the same options as a signed-in user in the dropdown menu, because the code missed the case when the user is a spectator. The fix involved adding the necessary guard clause to the option providing logic for the dropdown.
#30645 - composebox_typeahead: Fix checking whether messages can be sent.
This pull request fixes #30620, which was about a bug in uploading images. Apparently, when you uploaded an image, the sent message would sometimes contain a broken link to the image. Strangely enough, I narrowed the problem down to the code path responsible for sending messages on pressing the enter key. Apparently, there was an erroneous comparison to find out whether a message could be sent or not. The fix was changing just the CSS selector in the jQuery $
and checking if the element has a particular class (which decided whether the compose box was in a state of being able to send a message). Effectively, I changed only one line.
It has often happened that very grave-sounding issues turned out to be fixed by one-line changes!
As mentioned earlier, #30071 and #30646 are also quite noticeable bug fixes.
#30281 - overlay: Blur focused element while overlay is open.
This bug was discovered by me while working on #30645 (mentioned just above). The bug, simply put, was that the esc
key didn't close the picture overlay when the picture was opened from message edit preview. This happened due to the active element "stealing" the keyboard event before the code to hide the overlay could receive it. The fix was quite simple - blur the active element.
UI improvements
A set of pull requests deals with mere housekeeping work. However fancy you make an application, if the part of the application facing the user isn't appealing, no one would bother using your application. This makes UI-related code especially important, since that handles the most user-facing part of the application. The pull requests themselves are pretty small though.
#29436 - templates: Add internationalization.
This was one of my first pull requests, and back then, I wasn't well versed with how to write meaningful and succinct commit messages. I'd say that's a skill in itself. Anyway, this pull requests adds i18n
internationalization to some of the strings that missed it. All strings rendered in the UI in Zulip are internationalized. I stumbled upon the non-internationalized strings while exploring the codebase. This was worked on before the official start of the program.
#30394 - navbar: Tweak Combined feed description for spectators.
This PR just shows a different string for the combined feed description depending on whether the user is a spectator or not. This was a pretty minor change.
The following PRs involve pretty minor refactors:
#30033 - left_sidebar: Rename "more topics" to "show all topics"
#30369 - right_sidebar: Remove realm description for spectators.
#30933 - search: Improve text about searching public channels.
UX Improvements
#31085 - copy_and_paste: Paste text first unformatted and then formatted.
This PR builds upon the work done in #29302. It makes use of the functions added there to paste some text by retaining the source formatting and then enable the user to Ctrl+Z
to remove the formatting.
#29386 - settings: add tooltip to clarify invalid Jitsi URL - completion
This PR builds upon the work of an earlier PR which had been marked completion candidate
, i.e., pull requests which were abandoned on the way, but have made some progress. It brought #27594 to completion. This was worked on before the official start of the program.
#29412 - Go to newly created stream.
When a user creates a channel for the first time, they are taken to the newly created channel. Additionally, if this is the first time the user is creating a stream, an explanatory modal is shown. The changes were pretty simple, but the failing puppeteer tests as a result of adding a new modal were an annoyance.
I shortly had to follow up on this PR (#29412) when it was found that as a result of this PR, the user would always be redirected to the topic stream events
of the newly created channel. But non-anglophone organizations won't have the topic stream events
(with the English name). The solution was to just redirect to the newly created stream, but no particular topic. This was worked on before the official start of the program.
#29435 - compose: Unresolve empty topics followup
This was a followup to #29225, a minor improvement in UX. This PR makes it so that the Unresolve topic
button marks the topic as unresolved and re-narrows to the now unresolved topic if the topic is empty.
Other contributions
The org admins had paired up GSoC contributors in order to improve the quality of contributions and catch some errors before a core maintainer takes a look at the PR. I I was paired up with Pratik, and provided buddy reviews
to his PRs. I have also helped many new contributors with their first pull requests, and helped core contributors with their work. While tinkering around the Zulip web app, I discovered and reported various bugs, and resolved several of them myself.
Pull requests reviewed
Buddy reviews
Show action buttons only on hover for non sticky header. #31243
Defer computing last_edit_timestr until tooltip renders. #31199
Open topic status menu from followed topic icon in left sidebar #30313
Other reviews
compose: Fix flashing effect on trying to send message that's too long #30720
edit_stream_status: Removed the word channel from the stream_status #30808
Here is the thread where I posted my weekly check-ins to keep everyone informed of what I was working on each week.
The current state of things and future plans
Some of my biggest and most important pull requests are currently open and are actively being developed. Even though GSoC is nearly complete, I am going to stick around and get these pull requests merged. I have grown fond of the project, and plan to keep taking up new issues and fix bugs whenever I get time.
Here is a list of all the pull requests currently open.
Here are some of the most important pull requests which are currently open:
#30425 - Automatically detect the user’s time zone
This PR adds support for the web app to automatically detect the user's time zone using the new Intl.DateTimeFormat
API in JavaScript and offer to update the user profile time zone with it if it is found to be inconsistent with the browser time zone, and if the option to do so is enabled. This is strategically important, because if we are able to keep the user's profile time zone in sync with their geographic location, it would allow Zulip to render times in the time zone set in the user's profile, which will be done in a future PR.
#28974 - compose: Make it possible to split messages on delimiter.
This is my first pull request in Zulip and has undergone the most amount of review rounds. Most of what I know about the Zulip codebase comes from here. It implements a new feature where two blank lines in a message will cause the message to split into two parts before being sent. The big challenge here is to make sure that if one of the parts fails to send, the subsequent parts are also not sent and the unsent message content is restored in the compose box. This pull request awaits some review rounds and can be merged soon.
#30208 - Add support for a per-stream version of the "Default code block programming language".
Zulip uses a default programming language for syntax highlighting in markdown code blocks. Until now, each organization could choose the default which would be applied to all the messages. This pull request enables individual channels to have their own default language. This is particularly useful for developer communities which use Zulip, where generally each channel is used to talk about a particular area of the project and so the default code block language is different for each.
Lessons learned
My favorite part of participating in GSoC was finding myself grow in ways I hadn't even expected would happen through the program.
My communication skills have improved and I can now write succinct sentences explaining my work or any problem encountered while working on a particular code area. I can provide and respond well to code reviews as a result of participating in GSoC.
Having your code reviewed by some experienced professionals has its own benefits. Their feedback and advice transcends the particular piece of code they're reviewing and help you improve your personal projects as well as be a better team player. There is a lot to learn from their experience, and each review cycle has improved my debugging and programming skills in unimaginable ways.
There is a way to approach any open source project. You should first read the documentation and get acquainted with the project first, instead of directly jumping into code contributions and ending up making avoidable mistakes. Every project has a communication channel, and it is worth joining it and introducing yourself there.
Prior to GSoC, coding something up meant writing any kind of arcane code that would get me the desired result. This had the obvious drawback of me not being able to recognize and navigate through my own code after a while, and I'd have no idea why a particular block of code is written the way it is, since I would not add comments, or would write a poorly-worded one.
This changed very early while contributing to Zulip for GSoC, because the folks there are very particular about what kind of code they merge upstream. Getting the desired output is only a part of the requisite for them - they also require the contributor to have good reasoning for preferring a particular approach over others, and carefully choose the variable and function names, and write unit tests for the newly introduced logic. Their test suite would fail if even one newly introduced line in the codebase is not covered by tests, or is not permitted by the formatting and linting rules.
Needless to say, I will definitely apply next year, and in the meanwhile remain active in the Open Source space in general.
Conclusion
I could experience the beauty of Open Source while working with Zulip this summer. The development community is very welcoming and is really happy to onboard you with the project. Seeing code authored by me get merged upstream and used by thousands of users is a feeling I find hard to articulate well - it is to be experienced firsthand.
I am very grateful to my mentors Riken Shah and Shlok Patel who were there to guide me whenever I faced any kind of issue - both technical and non-technical.