🔥 Jetpack Navigation 3 теперь мультиплатформенная!
В релизе 1.0.0-alpha08 добавили поддержку множества новых KMP-таргетов для runtime-артефакта. Теперь библиотека работает на:
👉 JVM → Android и Desktop
👉 Native → Linux, iOS, watchOS, macOS, MinGW
👉 Web → JavaScript и WasmJS
Для UI-артефакта (где лежат Composable-функции) пока поддержка осталась только у Jetpack Compose.
Ждём появления отдельного артефакта для⚙️ Compose Multiplatform от JetBrains
#compose #kmp #navigation
В релизе 1.0.0-alpha08 добавили поддержку множества новых KMP-таргетов для runtime-артефакта. Теперь библиотека работает на:
👉 JVM → Android и Desktop
👉 Native → Linux, iOS, watchOS, macOS, MinGW
👉 Web → JavaScript и WasmJS
Для UI-артефакта (где лежат Composable-функции) пока поддержка осталась только у Jetpack Compose.
Ждём появления отдельного артефакта для
#compose #kmp #navigation
Please open Telegram to view this post
VIEW IN TELEGRAM
Подкючайте артефакт
org.jetbrains.androidx.navigation3:navigation3-ui:1.0.0-alpha01 в common код и можете пробоватьЖдем актуализации до свежей альфа версии, а также адаптивные layout и интеграцию с ViewModel
#compose #kmp #naviation #jetpack
Please open Telegram to view this post
VIEW IN TELEGRAM
Что нового для всех таргетов:
👉 Аннотация
@Preview в common коде теперь поддерживает задание параметров (имя для отображения, размеры и прочее)👉 Больше возможностей по управлению тенями
👉 Адаптировали новое API для управления контекстным меню из Android под все платформы. Требуется включение через код
ComposeFoundationFlags.isNewContextMenuEnabled = true
👉 Тема Material Expressive
👉 Артефакт
androidx.compose.runtime:runtime стал мультиплатформенным, перенеся наработки из org.jetbrains.compose.runtime:runtime👉
runComposeUiTest() теперь позволяет запускать suspend функции в теле вызоваCompose/iOS
👉 Управление желаемой частотой кадров для рендера Composable
Modifier.preferredFrameRate(FrameRateCategory.High)
Modifier.preferredFrameRate(120f)
👉 Поддержка кастомизаций ввода, специфичных для iOS
BasicTextField(
value = "",
onValueChange = {},
keyboardOptions = KeyboardOptions(
platformImeOptions = PlatformImeOptions {
keyboardType(UIKeyboardTypeEmailAddress)
}
)
)
Compose/Web
🎉 Поддержка Web таргета перешло в Beta статус
👉 Поддержка Accessibility API
👉 Новое API для встраивания HTML
private val ttOSM =
"https://www.openstreetmap.org/export/embed.html?bbox=4.890965223312379%2C52.33722052818563%2C4.893990755081177%2C52.33860862450587&layer=mapnik"
@Composable
fun Map() {
Box(
modifier = Modifier.fillMaxWidth().fillMaxHeight()
) {
WebElementView(
factory = {
(document.createElement("iframe")
as HTMLIFrameElement)
.apply { src = ttOSM }
},
modifier = Modifier.fillMaxSize(),
update = { iframe -> iframe.src = iframe.src }
)
}
}
👉 Упростили связывание Jetpack Navigation c навигацией в браузере
// Код в Composable функции
LaunchedEffect(Unit) {
// Implicitly accesses the window object
navController.bindToBrowserNavigation()
}
Compose/Desktop
👉 Возможность настройки окна с контентом с помощью API SwingFrame() and SwingDialog(), аналогичные Window() and DialogWindow(). Разница то что новые API конфигурируются в init блоке до показа UI.
#compose #kmp
Please open Telegram to view this post
VIEW IN TELEGRAM
This media is not supported in your browser
VIEW IN TELEGRAM
Решение использует dev сборки Jetpack Navigation 3 для Compose Multiplatform
#compose #jetpack #navigation3 #cmp #kmp
Please open Telegram to view this post
VIEW IN TELEGRAM
Что нового:
👉 Основано на Jetpack Compose 1.9.3
👉 Артефакт compose.material3 теперь основывается на Jetpack Compose Material3 1.4.0, чтобы использовать предыдушую версию, то надо подключать зависимость традиционным образом
// было
implementation(compose.material3)
// заменить для совместимости
implementation("org.jetbrains.compose.material3:material3:1.8.2")
👉 Исправление багов на iOS
#compose #cmp #kmp
Please open Telegram to view this post
VIEW IN TELEGRAM
#compose #kmp #cmp
Please open Telegram to view this post
VIEW IN TELEGRAM
⚙️ Compose Stability Analyzer включает в себя плагин компилятора, который в рантайме позволяет в логах видеть информацию по рекомпозиции функций. Работает с Kotlin Multiplatform
#compose #производительность #kmp #cmp
@TraceRecomposition
fun MyComposable(...) { ... }
#compose #производительность #kmp #cmp
Тех стек:
👉 Многомодульная архитектура
👉 Metro DI
👉 Coil для показа картинок
👉 Kotlin Coroutines и SerlializationX
👉 Ktor
👉 Jetpack Room
#compose #cmp #kmp #android #ios #desktop #пример #opensource
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Google представила Navigation 3 — совершенно новую библиотеку для навигации в Compose, где управление стеком экранов сводится к простым операциям с списком.
Хорошая новость: JetBrains уже адаптировали её для Compose Multiplatform! В статье на реальном примере показывает, как:
👉 Добавить зависимости Navigation 3 в KMP-проект
👉 Определить маршруты через sealed-интерфейсы с @Serializable
👉 Работать с back stack как с обычным mutable list
👉 Создать адаптивные layouts для разных размеров экранов
Особенно полезно будет:
В статье — чистый код из commonMain с примерами навигации между экранами и реализацией bottom navigation.
#compose #cmp #kmp
Please open Telegram to view this post
VIEW IN TELEGRAM
#compose #cmp #kmp #androidjetpack
Please open Telegram to view this post
VIEW IN TELEGRAM
Появилась реализация навигации под Web-браузер, совместимая с Jetpack Navigation 3 и интегрированная с нативной историей браузера. Автор — Костя Цховребов из JetBrains (KMP-команда).
Теперь Web-приложения на Compose Multiplatform могут работать с привычным поведением браузера: кнопки Back/Forward, корректное управление историей, восстановление состояния и предсказуемая работа нескольких экранов.
Поддерживаются две стратегии навигации:
👉 Chronological - Классическая браузерная модель: линейный переход по посещённым состояниям (Back/Forward).
👉 Hierarchical - Мобильная модель навигации, имитирующая структуру экранов и вложенную иерархию — аналогично Android-приложениям.
🧪 Обе стратегии можно сравнить в онлайн-демо
Пример использования Chronological-навигации
@Composable
fun App() {
val backStack = remember { mutableStateListOf<Any>(Root) }
ChronologicalBrowserNavigation(
backStack = backStack,
saveKey = { key ->
when (key) {
is Root -> buildBrowserHistoryFragment("root")
is Profile -> buildBrowserHistoryFragment(
"profile",
mapOf("id" to key.id.toString())
)
else -> null
}
},
restoreKey = { fragment ->
when (getBrowserHistoryFragmentName(fragment)) {
"root" -> Root
"profile" -> Profile(
getBrowserHistoryFragmentParameters(fragment)
.getValue("id")
?.toInt() ?: error("id is required")
)
else -> null
}
}
)
NavDisplay(backStack) { /* ... */ }
}
Navigation3 Browser кажется важным шагом для формирования единой модели навигации в Compose Multiplatform: Android → Desktop → Web.
Это упростит мультиплатформенную архитектуру и сделает перенос логики между платформами гораздо чище.
#Kotlin #Compose #KMP #CMP #WEB #AndroidJetpack #Jetpack
Please open Telegram to view this post
VIEW IN TELEGRAM
Привет! Вышла стабильная версия Compose Multiplatform 1.10.0 с революционными изменениями для кроссплатформенной разработки. Давайте разберём главные фичи, которые изменят ваш подход к KMP.
🔥 Главная фишки релиз - Preview аннотация теперь работает в коде из commonMain — наконец-то!
// Работает в commonMain!
@Preview
@Composable
fun MyComponentPreview() {
MyTheme {
MyComponent()
}
}
МИГРАЦИЯ! Депрекейт
org.jetbrains.compose.ui.tooling.preview.Preview → переходите на androidx.compose.ui.tooling.preview.Preview👉 Compose Hot Reload встроен в Compose плагин и подключать отдельно больше не нужно
adaptive-navigation3⚠️ Breaking Changes & Миграция
Требования к версиям Kotlin
- Kotlin 2.1.20+ (обязательно из-за Hot Reload)
- Kotlin 2.2+ для native и web платформ
// build.gradle.kts
kotlin {
sourceSets {
commonMain.dependencies {
implementation(compose.ui)
// Заменяем на
implementation("org.jetbrains.compose.ui:ui:1.10.0")
}
}
}
Кто уже обновился? Какие впечатления от Preview в commonMain? Делитесь в комментариях!
#compose #gradle #kmp #android #ios #desktop
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥 Compose Hot Reload 1.0.0 — стабильный релиз!
JetBrains выпустили стабильную версию Compose Hot Reload, и это действительно круто!
Теперь когда меняете код Compose UI → жмете Cmd+S/Ctrl+S → изменения мгновенно применяются в запущенном приложении. Без перезапуска. Без потери state.
Можно добавлять/удалять функции, классы, параметры — практически любые изменения кода работают.
✅ Стабильная версия 1.0.0 — больше не beta
✅ Отдельный плагин НЕ нужен — встроен в Compose Multiplatform 1.10+, работает из коробки (zero configuration)
⚠️ Работает только на JVM Desktop — и вот почему это важно понять:
Почему только JVM Desktop?
Hot Reload требует JetBrains Runtime с DCEVM (Dynamic Code Evolution VM). Обычная JVM умеет перезагружать только тела методов. DCEVM может делать произвольные изменения кода — добавлять поля в классы, менять иерархию, интерфейсы и т.д.
Android и iOS не могут использовать JetBrains Runtime с DCEVM. Поэтому Hot Reload технически невозможен на этих платформах.
💡 Зачем это мобильным разработчикам?
Еще один повод добавить Desktop таргет в ваш KMP проект!
Даже если вы не планируете запускать Desktop версию в прод - это мощный инструмент для разработки:
👉 Быстро итерируете UI на Desktop с Hot Reload
👉 Проверяете изменения
👉 Переносите на Android/iOS
Скорость итераций UI вырастает в разы. Вместо "изменил → собрал → запустил → дождался" получается "изменил → Cmd+S → увидел результат".
Короче: если делаете Compose Multiplatform — попробуйте обязательно. Desktop таргет окупится только ради Hot Reload.
🔗 Подробности в блоге JetBrains и в документации
#Compose #KMP #Desktop #JVM #CMP
JetBrains выпустили стабильную версию Compose Hot Reload, и это действительно круто!
Теперь когда меняете код Compose UI → жмете Cmd+S/Ctrl+S → изменения мгновенно применяются в запущенном приложении. Без перезапуска. Без потери state.
Можно добавлять/удалять функции, классы, параметры — практически любые изменения кода работают.
✅ Стабильная версия 1.0.0 — больше не beta
✅ Отдельный плагин НЕ нужен — встроен в Compose Multiplatform 1.10+, работает из коробки (zero configuration)
⚠️ Работает только на JVM Desktop — и вот почему это важно понять:
Почему только JVM Desktop?
Hot Reload требует JetBrains Runtime с DCEVM (Dynamic Code Evolution VM). Обычная JVM умеет перезагружать только тела методов. DCEVM может делать произвольные изменения кода — добавлять поля в классы, менять иерархию, интерфейсы и т.д.
Android и iOS не могут использовать JetBrains Runtime с DCEVM. Поэтому Hot Reload технически невозможен на этих платформах.
💡 Зачем это мобильным разработчикам?
Еще один повод добавить Desktop таргет в ваш KMP проект!
Даже если вы не планируете запускать Desktop версию в прод - это мощный инструмент для разработки:
👉 Быстро итерируете UI на Desktop с Hot Reload
👉 Проверяете изменения
👉 Переносите на Android/iOS
Скорость итераций UI вырастает в разы. Вместо "изменил → собрал → запустил → дождался" получается "изменил → Cmd+S → увидел результат".
Короче: если делаете Compose Multiplatform — попробуйте обязательно. Desktop таргет окупится только ради Hot Reload.
🔗 Подробности в блоге JetBrains и в документации
#Compose #KMP #Desktop #JVM #CMP
Да, у нас уже есть Jetpack Navigation 3 с официальной поддержкой KMP. Тем не менее авторы Kompass смотрят на проблему иначе, и идея тут любопытная.
Суть в том, что вся навигация строится на чистых редукторах. Любой переход — это
State + Command → State, без побочных эффектов. Вот как это выглядит в коде:// Граф описывает, какие экраны в нём живут и как рендерятся
class MainNavigationGraph : NavigationGraph {
override fun canResolveDestination(id: String) =
id in setOf("home", "profile")
@Composable
override fun Content(entry: BackStackEntry, destination: Destination, navController: NavController) {
when (destination) {
is MainDestination.Home -> HomeScreen(navController)
is MainDestination.Profile -> ProfileScreen(navController)
}
}
}
// Хост принимает список графов и рендерит текущий экран
@Composable
fun AppNavigation() {
val navController = rememberNavController(
startDestination = MainDestination.Home
)
KompassNavigationHost(
navController = navController,
graphs = persistentListOf(MainNavigationGraph())
)
}
// Навигация из экрана
navController.navigate(
entry = BackStackEntry(destinationId = "profile", scopeId = newScope())
)
// Возврат с результатом
navController.pop(result = ProfileResult(userId = "123"))
NavigationState и BackStackEntry иммутабельны, поэтому всю навигацию можно покрыть обычными unit-тестами без инструментации: создаёшь NavigationHandler, кидаешь команду, проверяешь стейт.Особенности:
👉 Таргеты — Android, iOS, Desktop (JVM).
👉 Scopes вместо ViewModel.
rememberScoped<T> живёт ровно пока BackStackEntry в стеке, автоматически чистится при pop.👉 Multi-graph. Несколько независимых графов с собственными лейаутами. Из коробки есть поддержка master-detail для планшетов.
👉 Дип-линки. Через
DeepLinkHandler — типизированный парсинг URI в NavigationCommand.🛠 Библиотека ещё в активной разработке
#KMP #ComposeMultiplatform #Navigation #Kotlin #AndroidDev
Please open Telegram to view this post
VIEW IN TELEGRAM
До сих пор для сеток у нас были только ленивые
LazyVerticalGrid / LazyHorizontalGrid. Но если все элементы уже в памяти (небольшое количество) и нужен точный контроль над расположением ячеек — пригождается новый экспериментальный Grid.// Пример
Grid(config = {
column(100.dp)
column(1.fr) // забирает остаток строки
row(50.dp)
row(80.dp)
gap(8.dp)
}) {
Box(Modifier.gridItem().fillMaxSize()) { ... }
Box(Modifier.gridItem().fillMaxSize()) { ... }
Box(Modifier.gridItem().fillMaxSize()) { ... }
Box(Modifier.gridItem().fillMaxSize()) { ... }
}
Работает на Android и KMP (iOS, Desktop, Web) – общий API
🔗 Документация по Grid
#Compose #KMP #Android #iOS #Desktop #Web #CMP
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Камера в CMP это всегда возня с
expect/actual и тремя платформенными бэкендами. Kamera (бывшая CameraK) закрывает это одним Compose-first слоем: один @Composable-вход, под капотом CameraX на Android, AVFoundation на iOS и JavaCV на Desktop.API реактивный, через состояние. Заводишь
rememberCameraKState(), получаешь StateFlow<CameraKState> c ветками Initializing, Ready(controller, uiState) и Error, и рисуешь превью, когда камера готова:val cameraState by rememberCameraKState(
config = CameraConfiguration(
cameraLens = CameraLens.BACK,
aspectRatio = AspectRatio.RATIO_16_9,
),
)
when (val state = cameraState) {
is CameraKState.Ready -> CameraPreviewView(state.controller)
is CameraKState.Initializing -> CircularProgressIndicator()
is CameraKState.Error -> Text(state.message)
}
Из коробки: зум, вспышка, фонарь, переключение линз (ultra-wide/telephoto на iOS),
takePictureToFile() для прямого сохранения в файл. Сверху плагины, которые сами активируются на Ready: сохранение фото, QR/штрихкоды, OCR, запись видео с pause/resume и лимитом длительности, анализ кадров через analyzer.Главное в 1.0: починили то, что мешало брать в прод. На iOS фронталка отдавала тёмные кадры из-за бага в
MemoryManager, хотя превью выглядело нормально. На Android фото оказывалось кропом вместо настроенного аспекта, теперь что видишь, то и снимаешь. Плюс вычистили утечки корутин в плагинах при ре-ините камеры.‼️ Это молодая 1.0 и по сути проект одного мейнтейнера под Apache-2.0. Блокеры выше жили буквально до вчера, так что 1.0 это точка, где их закрыли, а не годы шлифовки. Desktop тянет JavaCV с нативными либами, это тяжело. Но если нужна камера в CMP без трёх реализаций руками, смотреть стоит.
#Compose #ComposeMultiplatform #KMP
Please open Telegram to view this post
VIEW IN TELEGRAM
DrawBox работала как Android-only с 2021 года. В конце мая вышел
2.0.0-alpha02 с таргетами Android, iOS, JVM/Desktop и WASM. Живая демка работает прямо в браузере без установки.В 2.0 добавили: SVG и JSON экспорт, бесконечный канвас с зумом и паном, выделение и перетаскивание фигур, коннекторы, object eraser и Roborazzi тесты.
Автор написал пост про перенос, и самый ценный кусок там не про KMP. Самая интересная часть - использование MVI. Один
State, Intent на каждое действие, Reducer с (State, Intent) → State. После этого undo/redo - это стек из State, JSON-сериализация практически бесплатна, и логика платформ физически не может разъехаться.#Compose #KMP #ComposeMultiplatform
Please open Telegram to view this post
VIEW IN TELEGRAM
Media is too big
VIEW IN TELEGRAM
37 минут от Sebastian Aigner и Marton Braun (JetBrains) про всё, что вышло за последний год. Хорошо структурированный доклад: общие изменения, потом iOS, потом Web.
Ключевое:
👉 Navigation 3 — стабильный в CMP. Бэкстек это просто
SnapshotStateList<NavKey>, которым управляешь сам. Адаптивные Scene-API, нативные iOS-жесты, browser history на Web из коробки.👉 Compose Hot Reload — стабильный, встроен в новые проекты без настройки. Работает и с AI-агентами: IDE подхватывает правки в файлах и перезагружает UI сама.
👉 @Preview унифицировали:
androidx.compose.ui.tooling.preview.Preview теперь работает в commonMain. Прошлые аннотации deprecated.👉 iOS: параллельный render pipeline по умолчанию в 1.11 (+20% на сложных лейаутах),
placedAsOverlay для нативных Liquid Glass-компонентов, полноценный нативный ввод с magnifier / translate / autofill / кастомными IME.👉 Web (beta):
HTMLElementView для HTML прямо в Composition, VoiceOver через семантику, Coil на web workers.👉 Из цифр в докладе: Kuaishou (250M DAU) и Tencent Video (340M MAU) уже работают на CMP-экранах. По iOS-блоку видно, что команда за год реально закрыла большинство «но» для старта
0:00 Вступление: что такое Compose Multiplatform
2:04 Масштаб: Perk, Alipay, Kuaishou, Tencent
4:06 Демо: структура нового проекта
5:40 Compose Hot Reload
8:49 Паритет с Jetpack Compose
10:24 Navigation 3
16:05 Единая аннотация @Preview
17:39 iOS: новый pipeline рендеринга
19:43 iOS: Liquid Glass и overlay interop
27:00 iOS: нативный ввод текста
31:11 Web: HTML interop
33:46 Web: доступность и производительность
35:50 Итоги
#ComposeMultiplatform #KMP #Navigation3 #KotlinConf
Please open Telegram to view this post
VIEW IN TELEGRAM
Плагин через
ComponentMetadataRule подвешивает available-at вариант с tvOS-klib к официальному org.jetbrains.compose.*. Дальше решает штатный variant resolution Gradle: tvOS-таргет забирает форк, а iOS/Android/Desktop продолжают резолвить артефакт JetBrains. Отдельно перехватывается маркер плагина через
pluginManagement.resolutionStrategy.eachPlugin, чтобы работала упаковка Compose Resources.// settings.gradle.kts
plugins {
id("dev.sajidali.compose-tvos") version "1.3.0"
}
Всё,
dependencies {} не меняешь. Приём годится далеко за пределами tvOS: так же можно подсунуть свою пересборку любой чужой библиотеки, у которой не хватает таргета.⚠️ Под капотом форк 15 групп библиотек Compose и AndroidX, опубликованный одним человеком. Автор прямо пишет, что тянет его ровно настолько, насколько нужно для собственного приложения: ни обязательств, ни расписания релизов. Держать
compose.runtime и compose.ui в проде из такого источника решение уровня «мы понимаем, на что подписались». Форк сейчас держит линию 1.12, но догонять апстрим ему придётся рукамиСмотреть стоит ради механики. Тащить в прод - явным фанатам поддержки tvOS из CMP.
#Compose #ComposeMultiplatform #KMP #Gradle
Please open Telegram to view this post
VIEW IN TELEGRAM