We received a complaint about the generation of multiple duplicate drafts for a single message. It was discovered that the likely cause of this was how we were handling clients that were frequently suspending/unsuspending, we would initiate a reload when we discovered this, and expect the `beforeunload` handler to save the draft. This behaved correctly, however, we would also save the compose state and fill it in via `preserve_state` in reload.js. The important detail here is that `preserve_state` would not encode and preserve the `draft_id` for the current message, partly because it had no way of knowing the `draft_id` of the draft... since we have not saved it yet, the `beforeunload` event happens after `preserve_state`. As such, performing any action that would trigger a draft to be saved, eg pressing Esc to close the compose box, would save a duplicate draft of the same message. To resolve the above bug, we (1) ensure that we call `drafts.update_draft()` in `preserve_state`, this returns a draft_id to us, which we (2) ensure that we encode as part of the url and (3) set on the `#composebox-textarea` as a `draft-id` data attribute, which we check the next time we try to save the draft, post reload. Note that this causes us to save the draft twice, once from preserve_state and then again from the `beforeunload` handler, but we do not add two drafts since the second update_draft call just edits the timestamp because it finds the `draft-id` data attribute on the `#composebox-textarea` set by the first call. |
||
|---|---|---|
| .github | ||
| .tx | ||
| .vscode | ||
| analytics | ||
| confirmation | ||
| corporate | ||
| docs | ||
| frontend_tests | ||
| locale | ||
| pgroonga | ||
| puppet | ||
| requirements | ||
| scripts | ||
| static | ||
| stubs | ||
| templates | ||
| tools | ||
| var/puppeteer | ||
| zerver | ||
| zilencer | ||
| zproject | ||
| .browserslistrc | ||
| .codecov.yml | ||
| .codespellignore | ||
| .editorconfig | ||
| .eslintignore | ||
| .eslintrc.json | ||
| .gitattributes | ||
| .gitignore | ||
| .gitlint | ||
| .mailmap | ||
| .npmignore | ||
| .prettierignore | ||
| .pyre_configuration | ||
| .sonarcloud.properties | ||
| .yarnrc | ||
| babel.config.js | ||
| CODE_OF_CONDUCT.md | ||
| CONTRIBUTING.md | ||
| Dockerfile-postgresql | ||
| LICENSE | ||
| manage.py | ||
| NOTICE | ||
| package.json | ||
| postcss.config.js | ||
| prettier.config.js | ||
| pyproject.toml | ||
| README.md | ||
| SECURITY.md | ||
| setup.cfg | ||
| stylelint.config.js | ||
| tsconfig.json | ||
| Vagrantfile | ||
| version.py | ||
| webpack.config.ts | ||
| yarn.lock | ||
Zulip overview
Zulip is a powerful, open source group chat application that combines the immediacy of real-time chat with the productivity benefits of threaded conversations. Zulip is used by open source projects, Fortune 500 companies, large standards bodies, and others who need a real-time chat system that allows users to easily process hundreds or thousands of messages a day. With over 700 contributors merging over 500 commits a month, Zulip is also the largest and fastest growing open source group chat project.
Getting started
Click on the appropriate link below. If nothing seems to apply, join us on the Zulip community server and tell us what's up!
You might be interested in:
-
Contributing code. Check out our guide for new contributors to get started. Zulip prides itself on maintaining a clean and well-tested codebase, and a stock of hundreds of beginner-friendly issues.
-
Contributing non-code. Report an issue, translate Zulip into your language, write for the Zulip blog, or give us feedback. We would love to hear from you, even if you're just trying the product out.
-
Supporting Zulip. Advocate for your organization to use Zulip, become a sponsor, write a review in the mobile app stores, or upvote Zulip on product comparison sites.
-
Checking Zulip out. The best way to see Zulip in action is to drop by the Zulip community server. We also recommend reading Zulip for open source, Zulip for companies, or Zulip for communities.
-
Running a Zulip server. Use a preconfigured DigitalOcean droplet, install Zulip directly, or use Zulip's experimental Docker image. Commercial support is available; see https://zulip.com/plans for details.
-
Using Zulip without setting up a server. https://zulip.com offers free and commercial hosting, including providing our paid plan for free to fellow open source projects.
-
Participating in outreach programs like Google Summer of Code.
You may also be interested in reading our blog or following us on Twitter. Zulip is distributed under the Apache 2.0 license.