Telegram Web Link
#проект дня

Не так давно проходила выставка в Смитсоновском музее американского искусства и на ней была представлена целая стена из ЭЛТ-телевизоров. Почему-то на это обратил внимание твиттер FPGA Gaming (я просто очень эмуляторы люблю).

И я подумал: «А чем я хуже?» Тем более, что лет 8 назад мы делали проект для одного энергетического напитка, в котором был буквально ровно похожая идея. И они решили повторить её и на своём сайте.

Сайт уже давно поменялся, но подготовленные к проекту изображения у меня остались. По прошествии такого количества времени — зачем пропадать красоте, верно?

Итак, вашему вниманию совершенно бесполезная, но такая забавная, пирамида из телевизоров: https://bekharsky.github.io/tvs/

На айфонах не открывайте ссылку пока, я позже переделаю загрузку видео :) С автоматическим проигрыванием видео в мобильном Safari всегда были проблемы.

Что же понадобилось для сборки?

Первым делом, естественно, нужно собрать кадры аналоговых глюков воедино, чтобы получилось несколько видео. Их и будем запускать:


ffmpeg -f image2 -r 25 -pattern_type glob -i '*.png' -vcodec libx264 -crf 22 video.mp4


После чего подготовим наш список видео и подумаем: а что нужно сделать-то?

Простой запуск всех видео разом даёт интересный, но быстро надоедающий результат. Видеть подобное, например, на заставке — банально скучно. Очевидно, нужно запускать видео рандомно.

А лучше не просто рандомно, а ещё и сами видео на телевизорах менять!

И тут нам помогут вечные друзья: raf и ref.

В смысле, requestAnimationFrame и reference в React. А не то, что вы подумали.

С помощью requestAnimationFrame добиваемся рандомного запуска в пределах от секунды до трёх, а с помощью массива рефов — просто подменяем src видео в цикле.

Кстати, забавный трюк:


<video
ref={(el) => (videoRefs.current[i] = el)}
className="video"
key={`video-${i}`}
src={name}
loop
muted
/>


Проп ref представлен в виде функции, ref callback:

ref={(el) => (videoRefs.current[i] = el)}


В этот момент React присваивает ссылку на ноду элементу массива. Это хорошо описано в документации и не только экономит число ссылок и использований useRef, но и позволяет динамически этим списком управлять.

Ну и осталось — а осталось только запустить несколько рандомных видео и вовремя остановить их.

Повторю, на айфонах не всё так просто, поэтому запуск видео там я отложил на потом.

Исходный код, как всегда, доступен: https://github.com/bekharsky/tvs

Кстати, чтобы сделать эффекты ещё более интересными, можно не в видео их собирать, а перебирать картинки на лету. Что даст абсолютный контроль над кадрами. Чем, наверное, и займёмся вскорости.

Задавайте ваши ответы, котаны :)

#react #art #ref
#инструмент дня

Даже два. И оба для работы с SVG.

Одной из сильно раздражающих проблем при работе с SVG является, как ни странно, сложность кропа. Ну, обрезки полей, whitespace.

Почему? Ну, потому что многие редакторы (Inksape тот же) делают просто изменение viewBox или ещё трансформами подгоняют кривые.

Работает ли это? Ну, в целом, да. Правда, приносит с собой неожиданности вроде замыленных границ, сложности с расчётом анимаций и внезапном отсутствии поддержки в различных других редакторах.

Гарантии, что любой SVG загрузится в любом редакторе и так в принципе нет. Стандарт слишком большой, мусора напихать можно слишком много.

Так вот, к чему это я. Точно, к обрезке.

Раз: https://svgcrop.com/
Два: http://editor.method.ac/

Первая утилита обрезает по viewBox. А вот второй редактор — в него можно загрузить SVG с применёнными трансформациями сдвига, выделить и выбрать в меню Object 👉 Reorient path, что перепишет кривые с учётом трансформаций.

Вспомню, как это делать в Inkscape — напишу 🙂

#svg #crop #бородач
#статья дня

Встроенная в браузеры функция выполнения HTTP-запросов fetch — штука достаточно кондовая.

Топорная, если хотите.

Ошибки бросает только на ошибках сервера или соединения (404 — не ошибка), нужно самому формировать заголовки запроса, даже самому формировать строку с JSON или данными формы в urlencode...

Очень многие вместо неё как использовали, так и продолжают использовать тот же axios, кто-то берёт разные иные обёртки, как Tanstack Query aka React Query, а кто-то один раз написал свою реализацию обработки ошибок и прочего бойлерплейта — и забыл.

Так вот, позвольте вам напомнить, что таки есть причина для этой кондовости. По-порядку.

Чаще всего получение данных сводится к разрешению двух промисов:


let response = await fetch("/some-url")
let myObject = await response.json()


Но почему? Почему fetch сразу данные-то не отдаёт? К чему эти танцы?

Так вот, всё дело в том, что мир не ограничивается гонянием джисонов по сети. Возможно, нужен просто текст. Возможно, решение нужно принять ещё до того, как заняться обработкой тела запроса. Возможно, бинарные данные. А, возможно, данные кусками или потоком — stream — который можно прервать в любой момент:


async function readData(url) {
const response = await fetch(url);
for await (const chunk of response.body) {
// Do something with each "chunk"
}
// Exit when done
}


В любом случае, так или иначе, собственно, fetch возвращает промис с результатами запроса, а уже потом — дело за вами, как его обработать.

И вот хороший пример — от Тома Стивена: https://tomontheinternet.com/why-two-awaits/

В статье он даёт ссылку на код с демонстрацией: https://github.com/tom-on-the-internet/fetch-demonstration

Ну и я решил и в песочницу этот код запихать, для наглядности и понимания процесса: https://codesandbox.io/p/devbox/mvhrgz

Так что, возможно, fetch хорош таким, какой он есть. Универсальным.

#fetch #http #stream
#фишка дня

Думаю, все знают про :nth-child, :nth-last-child. А также про :nth-of-type и :nth-last-of-type.

Что в них самое раздражающее?

Кто сказал нумерация с единицы? Иди в свой Си.

Конечно же это неочевидность, а когда-то и невозможность, выбора элементов по классу или иному атрибуту!

Да-да, :nth-of-type выбирает по тегу, даже не по классу. Так что же делать?

А делать вот что: уже пару лет с нами присутствует синтаксис-дополнение к nth-child. И называется он of S.

Выглядит так:

:nth-child(An+B [of S]?)
:nth-last-child(An+B [of S]?)


А применяется так:

:nth-child(2 of .highlight)
:nth-child(even of :not([hidden]))


Первый выберет второе появление элемента с классом .highlight, а второй — все чётные не скрытые элементы.

Подробнее — в блоге разработчиков Chrome.

#css #nth #selector
#фишка дня

От Темани Афифа aka CSS Challenges! Он нам уже много крутого подарил :)

Что делать, если нужно несколько кнопок одной ширины? В смысле, подстраивающихся под самую широкую, а не просто заданной.

Использовать гриды, конечно!

Как-то так:


.container {
display: inline grid;
grid-auto-flow: column;
grid-auto-columns: 1fr;
}


Подробнее: https://css-tip.com/equal-width-button/

#css #button #grid
This media is not supported in your browser
VIEW IN TELEGRAM
#фишка дня

Надоело искать гит-бранчи в бесконечном их списке в консоли?

Это всё потому что они сортируются по алфавиту. Что вообще далеко не всегда удобно. Точнее, это удобно только когда название ветки начинается с номера тикета.

Но, опять же, а если проектов несколько?..

Решение очевидно: сортировать бранчи по дате изменения!

Для чего нужен вот этот конфиг:

git config --global branch.sort -committerdate


И всё, бранчи отсортируются по дате последнего коммита. Сильно удобнее, кмк.

Автор видео с примером — Бен Холмс.

P. S. сейчас евангелисты GUI для Git придут мне напихивать :)

#git #feature
#инструмент дня

Наткнулся на тред Андрея Романова про мониторинг крашей. Публикуется с изменениями.

Не тех крашей, что с чёлкой, а крашей браузера. Падений на ровном месте.

Очевидно, при падении ваш код перестанет выполняться, поэтому стандартные методы здесь не работают.

Зато Chrome нарисует симпатичную графику, очень полезно.

Однако, есть экспериментальный Reporting API, который позволяет браузеру отправлять отчёты о сбоях, нарушениях политик безопасности и использовании устаревших функций:
🔗 Спецификация API: https://w3c.github.io/reporting/
🔗 Обзор на Chrome for Developers: https://developer.chrome.com/docs/capabilities/web-apis/reporting-api

Reporting API предоставляет два способа получения отчётов:

📌 Глобальный класс ReportingObserver — позволяет подписаться на предупреждения и обрабатывать их в JavaScript. Он не фиксирует падения, так как работает на клиенте.
📌 HTTP-заголовок Reporting-Endpoints — задаёт серверные эндпойнты, на которые браузер отправляет отчёты. Этот метод покрывает все виды ошибок, включая падения вкладки.

Хотя API остаётся нестабильным и реализован не во всех браузерах, у него нет аналогов. Например, Figma уже использует его для мониторинга крашей браузера:
🔗 Разбор использования в Figma: https://neugierig.org/software/blog/2023/01/browser-crashes.html

Лучше так, чем совсем не иметь :)

Впрочем, отличным вариантом остаётся и пульс aka heartbeat с выставлением флага. Если приложение завершилось адекватно — флаг помечается как закрытый, а по пути можно собрать дополнительных данных.

Ну и, как минимум, средства вроде Sentry и Datadog отлично справляются с трекингом ошибок, по которым тоже можно косвенно понять причину падения.

#web #crash #report
Фронтенд — это не только натянуть верстку и подключить API. Чем глубже вникаешь в технологии, тем больше вопросов возникает. Как браузер работает с памятью? Почему одни операции быстрее других? Как устроены алгоритмы, которые ты используешь, даже не задумываясь?

Я уже некоторое время подписан на канал Андрея Кобеца (www.tg-me.com/kobezzza_channel). Андрей — инженер с 20-летним опытом, 10 лет руководил фронтендом в Яндексе, а теперь делится знаниями с разработчиками, которые хотят расти не только в грейде, но и в понимании технологий.

Что у него интересного:
🔹 Разборы концепций — «Передача по ссылке и по значению», «Как интерпретируется код», «Потоки и память в JS»
🔹 Как алгоритмы помогают фронтендеру — реальные кейсы, без теории ради теории
🔹 Карьерные советы — что делать, чтобы зарабатывать больше, но не превращаться в менеджера
🔹 Нестандартные темы — например, как устроена безопасность по памяти или почему в Unix «всё есть файл»

Читается легко, но плотно. Если интересно не просто писать код, а понимать, как он работает под капотом, рекомендую заглянуть:
👉 www.tg-me.com/kobezzza_channel

Реклама. ИП Кобец Д.Д. ОГРНИП: 322237500264561 erid: 2VtzqwmTdAW
This media is not supported in your browser
VIEW IN TELEGRAM
#инструмент дня

Как сконвертировать что угодно во что угодно?

Через https://transform.tools/, конечно!

SVG в JSX, CSS в TailwindCSS и обратно, Flow в TypeScript, JSON Schema в OpenAPI schema и так далее до бесконечности.

Конечно, если нужно делать это массово — не вопрос, стоит использовать специально подготовленные утилиты. Но, как минимум, их можно подсмотреть прямо в репозитории проекта: https://github.com/ritz078/transform

#tool
#статья дня

Сегодня у нас, прости господи, статья с Хабра. Там нынче много странного контента и плохих переводов, но эта — хорошая.

Автор — Карен Ананян, продуктовый дизайнер — предлагает новый (?) метод адаптивного дизайна, объединяющий принципы отзывчивого дизайна, адаптивного дизайна и масштабирования.

Я поставил вопрос после «новый», потому что, по факту, автор перепридумал clamp(). Но не то чтобы совсем.

Существующие подходы:

Responsive design (отзывчивый дизайн): Элементы интерфейса адаптируются к размерам экрана, сохраняя общую композицию и функциональность. Однако при значительном увеличении размеров экрана элементы могут чрезмерно растягиваться, ухудшая удобочитаемость и внешний вид.

Adaptive design (адаптивный дизайн): Структура блоков и элементов перестраивается в зависимости от устройства. Это требует разработки и поддержки нескольких макетов для разных типов устройств, что может быть трудоемким процессом.

Проблемы существующих подходов:

В Responsive design элементы могут чрезмерно растягиваться на больших экранах, что снижает удобство использования.

Adaptive design требует значительных ресурсов для разработки и поддержки множества макетов под разные устройства.

Предлагаемое решение: Stretch, Scale, Switch (SSS):

Автор предлагает трехэтапный подход к адаптивному веб-дизайну:

Stretch (Растяжение): Использование принципов отзывчивого дизайна для гибкого изменения размеров элементов по ширине или высоте, что обеспечивает адаптацию интерфейса к различным размерам экранов.

Scale (Масштабирование): При значительном изменении размеров экрана применяется пропорциональное масштабирование всего макета, включая шрифты, отступы и размеры блоков, с использованием выбранного множителя (scale-фактора).

Switch (Переключение): Если масштабирование достигает предела своей эффективности, происходит переключение на другой макет, оптимизированный для текущего разрешения экрана.

На самом деле, статья является действительно сборником хороших примеров и техник. Я сам пытался на эту территорию заходить с своё время, но не делал попыток свести всё к какому-то названию.

А вот собственно, ссылка: https://habr.com/ru/companies/simpleone/articles/881168/

#css #adaptive #responsive
#молния дня

Вы знали, что git reset --hard после git add . грохает все новые файлы в репе?

89 штук 🥲

Подробности завтра...
#такое дня

Итак, что же произошло?

Жена изучает Wordpress и React. Вот вы знали, почему Gutenberg — конструктор блоков в Wordpress — так боготворят? Вот я раньше не знал, пока, собственно, жена в колледже не начала его изучать.

Если коротко, каждый блок в Gutenberg можно описать в React. А потом рендерить WYSIWYG в конструкторе и PHP-версию для сайта. Исконный SSR как он есть :) На самом деле, я был почти в восторге.

И для этого процесса имеется кодогенератор.

Он сгенерирует JSON-схему блока, стили и начальные скрипты для редактора и клиентской части сайта, package.json с нужными скриптами, PHP-обвязку, readme... В общем, с десяток файлов.

Но вы не за этим тут собрались, верно?

Итак, нагенерировали 9 блоков, три из них практически полностью закончили, остальные — оставили в виде кодгена. И попросила жена меня помочь уложить всё в git. Последить, что все сделано правильно.

Как показали события, нашла, конечно, кого просить.

Ну, первый раз чтоле:
git init
touch .gitignore
git add .
git status
...так, index.php же не нужен...
git reset --hard
echo "index.php" >> .gitignore
...блять

89 файлов исчезли, осталось лишь то, что было открыто в файлах.

Зачем я сказал сделать хард-ресет — я сам не очень понимаю, если честно. Даже не спрашивайте. Я привык работать инкрементально: и добавлять файлы с самого начала, и ветки на каждый чих и так далее. Потому ресет для меня был инструментом простой подчистки мусора.

Теперь-то понятно, что от этой привычки надо избавляться.

К счастью, в git ничего не пропадает бесследно. Есть возможность вытащить «подвисшие» файлы из индекса, пока не произошёл коммит. Как-то так:

git fsck --lost-found

Эта команда вытащит подвисшие файлы в директорию .git/lost-found/.

Вот только вытащит она их по хэшу. Названия будут утеряны. Ну и ещё — одинаковые файлы будут, очевидно, схлопнуты в один (ещё раз внимание на слово хэш).

К счастью, мы же помним, что у нас кодогенератор? Содержимое каждого из этих файлов явно говорит, к чему оно относится. Так что, вооружившись списком файлов, который мне ранее дала команда git status, я создал 89 пустых файлов с верными именами и пошёл копировать один за одним. Полчаса из жизни.

Но точно не впустую. Выводы сделаны. Учитесь пользоваться инструментами, котаны. Не полагайтесь на привычку.

Да, во многи редакторах присутствует концепция локальной истории, но тот же VS Code реагирует только на открытые файлы.

В общем, было весело. И немного стыдно, да.

P. S. удалять index.php из списка добавленных файлов надо было так:

git reset index.php

Или просто

git reset

...чтобы очистить список файлов к добавлению.

#git #wordpress #fail
Привет, котаны! 🐱

В Телеге всегда была проблема с поиском классных авторов — здесь почти нет рекомендаций, алгоритмы не подсовывают похожие каналы, и найти что-то годное можно либо случайно, либо по совету тех, кто уже читает.

У меня есть несколько любимых каналов, но интересно, что читаете вы? Давайте вместе соберем список Telegram-каналов, которые реально заходят.

Не просто те, на которые когда-то подписались, а те, куда заглядываете с интересом, читаете посты, комментируете, прислушиваетесь.

Это могут быть каналы про разработку, ИТ, технологии или даже научпоп, общетематические или авторские — главное, чтобы читать их было интересно, а не «ну ладно, пусть висит в подписках».

Делитесь в комментариях! Если видите канал, который тоже читаете — ставьте реакцию. Посмотрим, какие из них набирают больше всего респекта в нашей ленте.🚀
Какими мини-апами в tg вы пользуетесь?

Вот какой удобный Mini App появился недавно: Calendar for Telegram

Это:
💫 Быстрый доступ к расписанию, которое теперь всегда под рукой;
💫 Лёгкий шэринг событий – без e-mail! Просто отправьте приглашение другу/коллеге в чат или в группу;
💫 Афиши – общее расписания для работы, мероприятий, совместных путешествий или спорта;
💫 Слоты – отражают доступность вашего свободного времени для назначения встреч (это как Calendly, только в вашем tCalendar);
💫 Моментальный видео-звонок – возможность создавать Google Meet сразу в tCalendar;
💫 Синхронизация с Google Календарем – все события всегда актуальны в обоих календарях.

Самое приятное, что всё это бесплатно и незаменимо в обычной жизни👌

Юзкейс такой: поняли, что нужна встреча -> создали её тут же в тг -> пригласили участников. В Гугл календарь само придет. 🪄
This media is not supported in your browser
VIEW IN TELEGRAM
#инструмент дня

F*ck Leetcode.

Как-то так приветствует нас проект https://www.interviewcoder.co/

Что же он делает?

А разработчики проекта догадались сделать невидимый для шаринга экрана ИИ-оверлей, который находит на экране и решает алгоритмические задачи.

Невидим он для:

- Zoom < v6.1.6
- Всех браузеров
- Discord
- Встроенного в maxOS скриншотера (не видео)

Видим для:
- Zoom > v6.1.6
- Записи видео в том же macOS

Может не только решать код, но и дебажить его, давать построчные подсказки и исправлять ошибки.

Ну что, литкод-собесам конец? :)

Да, проект — открытый: https://github.com/ibttf/interview-coder

И в доказательство — запись реального собеседования: https://youtu.be/rcH813f5vCE

#leetcode #interview #ai #cheat
#фишка дня

Я всегда считал карту кода достаточно бестолковой фишкой. С другой стороны, TODO-комментарии и ошибки достаточно легко распознаваемы и перемещаться по ним удобно.

А сегодня я узнал, что блоки кода можно ещё и помечать комментарием // MARK: Something, и этот самый Something будет виден на карте.

В идеале, конечно, не стоит развозить свой код на несколько экранов, но прежде чем разбивать — надо ж распознать, верно? :)

#vscode #minimap #бородач
Будни разработчика
#инструмент дня F*ck Leetcode. Как-то так приветствует нас проект https://www.interviewcoder.co/ Что же он делает? А разработчики проекта догадались сделать невидимый для шаринга экрана ИИ-оверлей, который находит на экране и решает алгоритмические задачи.…
#молния дня

Вы же посмотрели видеодемонстрацию ИИ-помощника, который поверх экрана выводит ответ на тестовое лайвкодинг-задание?

Вот: https://youtu.be/rcH813f5vCE

Так вот, повторю: это было реальное собеседование в Амазон. И интервьюверу потом это видео прислали.

И в Амазон обиделись! И требуют отчисления автора проекта из университета!

Пруф: https://x.com/im_roy_lee/status/1895276427005845981

В комментарии приложу картинку оттуда, на случай, если что-то с твитом пойдёт не так :)
#статья дня

В чатике всплыл очередной вопрос про эффект ambilight.

Если кто не помнит, фоновая интерактивная подсветка ambilight — от Ambient Light — пришла к нам от телевизоров Филипс, а нынче есть даже на YouTube.

Мы уже рассматривали пару вариантов создания такого эффекта, но не для видео.

А для видео же — есть прекрасная статья на Smashing Magazine: https://www.smashingmagazine.com/2023/07/recreating-youtube-ambient-mode-glow-effect/

Описывается создание нужного эффекта на основе canvas, со всеми пояснениями и кодом. Даже хук для React по пути сделали.

Вообще, до меня не сразу дошло, почему именно холст. Почему бы просто не запустить два видео и одно размыть?

Но, на самом деле, выходит так, что на холст можно отправлять далеко не все кадры, можно по пути накладывать дополнительные эффекты, не нужно заботиться о синхронизации двух видео. Ну и requestAnimationFrame позволяет здорово снизить нагрузку на клиента.

#ambilight #video #canvas
2025/07/05 07:55:24
Back to Top
HTML Embed Code: