Media is too big
VIEW IN TELEGRAM
#статья дня
Не так давно в чате канала проскочил вопрос, как правильно делать контейнеры, которые могут вылезать за визуальные границы.
Например, основной контент находится посредине и занимает в ширину 80-120 приятных для чтения глазу символов, а вот картинки хотелось бы разнести до краёв.
Техника называется full bleed. Я не знаю, как точно перевести.
Если посмотрите видео, то виден ещё один вариант использования, когда галерея выходит за пределы экрана лишь с одной стороны, но дальше тем не менее границы игнорирует.
Вот так: https://codepen.io/hexagoncircle/pen/gOWjwme
Альтернативный вариант: https://codepen.io/maartenbruggink/full/eYWjxae
Раньше такое делалось жонглированием полями, теперь же у нас есть гриды.
И у небезызвестного Джоша Комо есть статья как раз об этом: https://www.joshwcomeau.com/css/full-bleed/
Тем не менее, я рекомендую посмотреть приложенные кодпены, поскольку в них зоны грида именуются и становится понятнее, что к чему.
Всем full bleed, котаны!
#css #fullbleed #gallery #бородач
Не так давно в чате канала проскочил вопрос, как правильно делать контейнеры, которые могут вылезать за визуальные границы.
Например, основной контент находится посредине и занимает в ширину 80-120 приятных для чтения глазу символов, а вот картинки хотелось бы разнести до краёв.
Техника называется full bleed. Я не знаю, как точно перевести.
Если посмотрите видео, то виден ещё один вариант использования, когда галерея выходит за пределы экрана лишь с одной стороны, но дальше тем не менее границы игнорирует.
Вот так: https://codepen.io/hexagoncircle/pen/gOWjwme
Альтернативный вариант: https://codepen.io/maartenbruggink/full/eYWjxae
Раньше такое делалось жонглированием полями, теперь же у нас есть гриды.
И у небезызвестного Джоша Комо есть статья как раз об этом: https://www.joshwcomeau.com/css/full-bleed/
Тем не менее, я рекомендую посмотреть приложенные кодпены, поскольку в них зоны грида именуются и становится понятнее, что к чему.
Всем full bleed, котаны!
#css #fullbleed #gallery #бородач
1❤8🫡1
This media is not supported in your browser
VIEW IN TELEGRAM
#библиотека дня
Есть небольшая библиотека для undo/redo в JavaScript: async-history-stack.
Она интересна не тем, что «умеет откатывать состояние». Это как раз самый простой случай. Интереснее другое: в историю можно складывать действия, у которых есть асинхронные операции и побочные эффекты.
Например, пользователь удаляет картинку из галереи. В реальном приложении это может быть не один
А при undo надо сделать обратное: восстановить картинку, вернуть ссылку в состояние и снова открыть страницу этой картинки.
То есть в историю кладётся не снимок объекта, а переход туда-обратно. Благодаря этому undo/redo может быть не привязан к конкретному стору и нормально покрывает навигацию, RPC, работу с файлами и другие асинхронные штуки.
В библиотеке есть
Я набросал демо: галерея, удаление карточки, имитация асинхронного RPC, лог операций, undo/redo и восстановление маршрута. Ну и да, вместо обычных заглушек там процедурно генерируются SVG-паркеты, потому что почему бы и нет.
Ссылка на библиотеку:
https://github.com/kettanaito/async-history-stack
Демо:
https://codepen.io/editor/alinaki/pen/019f1263-8e38-73da-a864-9854b6093cee
Всем undo, котаны!
#history #undo #library #svg #tile
Есть небольшая библиотека для undo/redo в JavaScript: async-history-stack.
Она интересна не тем, что «умеет откатывать состояние». Это как раз самый простой случай. Интереснее другое: в историю можно складывать действия, у которых есть асинхронные операции и побочные эффекты.
Например, пользователь удаляет картинку из галереи. В реальном приложении это может быть не один
setState, а целая цепочка: уйти со страницы картинки, отправить запрос на удаление, убрать ссылку из локального состояния, обновить интерфейс.А при undo надо сделать обратное: восстановить картинку, вернуть ссылку в состояние и снова открыть страницу этой картинки.
async-history-stack предлагает описывать такие действия через push: функция сразу выполняет изменение и возвращает функцию, которая умеет это изменение откатить.
await historyStack.push(async () => {
await applyChanges()
return async () => {
await revertChanges()
}
})
То есть в историю кладётся не снимок объекта, а переход туда-обратно. Благодаря этому undo/redo может быть не привязан к конкретному стору и нормально покрывает навигацию, RPC, работу с файлами и другие асинхронные штуки.
В библиотеке есть
undo, redo, clear, size, timestamp, лимит истории, отмена через signal и merge, чтобы склеивать несколько изменений в одну запись. Например, когда много мелких действий должны откатываться одним undo.Я набросал демо: галерея, удаление карточки, имитация асинхронного RPC, лог операций, undo/redo и восстановление маршрута. Ну и да, вместо обычных заглушек там процедурно генерируются SVG-паркеты, потому что почему бы и нет.
Ссылка на библиотеку:
https://github.com/kettanaito/async-history-stack
Демо:
https://codepen.io/editor/alinaki/pen/019f1263-8e38-73da-a864-9854b6093cee
Всем undo, котаны!
#history #undo #library #svg #tile
❤12🔥4🫡1
#ссылка дня
Когда технологии стареют, это почти незаметно — пока не становится поздно. Вроде всё работает, но обновлений безопасности больше нет, старые зависимости перестают собираться, а новые версии библиотек ломают совместимость. Так проект постепенно превращается в мину замедленного действия.
Чтобы не попадать в такие ситуации, существует проект endoflife.date. Он показывает, когда заканчивается поддержка языков, библиотек, фреймворков и систем. Вводишь, например, Node.js или Ubuntu — и сразу видно, какие версии ещё живы, а какие пора обновлять. У них даже есть открытое API, так что можно встроить проверку прямо в CI и получать напоминания автоматически.
Но обновляться стоит с умом. Иногда новая версия приносит несовместимые изменения и кучу головной боли. Поэтому существуют LTS-версии — стабильные ветки, которые поддерживаются дольше обычных и меняются не так резко. На них удобно сидеть, если важна предсказуемость и стабильность.
Простая идея, но в долгосрочной перспективе экономит много времени и нервов.
#lts #support #бородач
Когда технологии стареют, это почти незаметно — пока не становится поздно. Вроде всё работает, но обновлений безопасности больше нет, старые зависимости перестают собираться, а новые версии библиотек ломают совместимость. Так проект постепенно превращается в мину замедленного действия.
Чтобы не попадать в такие ситуации, существует проект endoflife.date. Он показывает, когда заканчивается поддержка языков, библиотек, фреймворков и систем. Вводишь, например, Node.js или Ubuntu — и сразу видно, какие версии ещё живы, а какие пора обновлять. У них даже есть открытое API, так что можно встроить проверку прямо в CI и получать напоминания автоматически.
Но обновляться стоит с умом. Иногда новая версия приносит несовместимые изменения и кучу головной боли. Поэтому существуют LTS-версии — стабильные ветки, которые поддерживаются дольше обычных и меняются не так резко. На них удобно сидеть, если важна предсказуемость и стабильность.
Простая идея, но в долгосрочной перспективе экономит много времени и нервов.
#lts #support #бородач
❤5🫡2
#инструмент дня
Я уже один раз потерял ссылку на этот сервис, потому на правах закладки.
Встречайте, Cobalt: https://cobalt.tools/
Это сервис с открытым исходным кодом (GitHub), предназначенный для скачивания видео с большой кучи разнообразных сервисов: вк, ютуб, рутуб, тикток, твиттер, инстаграм и так далее и тому подобное. Полный список тут.
Никакой рекламы и занудства. Разве только UI на мобиле подглючивает — у меня не всегда правильно определяется безопасная зона "чёлки".
В общем, рекомендация.
#video #download #бородач
Я уже один раз потерял ссылку на этот сервис, потому на правах закладки.
Встречайте, Cobalt: https://cobalt.tools/
Это сервис с открытым исходным кодом (GitHub), предназначенный для скачивания видео с большой кучи разнообразных сервисов: вк, ютуб, рутуб, тикток, твиттер, инстаграм и так далее и тому подобное. Полный список тут.
Никакой рекламы и занудства. Разве только UI на мобиле подглючивает — у меня не всегда правильно определяется безопасная зона "чёлки".
В общем, рекомендация.
#video #download #бородач
❤11🔥4🤡2
Соскучились по рождественским календарям для программистов?
У CodeRun тут получился Advent of Code посреди лета, только с более олимпиадной составляющей: 15 задач, которые выкатываются пачками по 5 штук каждые 5 дней до 17 июля, общий зачёт и отдельные лидерборды по 11 языкам.
Главная механика — не просто «решил / не решил». Быстрый и экономный код даёт больше баллов, так что после первого accepted всё только начинается: можно переписывать решение, смотреть на время, память, крайние случаи и пытаться выжать из него ещё немного.
Я знаю людей, которые реально встают на час раньше, чтобы перед работой прорешать очередной LeetCode. Я не уверен, что сам готов к такой дисциплине, но понимаю, зачем они это делают: алгоритмы быстро ржавеют, если их не трогать. А здесь примерно тот же формат тренировки, только не в одиночном режиме и с таблицей, где сразу видно, насколько твоё «и так нормально» на самом деле нормально.
Призы тоже есть: топ-1 по каждому из 11 языков получает мерч-пак CodeRun, топ-3 общего зачёта — коллекционный лего-набор, а топ-200 общего зачёта — скип контеста и пробное интервью в Яндекс.
Последний пункт, кстати, довольно практичный. Даже если не относиться к этому как к спорту, такой челлендж можно использовать как понятный способ размяться перед алгоритмическими интервью: задачи, ограничения, дедлайн, сравнение решений и болезненное напоминание, что O(n²) иногда всё ещё O(n²).
У CodeRun тут получился Advent of Code посреди лета, только с более олимпиадной составляющей: 15 задач, которые выкатываются пачками по 5 штук каждые 5 дней до 17 июля, общий зачёт и отдельные лидерборды по 11 языкам.
Главная механика — не просто «решил / не решил». Быстрый и экономный код даёт больше баллов, так что после первого accepted всё только начинается: можно переписывать решение, смотреть на время, память, крайние случаи и пытаться выжать из него ещё немного.
Я знаю людей, которые реально встают на час раньше, чтобы перед работой прорешать очередной LeetCode. Я не уверен, что сам готов к такой дисциплине, но понимаю, зачем они это делают: алгоритмы быстро ржавеют, если их не трогать. А здесь примерно тот же формат тренировки, только не в одиночном режиме и с таблицей, где сразу видно, насколько твоё «и так нормально» на самом деле нормально.
Призы тоже есть: топ-1 по каждому из 11 языков получает мерч-пак CodeRun, топ-3 общего зачёта — коллекционный лего-набор, а топ-200 общего зачёта — скип контеста и пробное интервью в Яндекс.
Последний пункт, кстати, довольно практичный. Даже если не относиться к этому как к спорту, такой челлендж можно использовать как понятный способ размяться перед алгоритмическими интервью: задачи, ограничения, дедлайн, сравнение решений и болезненное напоминание, что O(n²) иногда всё ещё O(n²).
CodeRun
CodeRun Summer Challenge // CodeRun
CodeRun Summer Challenge. Решай рейтинговые задачи по программированию, вступай в борьбу с другими участниками. Стань лучшим и получи призы — сертификат, подарки и возможность попасть на работу в Яндекс.
🔥3❤2👍2
Media is too big
VIEW IN TELEGRAM
#фишка дня
Когда я наткнулся на этот твит в обсуждении утилиты работы с цветами Андрея Ситника, я не сразу примерил его на себя. Но, как оказалось, стоило бы.
Итак, давайте поясню для тех, кто по ссылкам не ходит.
В азиатских иероглифических языках почти весь ввод с клавиатуры происходит в аккордном режиме или же в режиме т. н. композитинга, общее название — Input Method Editor.
TL;DR: На экране всплывает окошко с символами или их группами и пользователь может что-то выбрать.
На каких-то ОС оно вызывается долгим зажатием клавиши, где-то — по хоткею, а где-то — автоматически и сразу.
Так вот, одно дело азиатские языки (я очень рекомендую посмотреть сам твит), а другое — разные европейские. И речь о диакритических знаках: умляуты, акуты, ударения, птички и шапочки.
Так вот, я не имею финской раскладки, потому буквы ä, å и ö ввожу как раз в режиме композитинга, долгим зажатием «материнской» клавиши.
Собственно, так база для азиатских языков проникла и в мою жизнь.
Кстати, выбор Emoji из всплывающего окошка — туда же.
В JavaScript-событиях для этого режима имеется флаг isComposing. Поэтому если вы, как и я в примере на видео, решили реализовать ввод групп символов подобным образом — циклически перебирая поля ввода — стоит об этом подумать :)
Собственно, давайте и пример: https://codepen.io/alinaki/pen/MWMpdvO?editors=1010
И напишите в комментариях, как вы решаете проблему редкого ввода букв с диакритикой у себя в системе. Например, я не помню, как это происходит в Windows, а в Linux я использую клавишу Compose, она работает чуть иначе.
#javascript #composing #event #бородач
Когда я наткнулся на этот твит в обсуждении утилиты работы с цветами Андрея Ситника, я не сразу примерил его на себя. Но, как оказалось, стоило бы.
Итак, давайте поясню для тех, кто по ссылкам не ходит.
В азиатских иероглифических языках почти весь ввод с клавиатуры происходит в аккордном режиме или же в режиме т. н. композитинга, общее название — Input Method Editor.
TL;DR: На экране всплывает окошко с символами или их группами и пользователь может что-то выбрать.
На каких-то ОС оно вызывается долгим зажатием клавиши, где-то — по хоткею, а где-то — автоматически и сразу.
Так вот, одно дело азиатские языки (я очень рекомендую посмотреть сам твит), а другое — разные европейские. И речь о диакритических знаках: умляуты, акуты, ударения, птички и шапочки.
Так вот, я не имею финской раскладки, потому буквы ä, å и ö ввожу как раз в режиме композитинга, долгим зажатием «материнской» клавиши.
Собственно, так база для азиатских языков проникла и в мою жизнь.
Кстати, выбор Emoji из всплывающего окошка — туда же.
В JavaScript-событиях для этого режима имеется флаг isComposing. Поэтому если вы, как и я в примере на видео, решили реализовать ввод групп символов подобным образом — циклически перебирая поля ввода — стоит об этом подумать :)
Собственно, давайте и пример: https://codepen.io/alinaki/pen/MWMpdvO?editors=1010
И напишите в комментариях, как вы решаете проблему редкого ввода букв с диакритикой у себя в системе. Например, я не помню, как это происходит в Windows, а в Linux я использую клавишу Compose, она работает чуть иначе.
#javascript #composing #event #бородач
🔥3
Дедлайны горят, а твои глаза уже нет. Что делать, если ты за#бался и хочется просто залипать в телефоне?
И вроде понимаешь, что НАДО, но от этого еще больше сопротивление.
Если близкие думают, что ты зажрался, а тебе и самому от себя уже тошно, но как себя взбодрить – непонятно, советую посмотреть вот что: https://t.me/Manifestans
Ты 100% себя узнаешь, а значит 100% получишь пользу от того, что там увидишь!
Если ты еще не собрал пожитки и не ушел отшельником в лес – есть шанс тебя оживить и вернуть эмоции и интерес к жизни.
Кликай сюда и начинай приходить в себя.
И вроде понимаешь, что НАДО, но от этого еще больше сопротивление.
Если близкие думают, что ты зажрался, а тебе и самому от себя уже тошно, но как себя взбодрить – непонятно, советую посмотреть вот что: https://t.me/Manifestans
Ты 100% себя узнаешь, а значит 100% получишь пользу от того, что там увидишь!
Если ты еще не собрал пожитки и не ушел отшельником в лес – есть шанс тебя оживить и вернуть эмоции и интерес к жизни.
Кликай сюда и начинай приходить в себя.
❤1👍1🔥1🤡1
#инструмент дня
Появился Nub — новый «всё-в-одном» тулкит для JavaScript. Название, конечно, опасное: любой пост про него автоматически звучит как обращение к аудитории.
GitHub: https://github.com/nubjs/nub
Site: https://nubjs.com/
Кто уже догадался, откуда у названия ноги растут?
Да, оттуда.
Но есть нюанс: Nub не пытается заменить Node.js.
Смысл такой: дать разработчику всё приятное, что люди обычно хвалят в Bun — быстрый запуск, TypeScript из коробки, меньше зоопарка CLI, — но оставить выполнение кода на старом добром Node.js.
Nub — это один Rust-бинарник поверх обычного Node.js. Он умеет:
— запускать TypeScript/TSX/JSX без отдельного build step
— автоматически подхватывать tsconfig paths
— грузить .env
— импортировать YAML/TOML/JSONC/JSON5
— работать как быстрый runner для package.json scripts
— заменять npx/pnpm exec
— ставить зависимости
— управлять версиями Node
— делать watch mode
То есть вместо набора из
Главный selling point не «мы быстрее всех, потому что переписали мир на Zig, потом по-ковбойски переписали его на Rust с помощью ИИ, а теперь давайте все сделаем вид, что это нормальный жизненный цикл инфраструктурного рантайма».
Код в итоге выполняет обычный Node.js. Nub просто добавляет слой удобства: транспиляцию через oxc, хуки резолвинга, полифиллы и быстрые команды вокруг проекта.
На сайте, конечно, бенчмарки красивые:
Плюс отдельно упирают в supply-chain безопасность: build scripts по умолчанию не запускаются, свежие подозрительные релизы можно придерживать, вредоносные пакеты проверяются через OSV.
Выглядит как очень понятная реакция на последние годы JS tooling: всем понравилось, что Bun быстрый и удобный, но не всем хочется тащить в прод ещё один почти-Node, который иногда внезапно оказывается «почти», а потом ещё и внезапно оказывается почти переписанным.
Nub говорит: а давайте оставим Node, но перестанем страдать от того, что вокруг него исторически вырос целый огород одноразовых CLI.
Пока штука свежая, я бы не тащил её сразу в критичный CI без проверки, но для внутренних тулов, dev-скриптов и монореп — очень интересно.
#node #bun #typescript #oxc #rust
Появился Nub — новый «всё-в-одном» тулкит для JavaScript. Название, конечно, опасное: любой пост про него автоматически звучит как обращение к аудитории.
GitHub: https://github.com/nubjs/nub
Site: https://nubjs.com/
Кто уже догадался, откуда у названия ноги растут?
Да, оттуда.
Но есть нюанс: Nub не пытается заменить Node.js.
Смысл такой: дать разработчику всё приятное, что люди обычно хвалят в Bun — быстрый запуск, TypeScript из коробки, меньше зоопарка CLI, — но оставить выполнение кода на старом добром Node.js.
Nub — это один Rust-бинарник поверх обычного Node.js. Он умеет:
— запускать TypeScript/TSX/JSX без отдельного build step
— автоматически подхватывать tsconfig paths
— грузить .env
— импортировать YAML/TOML/JSONC/JSON5
— работать как быстрый runner для package.json scripts
— заменять npx/pnpm exec
— ставить зависимости
— управлять версиями Node
— делать watch mode
То есть вместо набора из
tsx, ts-node, dotenv, tsconfig-paths, nvm, pnpm run, npx и пары заклинаний из README вашего монорепо — один nub.Главный selling point не «мы быстрее всех, потому что переписали мир на Zig, потом по-ковбойски переписали его на Rust с помощью ИИ, а теперь давайте все сделаем вид, что это нормальный жизненный цикл инфраструктурного рантайма».
Код в итоге выполняет обычный Node.js. Nub просто добавляет слой удобства: транспиляцию через oxc, хуки резолвинга, полифиллы и быстрые команды вокруг проекта.
На сайте, конечно, бенчмарки красивые:
nub run — сильно быстрее npm run / pnpm runnubx — сильно быстрее npxnub install — быстрее pnpm и, по их тестам, даже чуть быстрее bun installnub index.ts — примерно как обычный node по старту и быстрее tsxПлюс отдельно упирают в supply-chain безопасность: build scripts по умолчанию не запускаются, свежие подозрительные релизы можно придерживать, вредоносные пакеты проверяются через OSV.
Выглядит как очень понятная реакция на последние годы JS tooling: всем понравилось, что Bun быстрый и удобный, но не всем хочется тащить в прод ещё один почти-Node, который иногда внезапно оказывается «почти», а потом ещё и внезапно оказывается почти переписанным.
Nub говорит: а давайте оставим Node, но перестанем страдать от того, что вокруг него исторически вырос целый огород одноразовых CLI.
Пока штука свежая, я бы не тащил её сразу в критичный CI без проверки, но для внутренних тулов, dev-скриптов и монореп — очень интересно.
#node #bun #typescript #oxc #rust
👍11🔥3🫡2
#уязвимость дня
У браузеров новый жанр: сайт может косвенно смотреть, что вы делаете на компьютере, по задержкам SSD.
Исследователи из Graz University of Technology показали атаку FROST. Схема примерно такая: сайт заводит себе большой файл в локальном хранилище браузера через Origin Private File System и постоянно читает его маленькими кусками. Пока SSD занят только этим — задержки одни. Открыли другой сайт или приложение — нагрузка на диск изменилась, задержки тоже. По этим микросдвигам можно попытаться понять, что ещё запущено на компьютере.
В эксперименте сайты угадывались примерно с точностью 89%, приложения — около 96%.
Отдельно хороша реакция браузеров. По пересказу Ars Technica и Tom’s Hardware, Google не считает fingerprinting уязвимостью безопасности. Apple, судя по статье, отправила в сторону будущих privacy-защит. Mozilla проблему признала, но фикса пока нет.
Получилось как обычно: API добавляли для нормальных вещей — локального хранения, офлайн-работы, быстрых приложений. А потом выяснилось, что из этого же API можно собрать ещё один датчик состояния машины.
Закрывать лишние вкладки теперь можно не из-за RAM, а для своей же приватности.
#ssd #vulnerability
У браузеров новый жанр: сайт может косвенно смотреть, что вы делаете на компьютере, по задержкам SSD.
Исследователи из Graz University of Technology показали атаку FROST. Схема примерно такая: сайт заводит себе большой файл в локальном хранилище браузера через Origin Private File System и постоянно читает его маленькими кусками. Пока SSD занят только этим — задержки одни. Открыли другой сайт или приложение — нагрузка на диск изменилась, задержки тоже. По этим микросдвигам можно попытаться понять, что ещё запущено на компьютере.
В эксперименте сайты угадывались примерно с точностью 89%, приложения — около 96%.
Отдельно хороша реакция браузеров. По пересказу Ars Technica и Tom’s Hardware, Google не считает fingerprinting уязвимостью безопасности. Apple, судя по статье, отправила в сторону будущих privacy-защит. Mozilla проблему признала, но фикса пока нет.
Получилось как обычно: API добавляли для нормальных вещей — локального хранения, офлайн-работы, быстрых приложений. А потом выяснилось, что из этого же API можно собрать ещё один датчик состояния машины.
Закрывать лишние вкладки теперь можно не из-за RAM, а для своей же приватности.
#ssd #vulnerability
❤7👎1👏1
#игра дня
Среда — это маленькая пятница! Время сыграть в... Carmageddon!
Его как Никита Аксёнов портировал в браузер :) Точнее, не оригинальную игру, а движок Deathrace, целью которого является реверс-инжиниринг оригинального движка.
Естественно, чтобы играть локально нужны ассеты игры, но по ссылке — всё работает прекрасно: https://retrogamescenter.ru/ports/carmaweb/index.html
В отличие от нативного Carmageddon, управление тут перенесено на стрелки, а не работает на Numpad. Я всё ещё помню, насколько это было ублюдочно.
Я стар. Я суперстар.
Жаль, мультиплеер не пашет пока :)
#game #old
Среда — это маленькая пятница! Время сыграть в... Carmageddon!
Его как Никита Аксёнов портировал в браузер :) Точнее, не оригинальную игру, а движок Deathrace, целью которого является реверс-инжиниринг оригинального движка.
Естественно, чтобы играть локально нужны ассеты игры, но по ссылке — всё работает прекрасно: https://retrogamescenter.ru/ports/carmaweb/index.html
В отличие от нативного Carmageddon, управление тут перенесено на стрелки, а не работает на Numpad. Я всё ещё помню, насколько это было ублюдочно.
Я стар. Я суперстар.
Жаль, мультиплеер не пашет пока :)
#game #old
❤5
9 июля(в четверг!) в 19:00 по мск приходи онлайн на открытое собеседование, чтобы посмотреть на настоящее интервью на Middle Frontend-разработчика.
Как это будет:
Это бесплатно. Эфир проходит в рамках менторской программы от ШОРТКАТ для Frontend-разработчиков, которые хотят повысить свой грейд, ЗП и прокачать скиллы.
Переходи в нашего бота, чтобы получить ссылку на эфир → @shortcut_front_bot
Реклама.
О рекламодателе.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤1👎1