Insecure origins treated as secure
in chrome://flags
and add http://entry1300-jsround2.usercontest.com
there. demo ๐ผ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.
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
Loading after registration was fixed.
filter: drop-shadow(...)
, because it requires good GPU. Also, I use contain: content;
for chat messages, which also increased scrolling performance. 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 ๐ผ import lottie from 'lottie-web';
by import lottie from 'lottie-web/build/player/lottie_svg';
in src/login/components/Monkey/index.ts
src/chat/utils/audioRecorder.ts
Service messages, highlighting entities | demo ๐ผ, demo 2๐ผ |
Typing info, updating unreaded count | demo ๐น |
Reordering | demo ๐น |
Reply | demo ๐ผ |
Forward | demo ๐ผ |
Plain | demo ๐ผ |
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 ๐ผ |
Emoji | |
Gifs (but without playing) |
src/chat/components/Chat/MessageContainer.ts:230
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 ๐น |
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 ๐น