Skip to content
37 changes: 37 additions & 0 deletions learning/compose-multiplatform/intro.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
sidebar_position: 1
---

# Compose Multiplatform — обзор

**Compose Multiplatform** (CMP) — фреймворк от JetBrains для декларативного создания пользовательских интерфейсов на Kotlin, работающий на нескольких платформах.

## Поддерживаемые платформы

- **Android** — полноценная поддержка, идентична Jetpack Compose;
- **iOS** — рендеринг через Skia, UI выводится через `ComposeUIViewController`;
- **Desktop (JVM)** — нативные окна через compose-desktop;
- **Web** — экспериментальная поддержка через Canvas.

## Преимущества

- Единый код UI для всех платформ;
- Декларативный реактивный подход (как Jetpack Compose);
- Доступ к платформенным API через `AndroidView` / `UIKitView`;
- Полная совместимость с существующими Kotlin Multiplatform проектами;
- Богатая экосистема: Material3, навигация, анимации.

## Требования

- Kotlin 1.9.0+
- Gradle 6.8+
- Android API 21+
- iOS 12.0+

## Дополнительная информация

- [Официальный сайт](https://www.jetbrains.com/lp/compose-multiplatform/)
- [GitHub репозиторий](https://github.com/JetBrains/compose-multiplatform)
- [Документация JetBrains](https://www.jetbrains.com/help/kotlin-multiplatform-dev/compose-multiplatform-getting-started.html)
- [Compose Multiplatform Resources](https://jetbrains.github.io/compose-multiplatform/)
- [Compose Multiplatform — статься на kotlinlang.org](https://kotlinlang.org/docs/compose-multiplatform.html)
7 changes: 5 additions & 2 deletions learning/compose-multiplatform/links.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Ссылки

- https://johnoreilly.dev/posts/swiftui-component-compose-ios/ - как встроить Compose Multiplatform в SwiftUI ScrollView
- https://gist.github.com/Alex009/6b150b5027a04f9d4d1cf2072b713793 - как сделать QR сканер в Compose Multiplatform
- https://www.jetbrains.com/lp/compose-multiplatform/ — официальный сайт Compose Multiplatform
- https://github.com/JetBrains/compose-multiplatform — GitHub репозиторий
- https://www.jetbrains.com/help/kotlin-multiplatform-dev/compose-multiplatform-getting-started.html — официальное руководство по началу работы
- https://johnoreilly.dev/posts/swiftui-component-compose-ios/ — как встроить Compose Multiplatform в SwiftUI ScrollView
- https://gist.github.com/Alex009/6b150b5027a04f9d4d1cf2072b713793 — как сделать QR сканер в Compose Multiplatform

76 changes: 76 additions & 0 deletions learning/compose-multiplatform/moko-mvvm.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
---
sidebar_position: 3
---

# Compose и moko-mvvm

Библиотеки из экосистемы MOKO предоставляют готовые решения для совместной работы с Compose Multiplatform.

## StateFlow и collectAsState

Данные из `ViewModel` (StateFlow) преобразуются в Compose-состояние через `collectAsState()`:

```kotlin
@Composable
fun UserScreen(viewModel: UserViewModel) {
val user by viewModel.user.collectAsState()

Text("Hello, ${user.name}")
}
```

## moko-mvvm с Compose

`ViewModel` из moko-mvvm не требует специальных адаптеров — достаточно `collectAsState()` для `StateFlow` и `collectAsMutableState()` для двустороннего биндинга:

```kotlin
val (code, onCodeChange) = viewModel.code.data.collectAsMutableState()

AuthCodeContent(
code = code,
onCodeChange = onCodeChange,
codeError = viewModel.code.error.collectAsState().value?.localized()
)
```

## BindEffect

Для привязки контроллеров к жизненному циклу Compose используйте `BindEffect`:

```kotlin
@Composable
fun Sample(viewModel: PermissionsViewModel) {
BindEffect(viewModel.permissionsController)
// ...
}
```

Поддерживается для:
- `PermissionsController` из `moko-permissions`;
- `MediaPickerController` из `moko-media`;
- `LocationTracker` из `moko-geo`;

## remember-фабрики

Для создания экземпляров контроллеров внутри `@Composable` используются фабрики:

```kotlin
@Composable
fun Sample() {
val factory = rememberMediaPickerControllerFactory()
val picker = remember(factory) { factory.createMediaPickerController() }

BindMediaPickerEffect(picker)
}
```

Доступные фабрики:
- `rememberPermissionsControllerFactory()` — из `moko-permissions-compose`;
- `rememberMediaPickerControllerFactory()` — из `moko-media-compose`;
- `PermissionsControllerFactory` — для кастомной конфигурации.

## Дополнительная информация

- [moko-mvvm](https://github.com/icerockdev/moko-mvvm)
- [moko-permissions](https://github.com/icerockdev/moko-permissions)
- [moko-media](https://github.com/icerockdev/moko-media)
113 changes: 113 additions & 0 deletions learning/compose-multiplatform/platform-integration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
---
sidebar_position: 4
---

# Compose и интеграция с платформой

Compose Multiplatform предоставляет механизмы для встраивания платформенных компонентов в Compose UI и наоборот — встраивания Compose в существующие UIKit/SwiftUI проекты.

## AndroidView

Для использования Android View внутри Compose:

```kotlin
@Composable
fun CameraPreview(modifier: Modifier = Modifier) {
AndroidView(
factory = { context ->
PreviewView(context).apply {
layoutParams = ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
)
scaleType = PreviewView.ScaleType.FILL_CENTER
}
},
modifier = modifier
)
}
```

## UIKitView (iOS)

Для встраивания UIKit компонентов в Compose на iOS:

```kotlin
@Composable
fun NativeMap(modifier: Modifier = Modifier) {
UIKitView(
factory = { MKMapView() },
modifier = modifier
)
}
```

## ComposeUIViewController (iOS)

Для встраивания Compose UI в существующий UIKit/SwiftUI проект используется `ComposeUIViewController`:

```kotlin
fun MainViewController() = ComposeUIViewController {
MaterialTheme {
Greeting("iOS")
}
}
```

В SwiftUI оборачивается через `UIViewControllerRepresentable`:

```swift
struct ComposeView: UIViewControllerRepresentable {
func makeUIViewController(context: Context) -> UIViewController {
MainViewControllerKt.MainViewController()
}

func updateUIViewController(_ uiViewController: UIViewController, context: Context) {}
}
```

## Compose внутри SwiftUI ScrollView

При встраивании Compose компонента в SwiftUI `ScrollView` необходимо явно указывать высоту, так как `UIViewControllerRepresentable` не определяет свой размер автоматически.

Используйте `onGloballyPositioned` в Compose для измерения и колбэк высоты в SwiftUI:

```kotlin
// Kotlin
fun ViewController(onHeightChanged: (Int) -> Unit) = ComposeUIViewController {
Column(modifier = Modifier.onGloballyPositioned { coordinates ->
onHeightChanged(coordinates.size.height)
}) {
// содержимое
}
}
```

```swift
// SwiftUI
struct ComponentView: UIViewControllerRepresentable {
@Binding var measuredHeight: CGFloat

func makeUIViewController(context: Context) -> UIViewController {
ViewControllerKt.ViewController { height in
let scale = UIScreen.main.scale
measuredHeight = CGFloat(height) / scale
}
}

func updateUIViewController(_ uiViewController: UIViewController, context: Context) {}
}

// В SwiftUI ScrollView
ScrollView {
ComponentView(measuredHeight: $measuredHeight)
.frame(height: measuredHeight)
}
```

## Дополнительная информация

- [Compose iOS Integration](https://www.jetbrains.com/help/kotlin-multiplatform-dev/compose-multiplatform-ios.html)
- [AndroidView](https://developer.android.com/reference/kotlin/androidx/compose/ui/viewinterop/AndroidView)
- [UIKitView](https://jetbrains.github.io/compose-multiplatform/kotlin/multiplatform/ios/UIKitView)
- [SwiftUI Integration Guide](https://johnoreilly.dev/posts/swiftui-component-compose-ios/) — John O'Reilly
128 changes: 128 additions & 0 deletions learning/compose-multiplatform/setup.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
---
sidebar_position: 2
---

# Подключение и настройка

## Плагин Compose Multiplatform

Для подключения Compose Multiplatform используется официальный Gradle-плагин `org.jetbrains.compose`.

```kotlin
plugins {
kotlin("multiplatform")
id("org.jetbrains.compose")
id("org.jetbrains.kotlin.plugin.compose") // Kotlin Compose compiler plugin
}
```

Версия плагина задаётся в `gradle.properties` или `build.gradle.kts`:

```kotlin
// build.gradle.kts
plugins {
kotlin("multiplatform") version "2.0.21"
id("org.jetbrains.compose") version "1.7.3"
id("org.jetbrains.kotlin.plugin.compose") version "2.0.21"
}
```

## Подключение модулей

```kotlin
kotlin {
androidTarget()
listOf(iosX64(), iosArm64(), iosSimulatorArm64()).forEach { iosTarget ->
iosTarget.binaries.framework {
baseName = "shared"
isStatic = true
}
}

sourceSets {
commonMain.dependencies {
implementation(compose.runtime)
implementation(compose.foundation)
implementation(compose.material3)
implementation(compose.ui)
}

androidMain.dependencies {
implementation(compose.preview)
implementation("androidx.activity:activity-compose:1.9.3")
}
}
}
```

## Android

В Android Activity используйте `setContent`:

```kotlin
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MaterialTheme {
Greeting("Android")
}
}
}
}
```

## iOS

На iOS Compose UI выводится через `ComposeUIViewController`:

```kotlin
// commonMain
fun MainViewController() = ComposeUIViewController {
MaterialTheme {
Greeting("iOS")
}
}
```

```swift
// iOS App
import SwiftUI
import shared

struct ComposeView: UIViewControllerRepresentable {
func makeUIViewController(context: Context) -> UIViewController {
MainViewControllerKt.MainViewController()
}

func updateUIViewController(_ uiViewController: UIViewController, context: Context) {}
}

@main
struct iOSApp: App {
var body: some Scene {
WindowGroup {
ComposeView().ignoresSafeArea()
}
}
}
```

## Desktop

```kotlin
// jvmMain
fun main() = application {
Window(title = "Compose Desktop", state = rememberWindowState()) {
MaterialTheme {
Greeting("Desktop")
}
}
}
```

## Дополнительная информация

- [Getting Started — официальное руководство](https://www.jetbrains.com/help/kotlin-multiplatform-dev/compose-multiplatform-getting-started.html)
- [Compose Multiplatform — Tutorials](https://github.com/JetBrains/compose-multiplatform/tree/master/tutorials)
- [Настройка iOS в Compose Multiplatform](https://www.jetbrains.com/help/kotlin-multiplatform-dev/compose-multiplatform-ios.html)
Loading
Loading