Description entry1300

To test my entry, please enable Insecure origins treated as secure in chrome://flags and add there. demo ๐Ÿ–ผ
I did't know, that Chrome allows using Web Crypto API only on https and localhost.

As noted in the review for the first stage of contest, WebSockets are important in terms of performance. So, I decided to rewrite Data layer (messaging with Telegram server). The new implementation is based on GramJS , but uses TypeScript (parts which are used frequently, covered by types). In addition to GramJS implementation, I almost completely replicated Telethon client , cutted some huge dependencies and placed short versions of them in src/vendor. Fixed some bugs, for example sending batch requests, some performance issues, such as slow AES decryption. Added cancellable file downloading (primarily for media streaming ). Despite the fact that almost the entire Telethon client is implemented, there was not enough time to use all of its features in view.

View layer in the first stage was simple as possible (in terms of abstractions). In the second stage, it would be difficult to use it, because of app dynamics. So, I wrote simple abstraction around WebComponents for convinient updating view, based on properties passed to component and wrote a simple function for rendering keyed lists, such as dialog list, messages and shared media.

Fixed issues from first stage review

  1. Countries search; For demo purposes, I added aliases for three countries. Now you can find these countries with any value from righthand array demo ๐Ÿ“น:

    "Russia": ["russian federation"],
    "United Kingdom": ["britain", "great britain", "u.k."],
    "United States": ["usa", "u.s.a."],

    For other countries, it's enough to add aliases to src/login/components/Select/countries.ts

  2. Loading after registration was fixed.

  3. Scrolling performance was debugged. I deleted filter: drop-shadow(...), because it requires good GPU. Also, I use contain: content; for chat messages, which also increased scrolling performance.
  4. Added group avatars.
  5. Pinned and muted chats are highlighted now.
  6. Messages are aligned as they should be.
  7. Line breaks are fixed.
  8. Messages are no longer duplicated when you click twice on dialog.

Key details


  1. I18n. Execute localStorage.setItem('lang', 'ru') (or any different language supported by Telegram Desktop) in console and reload the page. All texts, except file hover menu, are internationalized. ES ๐Ÿ–ผ, RU ๐Ÿ–ผ
  2. Performant slider. Mainly it was developed for media popup (but slider in popup isn't implemented). Anyway, it used in sidebars. It supports delayed deletion of DOM elements, for efficiently fast returning to the previous slide, and returning to the previous slide while current animation is playing. demo ๐Ÿ“น,
  3. AES and factorization executing in WebWorker.
  4. Factorization. Firstly, I copied leemon implementation from prime-factorization-benchmark . Then I investigated, that it's possible to improve performance with different algorithm and native BigInt. [1 ] [2 ]. So I used Brentโ€™s algorithm with BigInteger.js wrapper for fast factorization.
  5. Profile photos and small (< 500KB) files are cached in IndexedDB.
  6. Storybook with core components

Known Issues (specific issues described below each part)

  1. The most ridiculous oversight is 2 versions of Lottie.js in the bundle. It can easily lose 64 KB (gzipped) only by replacing: import lottie from 'lottie-web'; by import lottie from 'lottie-web/build/player/lottie_svg'; in src/login/components/Monkey/index.ts
    Visualization: before after
  2. There are some small features that I forgot to add to view, such as src/chat/utils/audioRecorder.ts

Dialog list

Service messages, highlighting entities demo ๐Ÿ–ผ, demo 2๐Ÿ–ผ
Typing info, updating unreaded count demo ๐Ÿ“น
Reordering demo ๐Ÿ“น

Known Issues

  1. Wrong date formatting (forgot to multiply date by 1000) demo ๐Ÿ–ผ
  2. When a new message is received, the dialog moves to top, not taking in account pinned dialogs demo ๐Ÿ“น
  3. Wrong online indicator z-index demo ๐Ÿ–ผ;


Supported messages wrappers:

Reply demo ๐Ÿ–ผ
Forward demo ๐Ÿ–ผ
Plain demo ๐Ÿ–ผ

Supported messages types:

Plain text demo ๐Ÿ–ผ
Voice demo ๐Ÿ–ผ
Audio demo ๐Ÿ–ผ
Stickers demo ๐Ÿ“น
Video demo ๐Ÿ“น
Images demo ๐Ÿ“น
Webpage demo ๐Ÿ–ผ
Polls demo ๐Ÿ“น
Files with download cancelling demo ๐Ÿ“น
Contacts demo ๐Ÿ–ผ
Buttons demo ๐Ÿ“น
Servise messages demo ๐Ÿ–ผ
Gifs (but without playing)

Additional notes:

  1. Stickers auto-pausing while they are not in viewport; demo ๐Ÿ“น
  2. Audio and video downloading cancellation; audio demo ๐Ÿ“น, video demo ๐Ÿ“น
  3. Voice seeking highlighting; demo ๐Ÿ“น

Known Issues

  1. Replies rerender with loaded data, only when receiving new messages or requesting new messages demo ๐Ÿ“น
  2. Round message has the wrong layout demo ๐Ÿ–ผ
  3. Polls that already have votes and does't have your vote are rendered incorrectly demo ๐Ÿ–ผ
  4. Some message wrappers have wrong border-radius. I implemented media clipping as in design storybook. But then, I investigated, that it kills scroll performance on devices with slow GPU, due to clip-path GPU rendering and disabled it at the last moment. I think it's possible to use clipping and make it performant, but some investigation required.
  5. Gifs that are actually mp4 are not playing because of wrong routing in src/chat/components/Chat/MessageContainer.ts:230
  6. Video popup closing only with a close button.

New messages

Wysiwyg demo ๐Ÿ“น
Emoji and stickers demo ๐Ÿ“น
Images uploading (with DnD);
supports album uploading, but without
displaying as album in message list
demo ๐Ÿ“น
Video uloading without previewing
Files uploading (with DnD) demo ๐Ÿ“น
Poll demo ๐Ÿ“น

Known Issues

  1. emoji/stickers popover closing only after selecting something. demo ๐Ÿ“น
  2. poll/file/image popup closing only on overlay clicking. demo ๐Ÿ“น
  3. there are only animated stickers in new message menu
  4. there is no uploading progress

Shared media

demo ๐Ÿ“น

Search for messages in chats

demo ๐Ÿ“น

Media streaming / downloading on demand

My biggest tragedy of this stage ๐Ÿ˜ญ

I've wasted an unacceptable amount of time (about 4 days) on implementing audio/video streaming, which included in the final result partially (only with audio/mpeg, audio/mpeg3, audio/mp3) and with flag. By default media plays after full download.

Stream player mainly located in src/chat/MediaPlayer/StreamDownlaoder.ts and src/chat/MediaPlayer/GapController.ts

While developing, I was testing it on segmented mp4 file and I thought that DocumentAttributeVideo.supports_streaming: true, denotes that video is segmented. But then, I realized, that it's not true, and all videos that I found in public channels was unsegmented. So I disabled it because I had no time and skills to implement remuxing.

But, it's available with a flag, because after downgrading to src/chat/MediaPlayer/PlainDownloader.ts, it was necessary to implement the same interface and there was no time to test it in depth. So it's not very stable, sometimes it can be necessary to seek audio to trigger playing.

You can test it with executing localStorage.setItem('use_streaming', '1') in console and reloading the page.

Demo ๐Ÿ“น (โš ๏ธvideo with sound, and it's a little bit noisy).

If maybe you have time and desire to test it on segmented video (as this ) without seeking, you can replace if (isMp3 && this.mediaStreamMime && use_streaming) { with if (true) { in src/chat/MediaPlayer/MediaPlayer.ts:133 and rebuild project with yarn install then yarn build. Demo ๐Ÿ“น