Подойдут и для Android, и для iOS
Сделали новогодние заставки для телефонов с вайбом разработки на Flutter. Можно поставить себе, закинуть коллеге или в рабочий чат🎄
Скачать — в комментариях⬇️
Сделали новогодние заставки для телефонов с вайбом разработки на Flutter. Можно поставить себе, закинуть коллеге или в рабочий чат
Скачать — в комментариях
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12❤9🔥5😁3
Привет, я Катя, Friflex Flutter Dev. Сегодня расскажу о GenUI SDK для Flutter — инструменте, который помогает собирать динамические пользовательские интерфейсы с помощью генеративного ИИ.
Что такое GenUI SDK
GenUI SDK для Flutter — это альфа-версия SDK на pub.dev. Она предлагает другой подход к взаимодействию с пользователем: вместо текстового ответа чат-бота вы можете показывать адаптивные визуальные компоненты.
Например, выпадающие списки, слайдеры, карусели товаров и формы с выбором даты. Компоненты меняются в реальном времени, в зависимости от намерений пользователя.
⭐️ Вопрос к размышлению: как часто вы сталкивались с тем, что чат-бот перечисляет товары текстом, хотя удобнее было бы сразу увидеть карточки с кнопками?
Как работает GenUI
Процесс устроен как интерактивный цикл. Пользователь вводит запрос (например: «помоги спланировать поездку в Токио»), а приложение отправляет его ИИ-агенту вместе с описанием доступных виджетов.
Дальше ИИ-агент генерирует не только текст, но и описание интерфейса с помощью инструментов GenUI SDK. Обычно это структура в формате JSON (JavaScript Object Notation), которую приложение десериализует и превращает в соответствующие Flutter-виджеты.
SDK может отрисовывать стандартные компоненты постепенно, по мере генерации ответа большой языковой моделью (LLM). Так интерфейс появляется быстрее, и пользователю не нужно ждать, пока придет ответ целиком.
Что GenUI SDK умеет
🔴 Генерировать UI из структурированных данных
🔴 Работать с настраиваемым каталогом виджетов
🔴 Обрабатывать события и поддерживать интерактивный диалог
Каталог виджетов задает словарь Flutter-компонентов, которые ИИ может использовать. Каждый CatalogItem содержит имя виджета, JSON-схему его свойств и builder-функцию для рендеринга.
Реактивная система автоматически перестраивает виджеты при изменении данных в клиентской модели. А обработка событий позволяет фиксировать действия пользователя (клики, ввод текста) и отправлять обновленное состояние обратно ИИ для следующего шага.
⭐️ Попробуйте представить: какие компоненты вашего приложения могли бы генерироваться на основе запросов пользователей?
Практическое применение
GenUI SDK подходит для AI-нативных приложений. Например, вместо текстового списка продуктов можно показать кликабельную карусель, а при планировании поездки — сгенерировать форму с полями ввода и слайдерами.
Если продукт уже сделан на Flutter, интеграция может быть проще: вы используете существующие компоненты и систему стилей. SDK позволяет собирать макеты экранов и управлять навигацией на основе пользовательских намерений, чтобы создавать персонализированные интерфейсы в рамках вашего бренда.
Подробнее — в блоге Flutter: Rich and dynamic user interfaces with Flutter and generative UI.
P.S. SDK пока в альфа-версии, но уже доступен на pub.dev для экспериментов. Делитесь опытом в комментариях!
Что такое GenUI SDK
GenUI SDK для Flutter — это альфа-версия SDK на pub.dev. Она предлагает другой подход к взаимодействию с пользователем: вместо текстового ответа чат-бота вы можете показывать адаптивные визуальные компоненты.
Например, выпадающие списки, слайдеры, карусели товаров и формы с выбором даты. Компоненты меняются в реальном времени, в зависимости от намерений пользователя.
Как работает GenUI
Процесс устроен как интерактивный цикл. Пользователь вводит запрос (например: «помоги спланировать поездку в Токио»), а приложение отправляет его ИИ-агенту вместе с описанием доступных виджетов.
Дальше ИИ-агент генерирует не только текст, но и описание интерфейса с помощью инструментов GenUI SDK. Обычно это структура в формате JSON (JavaScript Object Notation), которую приложение десериализует и превращает в соответствующие Flutter-виджеты.
SDK может отрисовывать стандартные компоненты постепенно, по мере генерации ответа большой языковой моделью (LLM). Так интерфейс появляется быстрее, и пользователю не нужно ждать, пока придет ответ целиком.
Что GenUI SDK умеет
Каталог виджетов задает словарь Flutter-компонентов, которые ИИ может использовать. Каждый CatalogItem содержит имя виджета, JSON-схему его свойств и builder-функцию для рендеринга.
Реактивная система автоматически перестраивает виджеты при изменении данных в клиентской модели. А обработка событий позволяет фиксировать действия пользователя (клики, ввод текста) и отправлять обновленное состояние обратно ИИ для следующего шага.
Практическое применение
GenUI SDK подходит для AI-нативных приложений. Например, вместо текстового списка продуктов можно показать кликабельную карусель, а при планировании поездки — сгенерировать форму с полями ввода и слайдерами.
Если продукт уже сделан на Flutter, интеграция может быть проще: вы используете существующие компоненты и систему стилей. SDK позволяет собирать макеты экранов и управлять навигацией на основе пользовательских намерений, чтобы создавать персонализированные интерфейсы в рамках вашего бренда.
Подробнее — в блоге Flutter: Rich and dynamic user interfaces with Flutter and generative UI.
P.S. SDK пока в альфа-версии, но уже доступен на pub.dev для экспериментов. Делитесь опытом в комментариях!
Please open Telegram to view this post
VIEW IN TELEGRAM
❤6🔥2
Какой сценарий вы бы протестировали первым?
Anonymous Poll
41%
e-commerce
22%
бронирование
37%
что-то совсем другое
Сегодня поговорим про версионирование Futter-приложений. Тема простая, но часто вызывает вопросы у начинающих разработчиков.
Наверняка вы знаете, что во Flutter-приложениях версия указывается в pubspec.yaml с ключом vesion. Выглядит это так:
version: 1.2.3+4
Для удобства восприятия возьмем буквенное представление:
version: A.B.C+D
Сочетание A.B.C отвечает за версию приложения. Значение под буквой D — за версию сборки.
Когда повышать каждый уровень версии приложения?
A — отвечает за мажорные изменения.
Повышать этот уровень точно нужно, если ваше приложение сильно менялось. Например, если вы:
✔️Полностью изменили дизайн
✔️Переработали пользовательские пути
✔️Радикально изменили или удалили ключевые функции
✔️Загрузили полностью новое приложение
Если приложение уже не похоже на себя и может восприниматься пользователем как другой продукт, смело повышайте уровень А.
B — минорные изменения.
Сюда обычно относятся:
✔️Новый функционал и масштабирование старого
✔️Новые пользовательские пути без критичного изменения старых
Если приложение выросло, получило новые фичи, но при этом сохранило свой предыдущий вид — нужно увеличивать уровень B.
C — мелкие фиксы и доработки.
Стоит повысить уровень С, когда вы:
✔️Вносите правки по багам или верстке
✔️Повышаете производительность приложения
✔️Выполняете рефакторинг или обновление зависимостей без влияния на ранее реализованные функции
При повышении версии важно помнить: оно выполняется по уровню наиболее значимых изменений. Например, сейчас версия вашего приложения — 3.9.14. В новом релизе вы исправили баги, добавили новую фичу и полностью изменили весь UX/UI приложения. В этом случае самым критичным изменением считается последнее. Версия — 4.0.0.
А что с версией сборки?
D — версия конкретного билда.
Стандартно это значение инкрементируется в каждый новый билд вашего приложения. Независимо от изменений внутри.
Без повышения этой версии сторы не смогут принять вашу новую сборку. Возможно, в коде вообще не было никаких изменений — поднять D нужно обязательно.
❤️— если было полезно
Please open Telegram to view this post
VIEW IN TELEGRAM
❤24🔥4❤🔥1🤩1
Все мы привыкли использовать
Column, Row, ListView и различные layout-виджеты. Но как часто в проектах вы сталкивались с таблицами и использовали для этого виджет Table? Табличную структуру можно реализовать через комбинацию Column + Row + ListView. Иногда это оправдано, но не всегда — иногда лучше использовать специально предназначенные для этого инструменты.Во Flutter для работы с таблицами есть несколько виджетов:
✔️
PaginatedDataTable — для работы с большими таблицами с поддержкой постраничной навигации. Используется для больших таблиц, где можно управлять сортировкой и переходами между страницами данныхPaginatedDataTable(
header: Text('Список пользователей'),
columns: const [
DataColumn(label: Text('ID')),
DataColumn(label: Text('Имя')),
DataColumn(label: Text('Email')),
],
source: myDataSource, // DataTableSource
rowsPerPage: 10,
)
Для сортировки таблицы используются параметры sortColumnIndex (номер колонки) и sortAscending (направление сортировки), а обработка самой сортировки выполняется через onSort.
✔️
DataTable – для небольших или заранее известных наборов данных. Строки добавляются динамически из моделей, что упрощает масштабированиеПример с моделью
User:DataTable(
columns: const [
DataColumn(label: Text('ID')),
DataColumn(label: Text('Имя')),
DataColumn(label: Text('Email')),
],
rows: users.map((user) {
return DataRow(cells: [
DataCell(Text(user.id.toString())),
DataCell(Text(user.name)),
DataCell(Text(user.email)),
]);
}).toList(),
)
✔️
Table — дает полный контроль над структурой строк и столбцов. Каждая строка создается черезRow, ListVie а каждая ячейка может содержать любой виджет или комбинированный UI.Table(
border: TableBorder.all(color: Colors.black26), // границы таблицы
columnWidths: { // ширина столбцов
0: FlexColumnWidth(2),
1: FlexColumnWidth(3),
},
children: [ // список строк
TableRow(children: [ // каждая строка с набором виджетов
Text('ID', textAlign: TextAlign.center),
Text('Имя', textAlign: TextAlign.center),
]),
TableRow(children: [
Text('1', textAlign: TextAlign.center),
Row(children: [Icon(Icons.person), Text('Алексей')]),
]),
TableRow(children: [
Text('2', textAlign: TextAlign.center),
Row(children: [Icon(Icons.person), Text('Мария')]),
]),
],
)
Через
columnWidths можно управлять шириной столбцов:▫️
FixedColumnWidth — фиксированная ширина▫️
FlexColumnWidth – пропорциональная▫️
IntrinsicColumnWidth – по содержимому⚠️ Внутри ячеек
Table нельзя использовать Expanded, так как отрисовка и размеры управляются самим виджетом.
Table удобно использовать для кастомных макетов, где важны выравнивание ячеек, ширина столбцов и границы. Каждая строка состоит из набора виджетов, что облегчает управление макетом и сохраняет структуру данных.При работе с таблицами есть несколько нюансов:
✔️IntrinsicColumnWidth заставляет Flutter делать два прохода при компоновке: сначала измерить все элементы, затем отрисовать. Если строк сотни — интерфейс может начать тормозить. По возможности лучше использовать
FlexColumnWidth✔️Адаптивность на маленьких экранах. Таблица подстраивается под ширину экрана, но на небольших устройствах может быть трудночитаема. В таких случаях стоит использовать горизонтальный скролл или адаптивный макет
✔️ Динамическая высота строк. Если содержимое ячеек часто меняется (например, при загрузке данных, анимациях или использовании
ExpansionTile), Table может стать узким местом. Для таких случаев иногда удобнее использовать комбинацию ListView + Row/Column✔️Использование
Row/Column + ListView оправдано, если у вас простой список элементов, строки сильно различаются по содержимому или нужен вертикальный скролл без необходимости выравнивания колонокНа этом все! ❤️ всем любителям табличек
Please open Telegram to view this post
VIEW IN TELEGRAM
❤14👍8🔥4😢2😁1
Сегодня хочу поговорить о самом волнующем вопросе конца декабря: «А давайте запушим в прод?»
Предновогодний синдром деплоя
Знаете, что объединяет разработчиков по всему миру в конце декабря? Нет, не корпоративы с оливье. Это священный ужас при виде коллеги, который бодро пишет в чатик: «Ребят, у меня тут маленький фикс, можно быстренько в прод?» Маленький фикс в конце декабря — это как «просто быстренько зайти в магазин с мамой». Такого не бывает.
Декабрь — это время, когда даже самые отчаянные разрабы начинают говорить страшным голосом про code freeze. И правильно делают! Потому что если что-то пойдет не так 30 декабря, вы будете чинить баги не под бой курантов, а вместо боя курантов.
Что такое code freeze и почему его вводить
Code freeze (или фриз деплоя) — это когда команда договаривается: «Все, ребята, стоп-машина! До Нового года только критичные баги трогаем, и то если они прям совсем критичные». Это как карантин, но для кода.
Обычно фриз начинается где-то с 20-25 декабря и длится до середины января. В это время:
❌Нельзя мерджить фичи (даже если они «точно работают»)
❌Нельзя рефакторить (это вообще никогда нельзя перед праздниками)
❌Нельзя обновлять зависимости (Flutter SDK может и подождать)
❕Можно только чинить то, что реально горит
Почему нельзя лить в прод в конце декабря
Представьте: вы залили фичу 29 декабря, все ушли праздновать, а 31-го приложение начинает крашиться у половины пользователей. Поздравляю, вы только что стали главным злодеем чужого Нового года! Теперь вместо шампанского вы будете пить кофе и смотреть в логи Crashlytics.
А еще есть нюанс: если что-то сломается, собрать команду для фикса будет невозможно. Кто-то уехал к бабушке в деревню без интернета, кто-то в Таиланде (и там другой часовой пояс), а кто-то вообще отключил рабочий телефон. И правильно сделал.
Исключения из правил
Единственный валидный повод для деплоя в конце декабря — это когда прод реально горит. И под горит я имею в виду не «кнопка немного криво стоит», а «пользователи не могут оплачивать заказы» или «приложение крашится при старте у всех».
Но даже в этом случае фикс должен быть:
▪️Минимальным (чиним только то, что сломалось)
▪️Протестированным (да, даже в предновогодней запаре)
▪️С откатом наготове (если что-то пойдет не так)
Как пережить фриз без стресса
Главный секрет спокойного Нового года — это подготовиться заранее. Залейте все важные фичи до 20 декабря, проведите тщательное тестирование, убедитесь, что мониторинг работает, и можете спокойно идти выбирать мандарины🍊
Please open Telegram to view this post
VIEW IN TELEGRAM
❤8🔥7👍4🏆1
А как у вас в команде?
Anonymous Poll
33%
67%
Уже пару раз мы затрагивали вопрос in-app покупок в приложениях. Например, писали о том, как интегрировать плагин in_app_purchase в Flutter-проект. Сегодня же поговорим о том, как в целом по шагам работает процесс покупки и получения информации о них.
Дисклеймер. Эта информация актуальна именно для покупок через App Store, так как они сейчас доступны в России, в отличие от покупок через Google Play.
Для удобства представим — мы создаем Flutter-приложение, которое имеет определенный контент, доступный только пользователям с подпиской. Подписка оформляется через App Store и привязывается к конкретному аккаунту пользователя в базе данных на бэкенде.
Здесь мы четко можем увидеть трех участников процесса — приложение, бэкенд и App Store. Теперь разберем, как же они будут друг с другом взаимодействовать.
1 шаг. Приложение.
Пользователь в приложении знакомится с доступными продуктами для покупки. Затем через определенные элементы интерфейса осуществляет in-app покупку.
Для этого в проект необходимо интегрировать in_app_purchase. Подробнее процесс интеграции я описывала в предыдущем посте на эту тему. Основная задача приложения — вывести информацию об актуальных продуктах и при покупке вызвать нативное окно оплаты App Store.
2 шаг. App Store.
App Store самостоятельно выполняет процесс списания средств с привязанного счета. В случае успеха все данные о транзакции будут переданы дальше. И здесь два варианта развития событий:
✔️Данные о транзакции возвращаются колбэком в приложение. Дальше приложение может делать с ними все, что угодно, например, отправить на сервер
✔️Данные о транзакции получает сам сервер. За это ответственна технология Server-to-Server Notifications, когда App Store отправляет уведомление о покупке с данными на сервер. В этом случае требуется указать эндпоинт в App Store Connect в настройках приложения
У первого варианта больше рисков, так как весь процесс покупки напрямую зависит от состояния устройства — включено ли, подключено ли к интернету, открыто ли приложение. Если какой-то из этих пунктов будет нарушен, процесс может не завершиться, и данные о покупке не дойдут на бэкенд.
Второй вариант полностью абстрагирован от пользователя. Общение ведется только между сервером приложения и App Store. Здесь все выше перечисленные факторы не повлияют и не прервут процесс. В нашем примере пойдем именно по этому пути.
3 шаг. Бэкенд
Бэкенд получает колбэк от App Store с данными о транзакции. Эти данные достаточно объемны, они содержат много полезной информации. Например, тут можно найти сведения о купленном продукте, о его цене и времени покупки. Также из приложения можно передавать данные о внутреннем аккаунте приложения через поле applicationUsername. Эта информация также придет с данными транзакции.
Важно — перед выдачей прав пользователю покупку стоит сначала проверить.
4 шаг. Приложение.
Дальше приложение стучится на бэкенд, просит данные для конкретного авторизованного пользователя. Сервер в свою очередь самостоятельно проверяет актуальность данных и наличие оплаченного периода и определяет, какой контент нужно отдать.
Самое лучшее здесь то, что приложение остается «тонким клиентом». Оно не нагружено сложной логикой внутренних проверок. Его задача в том, чтобы просто отобразить полученные данные.
Если остались вопросы, задавайте в комментариях
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥8❤6☃1👍1🤩1🎄1
Год подходит к концу, и мы, Роза, Катя и Аня, хотим устроить небольшую ретроспективу и поделиться своими открытиями за 2025-ый
Этот год был богат на задачи абсолютно разного характера. За это время я сделала пару парсеров, разработала расширение для DevTools, внедрила LLM во Flutter Web-приложение, поработала с Serverpod, узнала, что такое OTA, и в целом писала бэкенд на Dart.
Главный инсайт: любую задачу можно сделать (почти). Какой бы сложной она ни казалась вначале, всегда находится решение. И в этом есть свой кайф — на второй-третий день ты всем сердцем ненавидишь ее, не понимая, с чего начать, а когда все-таки решаешь — это настоящее блаженство
Раньше я часто бралась за задачу без особого анализа и обдумывания деталей. Но когда сталкиваешься с большой фичей, которая может повлиять на другие части проекта, начинаешь задумываться над каждым шагом.
Моим ориентиром на год было улучшение кода и архитектуры. Справилась ли я? Сложно сказать. Но открывая свой старый код, я постоянно вижу, что его можно улучшить и оптимизировать — а то, что я это замечаю, наверное, о чем-то говорит.
Мой главный инсайт: агенты и вайб-кодинг. В этом году у меня было открытие, которое изменило мой подход к разработке. Сейчас начинается эра vibe coding — когда ты не пишешь код построчно, а просто описываешь намерение, и агент превращает его в рабочий (не всегда) код.
Раньше программирование было про «как»: как написать цикл, как обработать исключение, как настроить конфиг. С агентами это стало про «что»: что я хочу получить, какую проблему решаем.
Что изменилось?
✔️Скорость: То, что занимало час, теперь — 15 минут
✔️Креативность: Освободилось время на архитектуру и эксперименты
✔️Рутина: Boilerplate, тесты, документация генерируются автоматически
Но главное — важно понимать, что даже сейчас агенты работают неидельно и их нужно перепроверять. Но с базовыми задачками они справляются хорошо. Конкретно я использую copilot, и в первое время он выдавал чепуху, но тут главное хорошо описывать промпт и потом читать код.
Этот год был супер насыщенным на новые знания и открытия. Но мой самый главный инсайт — коммуникация команды с заказчиком.
На первый взгляд здесь все максимально просто. В команде у каждого участника есть своя роль, а с ней — свои обязанности. Но, как показывает практика, иногда бизнес выдвигает свои требования, которые могут сильно повлиять на весь процесс коммуникации.
В этом случае важно идти на компромисс. Да, заказчик может хотеть общаться напрямую с разработчиками и другими членами команды. Да, заказчик может просить встречи и обсуждения в нерабочее время. Здесь самое главное — уверенно отстоять границы команды, донести до бизнеса наши внутренние роли, предложить варианты, которые не будут негативно влиять на продуктивность команды.
Самая идеальная схема коммуникации — через PM, как через некий буфер, который не пропускает лишней информации в обе стороны. В таком случае другие члены команды остаются максимально в фокусе своих задач и не тратят силы и время на дополнительные вопросы.
И главное, что стоит помнить и заказчикам, и команде — вы не конкуренты, вы партнеры! У вас общая цель, вы идете к стабильному, рабочему продукту. А достичь этой цели возможно только совместными усилиями и обоюдными компромиссами.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤13👍6🎄6🔥3☃1😁1🎅1
А пока вы готовите костюмы, хотим поздравить с Новым годом!
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
❤14😁5🔥4👍1
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4👍2
Какие три основных подхода существуют для работы с иконками во Flutter?
Anonymous Quiz
4%
PNG, JPG, GIF
61%
Icon Fonts, SVG, Vector Graphics
33%
Material Icons, Cupertino Icons, Font Awesome
2%
Bitmap, Vector
Какой виджет позволяет дочернему элементу выходить за границы родителя?
Anonymous Quiz
85%
OverflowBox
3%
AspectRatio
11%
Expanded
2%
Align