Android в тесте и маленький капучино


Kanal geosi va tili: Rossiya, Ruscha


Android разработчик из Дринкит @kartollika переродился в писателя и активно ищет темы для публикации

Bog‘liq kanallar

Kanal geosi va tili
Rossiya, Ruscha
Statistika
Postlar filtri


Сделали себе публичный дашборд проекта Drinkit

Пока что только для Android, скоро сделаем и iOS, как только обсудим что ребята хотят трекать 📊

Завели, чтобы смотреть на него и улучшать показатели проекта. И показать в паблик, как у нас идут дела и обзавестись мотивацией становиться лучше

Дашборд построен на движке и идее из iOS пиццы, про которую Леша Березка писал у себя

657 0 14 8 12

Mobius — канал конференции dan repost
#видеозаписи #МобильныйВторник

Долгое время Shared-анимации воспринимались как красивое дополнение, без которого можно обойтись. Сейчас ситуация меняется: дизайнеры все чаще закладывают такие переходы как обязательную часть UX. На весеннем Mobius мы увидели кейс из Дринкит с Shared Transitions в нетривиальных условиях — с блюром, затемнениями и другими визуальными эффектами.

Дмитрий Максимов — Когда Shared Transition — это требование дизайнеров: необычные кейсы на Compose

😉 YouTube | 📺 VK Видео

Скачать презентацию с сайта Mobius


Так был погружен в рабочие задачи, что не заметил, как неделю назад опубликовали мой доклад с весеннего Mobius 2026

Рассказывал тогда про Shared Transitions и блюр в Compose на примере нашей фичи комбо. Залетайте на просмотр 😏


Кстати, есть еще одна очень срочная и горячая новость

В Додо появились стажировки! И с подачей заявок лучше поторопиться, потому что прием заканчивается сегодня

Открытые направления:
⭕ Разработка & Security
⭕ QA
⭕ Аналитика
⭕ Дизайн
⭕ Менеджмент в ИТ

Стажировка только для студентов ИТМО и СГУ (Сыктывкарский ГУ) 3-4 курсов бакалавриата и 1-2 курсов магистратуры

Поторопитесь, потому что прием заявок заканчивается 7 сентября. Если у вас есть кандидаты — скидывайте им этот пост

https://maxpolitov.github.io/dodo-internship-landing/#apply


Ура! У нас в додо наконец то открылись вакансии для Android разработчиков 👩‍💻🍕

Android разработчик (App&Web) — ищем разработчика в команду оформления заказа

Android разработчик (Core команда) — вакансия разработчика в core-команду мобильного приложения Додо

Знаю, что вы интересовались наличием вакансий к нам. Пришло ваше время 😧

1.2k 0 37 28 19

Наткнулся в LinkedIn на вакансию, а на её странице висит системный промпт для отбора и отсеивания кандидатов. А там вот такие штуки:

Отсеивание по возрасту:
Upper Limit: FAIL the candidate if total experience exceeds 20 years


Тир лист компаний для приоритетного найма
Industry Tier Alignment: Prioritize candidates from target tiers:
- Tier 1 (Fintech, Neobanks & Payments): Tinkoff, Wise, Revolut alumni
- Tier 2 (High-Scale B2C Apps): Glovo, Ozon, Kiwi.com, Aviasales, Booking.com
- Tier 3 (High-Growth Tech & B2C SaaS): Amazon, TikTok


Отсев кандидатов по прошлому месту работы
FAIL the candidate if their experience is exclusively from slow-paced/legacy environments, static marketing agencies, internal enterprise tools, or small/toy apps, prototypes, or unscaled MVPs


И это Revolut. Как вам? 😳


В песочнице для iOS мы выбрали немного другую механику. Там мы делали песочницу уже после Android, так что был взгляд со стороны, что хорошо и что плохо. В итоге получилось похоже, но со своими отличиями 👁

И пока андроидик отдыхает после рассказа, к доске подходит иосик

iOS: Макросы + Build Tool Plugin
🦾

Был выбран путь сделать полностью контролируемую песочницу, где каждый параметр компонента должен быть отмечен и задан явно

Основная идея такая же — компонент отмечается макросом Playground
@attached(peer, names: suffixed(_Playground))
public macro Playground(
_ name: String,
in location: CatalogPath,
status: ComponentStatus = .active,
presentation: PlaygroundPresentation = .page,
previewLayout: PlaygroundPreviewLayout = .sizeThatFits,
designVersion: String = "1.0"
) = #externalMacro(
module: "PlaygroundMacroPlugin",
type: "PlaygroundMacro"
)

Но различие в том, как и какие параметры попадают в плейграунд

Механика плейграунда на iOS такая:

1. Пометить компонент макросом @Playground

2. Если у компонента есть параметры — разметить ВСЕ поля его модели @PlaygroundParam либо @PlaygroundIgnore. За полноту разметки отдельно следит CI-линтер.

3. Макрос разворачивается компилятором в отдельный тип PlaygroundComponent с методом component(knobs:), который возвращает View — аналог PlaygroundProvider на Android

4. На этапе сборки Build Tool Plugin сканирует swift файлы, запускает кодогенератор и на выходе получает манифест модуля PlaygroundManifest со списком всех найденных компонентов.

5. При открытии песочницы, содержимое манифеста регистрируется в singleton реестре. Он оборачивает фабрику View компонента в экранный контейнер, готовый для отображения в плейграунде.

Итого на песочнице iOS:
⭕ Компоненты строго типизированы и вероятность райнтайм крашей минимальна
⭕ Для каждого параметра явно задается своё default значение рядом с местом объявления. Видно прямо в коде компонента, а не в отдельном файле
⭕ Для компонента можно даже создать "фабрику стейтов", которая нарисует переключатель стейтов в песочнице. Удобно, чтобы проверять полноценные пресеты
⭕ Про забытые поля напомнит линтер в CI, но решение всё равно за человеком
⏺ Каждый компонент нужно явно декларировать вместе со всеми параметрами. Когда добавляется новый параметр, то надо провести анализ, какое ему значение надо поставить или поставить Ignore
⏺ Так как не все хочется показывать,
⏺ Разметка для песочницы живёт в проде, рядом с боевым кодом компонента

Ну и получается, что если в Android подход больше про "магию", то в iOS — больше про "контроль". Не знаю, хорошо или плохо это... Ответ мы еще не нашли

А что думаете вы? Какой метод показался более логичным и правильным? Делитесь мыслями ⬛


Пора раскрыть, как конкретно работают наши песочницы и рассказать про разницу между iOS и Android 🖼

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

Android: KSP + Рефлексия + ServiceLoader 🏗️

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

Точка входа в создание компонента в песочнице одна — аннотация PlaygroundComponent
annotation class PlaygroundComponent(
val name: String = "",
val category: PlaygroundCategory = PlaygroundCategory.OTHER,
val provider: KClass = NoProvider::class,
val state: KClass = Nothing::class,
val stateFactory: KClass = NoStateFactory::class,
val excludeParams: Array = [],
)

Весь подход держится на последовательных механиках:

1. Пометить Composable компонент аннотацией PlaygroundComponent

2. Если компоненту нужно задать дефолтный стейт — передать их в корневую аннотацию в stateFactory. Если какие-то параметры нужно скрыть — пометить их @PlaygroundHidden

3. Далее подключается KSP с сканированием и обработкой помеченных компонентов. Генерирует PlaygroundProvider класс — класс с методом @Composable Render(), который и отображается в нашей песочнице для отдельного компонента. Сгенерированный код Provider можно глянуть вот тут. Кстати, можно передать свой  PlaygroundProvider через корневую аннотацию

4. Все PlaygroundProvider'ы регистрируются в META-INF, а в рантайме эти классы создаются с помощью ClassLoader при заходе на экран — код Registry

Итого получили:
⭕️ Компоненты сами появляются в плейграунде, надо только поставить одну аннотацию
⭕️ В песочнице отображаются вообще все параметры у компонента, что вносит прозрачность в то, как выглядит модель компонента
⭕️ Есть возможность задавать свой дефолтный стейт, скрывать параметры, делать свои Providers для сложных компонентов
⏺️ Отображение всех параметров создает шум
⏺️ Кодогенерация и наша практика stateless компонентов вводит ограничение на "интерактивность" в песочнице. Менять состояние можно только через настройки

Это наш Android way. Следующим постом поделюсь про iOS путь
А пока делитесь мыслями, как вам подход? ⬛️

Хочу уже закончить с этой темой и перейти к теме автономного агента в дринките 🙏


В этом месяце у меня годовщина работа в Додо — работаю в компании 5 лет ☕️🐳

Я слышал, что на такую дату сотрудникам дарят значки, но не знал, дойду ли я сам до значка

Дошел

Очень рад, что работаю тут. Мой путь начинался ещё в Донер 42 с Арсением @startupsproducer. А последние уже 4 года я в дринките и останавливаться совершенно не хочется

Работаем 🐱






Проблемы с Navigation 3 присутствуют – от архитектуры до мелочей. Если про архитектуру можно спорить и это даже тянет на статью (может и напишу даже?), то про мелкие сложности легко поделиться тут

Одна из таких сложностей связана с BottomSheets. Это даже не столь сложность, сколько кривой их дизайн.

Излишне будет упоминать то, что BottomSheet для Navigation 3 вам до сих пор надо копировать себе из Github, чтобы завести стратегию BottomSheetStrategy. На это очень больно смотреть 😅

А саму проблему можете заметить на первом видео. Когда нам нужно открыть боттомшит с полем ввода и сразу показать клавиатуру, то это из коробки сделать не получится. Анимации происходят одновременно, и клавиатура перекрывает BottomSheet полностью. Именно во время первого открытия происходит конфликт анимаций, и клавиатура не учитывается в отступах

И это очень давний и известный баг, но фиксить не торопятся

Как идея решения я придумал следующую схему:
1. При открытии мы меняем анимацию BottomSheet на более быструю, пока Sheet не перешел в статус "открыт".

private class InstantKeyboardMotionScheme(
private val standardMotionScheme: MotionScheme = MotionScheme.standard(),
) : MotionScheme by standardMotionScheme {

var isSheetOpened by mutableStateOf(false)

override fun defaultSpatialSpec(): FiniteAnimationSpec = if (isSheetOpened) {
standardMotionScheme.defaultSpatialSpec()
} else {
tween(durationMillis = 50)
}
}

2. Подменить анимацию можно через MaterialTheme

val motionScheme = remember { InstantKeyboardMotionScheme() }
MaterialTheme(motionScheme = motionScheme) {
ModalBottomSheet()
}

3. Отслеживаем статус BottomSheet через стейт

val sheetState = rememberModalBottomSheetState()
val isSheetOpened = sheetState.currentValue != SheetValue.Hidden
SideEffect {
if (isSheetOpened) {
motionScheme.isSheetOpened = true
}
}

Итог – как теперь это выглядит на видео 2. Видно, что диалог быстро появляется, и дальше уже работает стандартная анимация 🤩

Выложил это в Gist на Github. Сделал это отдельной стратегией, но полезно и объединить обычный BottomSheet и InstantKeyboardBottomSheet в единую стратегию, чтобы поддерживать только один диалог


Привет! Долго меня тут не было, считайте что был в творческом отпуске (работал)

На этой неделе начну рассказывать цикл про то, как мы всё таки делаем дизайн систему в Дринките, как и обещал чуть ранее. Спойлер – мы продолжаем тюнить playground и готовимся к рефакторингу темы.

А пока напишу про пост, который сегодня привлек мое внимание. Пост про Navigation 3 в канале Compose Broadcast. В статье переводили сразу всё приложение с Navigation 2 на Navigation 3. В итоге вышло 2 недели разработки и еще полторы недели стабилизации.

Так совпало, что недавно я делал доклад на нашу Android гильдию о том, как хорош Navigation 3 и как переехать на него итеративно и контролируемо:

▫️Идем от листьев к корню. Фичи по отдельности переезжают на Nav3 и создают свой локальный NavDisplay, но снаружи остаются обычным экраном (фрагментом)
▫️Всякие диалоги и BottomSheets перестают быть фрагментами и рендерятся через сцены
▫️Nav2 выпиливается последним шагом, когда всё остальное уже на Nav 3
▫️Ну и делать это конечно можно агентами, заранее описав спеки об итеративной миграции и о том, как конечный результат должен выглядеть

Однако даже так есть свои сложности. Об одной из них расскажу завтра

Cаму презентацию я залил на Github Pages, а также выложил видео с гильдии и демо-проект с этапами миграции.


Dodo Engineering dan repost
Дима Максимов выступил на Мобиусе! Показал как мы в Дринките делаем Shared element и как у нас комбо с блюром на блюбре. 💙

Я сидел, слушал, и подумал, если бы я не знал Диму и был во вне Додо, я бы подумал "ну парни конечно с ума сошли, пиксель перфект их покусал". Но ведь выглядит топово! 🐳

300 0 4 12 28

И вот снова мобиус, только теперь я спикер 😅

Подходите знакомится, общаться!


🎁 Промокод на Mobius на 25% 🎁

Мне дали несколько промокодов на конференцию Mobius 2026 Spring, которая начинается уже на следующей неделе

Напомню, что я буду там спикером с темой про Shared Transitions 🎤
Помимо меня, там будет выступать мой коллега Максим @mobilefiction с хайповым докладом про AI Бариста

Я очень люблю залипать в разные приложения и вдохновляться интерфейсами оттуда 🙄

Так что условия такие:

💭 В комментариях скиньте приложение, которым вы вдохновляетесь
📱 Если приложите скрин — будет вообще огонь
😅 Если сложно придумать конкретное приложение, напишите, что вы цените в UI больше всего

Среди комментаторов рандомно выберу 2 человека и скину промокод в личку

Сам жду новых референсов в комментах 😼
Итоги будут уже завтра в 18:00

#Mobius


В последнее время было много суеты в жизни 💲

В начале апреля активно переезжали в собственную квартиру – и вот уже как 2 недели живу там. Пока что все нравится, каждый день на маркетплейсах покупаем что-то в дом

На прошлой неделе был в Москве в командировке. Там увиделись в полном (почти) составе Дринкита и ребятами из большого Додо. Было очень приятно всех-всех повидать, особенно кто всегда сидит в других странах

Сразу после командировки я заболел, но уже восстанавливаюсь :)

Теперь настает суета по финальным подготовкам к Mobius, который через полторы недели 😧


Мы в Дринките начали долгожданную большую работу над дизайн системой!

Наверное вы удивитесь, но у нас не было дизайн системы как таковой... Наша дизайн система в проекте выглядела так: общая Compose тема DrinkitTheme, на коленках сверстанные компоненты (к тому же часто дублирующие друг друга)
Да и ... всё

Планы у нас амбициозные, аппетиты нескончаемые, а команда всего 3 человека 😅

Главные вещи, которые мы планируем затронуть и решить за наш эпик:

🟡 Автоматизация токенов и атомов из фигмы в код. Помощь дизайнеру, чтобы без разработчиков поменять цвет/тень/скругление
🟡 Песочница дизайн системы. Наша дизайнер настояла, что это must для нашей жизни, и мы согласны. Единое место, где можно протестировать все компоненты – это очень важно
🟡 Унификация всех компонентов – от кнопок до полноценных молекул и организмов. Чтобы одна и та же вьюшка выглядела и работала одинаково, а не пятью разными способами, как у нас сейчас

И это только малая часть. Дальше – процессы, адаптация команды, метрики, обмен практиками с ребятами из Додо и рассказ об этом в паблик. В общем, работы на несколько кварталов 💻

Буду рассказывать по пути про успехи, сложности и наш опыт. А начнем мы с дизайн-песочницы, написанной на 100% с помощью Claude Code 👮‍♀️


Кто первый дойдет до знакомства с Lance Vance Dance с фотопруфом - тому подарю напиток в дринките 💲


Хотите испорчу ваш рабочий пятничный настрой? 😏

Нашел сайт с полностью портированной на Web моей любимой игрухой – GTA: Vice City

https://quenq.com/apps/vice-city/

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

600 0 12 2 19
20 ta oxirgi post ko‘rsatilgan.