现象:对一条历史消息点"回复",输入含链接的文本触发风控弹窗后点"取消发送" (预览条正确保留,这是既有修复的正常行为),不改动文本再次点发送、这次 在弹窗里点"我已知晓,继续发送"——最终发出的消息里,正文被写了两遍(引用 块本身只有一份),例如输入"排查根因4 xxx",实际发出"[引用] 排查根因4 xxx排查根因4 xxx"。第三次发送同一条文本会变成正文三遍,以此类推。 根因:sendMessage()给回复拼接引用内容时写的是 `Drafty.append(Drafty.sanitizeEntities(this.state.reply.content), msg)`。 Drafty.sanitizeEntities和Drafty.append(umd/tinode.dev.js,第三方SDK, 未改动)都会原地修改第一个参数并把同一个引用返回,从不做深拷贝—— sanitizeEntities内部直接改content.ent[i]再return content,append直接 first.txt+=、first.fmt.push()再return first。这里把this.state.reply.content (React state里"正在回复"预览条依赖的同一个对象)原样传进去,等于每次 点发送都会把当次输入的正文永久焊死在这条回复引用的原始内容上。 平时这个副作用不可见:一次成功发送后handleCancelReply()马上清掉 state.reply,被污染的对象跟着一起扔掉。但URL风控检查会把真正调用 doSend()(进而调用这行代码)的时机推迟到弹窗resolve之后,"取消发送" 按现有修复(a964d51b)刻意不清空state.reply以保留预览条——这就让 被污染的引用内容留了下来,等下一次点发送时,同一个已经被污染的对象 再被追加一次,正文因此重复。 修复:拼接前对this.state.reply.content做一次深拷贝,让两个SDK方法的 原地修改只作用于用完即扔的副本,不管sendMessage对同一条还没清空的 回复调用多少次都不影响原始状态。 验证:真实浏览器操作,对消息点回复,输入带链接文本发送触发风控弹窗, 点"取消发送"(预览条与文本保留正常),不改文本再次发送并这次确认 "继续发送"——发出的消息引用块和正文都只出现一次,不再重复。 第14+轮最小粒度测试 Ch4 发现(回复+风控弹窗联动场景,紧邻已知修复 a964d51b验证时发现)。 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Tinode Web
Briefing
Single-page web chat application for Tinode. The app is built on React. The Tinode javascript SDK has no external dependencies. Overall, it's a lot like open source WhatsApp or Telegram web apps.
Although the app is generally usable, keep in mind that this is work in progress. Some bugs probably exist, some features are missing. The app was tested in the latest Chrome & Firefox only. NPM package is available.
Try possibly newer or older version live at https://sandbox.tinode.co/.
For demo access and other instructions see here.
Installing and running
This is NOT a standalone app, this is just a frontend, a client. It requires a backend. See installation instructions. See instructions for enabling push notifications.
Getting support
- Read client-side and server-side API documentation.
- For support, general questions, discussions post to https://groups.google.com/d/forum/tinode.
- For bugs and feature requests open an issue.
- Use https://tinode.co/contact for commercial inquiries.
Helping out
- If you appreciate our work, please help spread the word! Sharing on Reddit, HN, and other communities helps more than you think.
- Consider buying paid support: https://tinode.co/support.html
- If you are a software developer, send us your pull requests with bug fixes and new features.
- If you use the app and discover bugs or missing features, let us know by filing bug reports and feature requests. Vote for existing feature requests you find most valuable.
- If you speak a language other than English, translate the apps into your language. You may also review and improve existing translations.
- If you are a UI/UX expert, help us polish the app UI.
- Use it: install it for your colleagues or friends at work or at home.
Internationalization
The app is fully internationalized using React-Intl. The UI language is selected automatically from the language specified by the browser. A specific language can be forced by adding #?hl=XX parameter to the URL when starting the app, e.g. https://web.tinode.co/#?hl=fr.
The app is currently available in the following languages:
- English - default
- Arabic
- Chinese simplified
- Chinese traditional
- French
- German
- Italian
- Korean
- Romanian
- Russian
- Spanish
- Thai
- Ukrainian
- Vietnamese
More translations are welcome. See instructions.
Not done yet
- End-to-End encryption.
- Emoji support is weak.
- Mentions, hashtags.
- Previews not generated for links and docs.
- Location and contact sharing.
- Recording video messages.
Other
- Demo avatars and some other graphics are from https://www.pexels.com/ under CC0 license.
- Background patterns from http://subtlepatterns.com/, commercial and non-commercial use allowed with attribution.
- Fonts and icons from Google under license which permits commercial and non-commercial use.
- Push notifications built with https://firebase.google.com/.






