Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

What's New in Compose Multiplatform 1.8.0 beta-02 #328

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
127 changes: 99 additions & 28 deletions topics/whats-new/whats-new-compose-180.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Here are the highlights for this EAP feature release:
* [Preloading of resources for web targets](#preloading-of-resources)
* [Integration with browser navigation controls](#browser-controls-supported-in-the-navigation-library)

See the full list of changes for this release [on GitHub](https://github.com/JetBrains/compose-multiplatform/blob/master/CHANGELOG.md#180-beta01-march-2025).
See the full list of changes for this release [on GitHub](https://github.com/JetBrains/compose-multiplatform/blob/master/CHANGELOG.md#180-beta02-april-2025).

## Breaking changes

Expand Down Expand Up @@ -68,21 +68,28 @@ composable(Destinations.Followers.route) { navBackStackEntry ->
}
```

### Implementation of `runOnIdle()` aligned with Android
### Deprecated `ComposeUIViewControllerDelegate` on iOS

To bring the Compose Multiplatform implementation of the `runOnIdle()` test function in line with Android behavior,
we introduced the following changes:
The `ComposeUIViewControllerDelegate` API has been deprecated in favor of the parent view controller.
If you use the deprecated API with Compose Multiplatform %composeEapVersion%, you will encounter a deprecation error indicating
that you should override the `UIViewController` class methods via the parent view controller.

* `runOnIdle()` now executes its `action` on the UI thread.
* `runOnIdle()` does not call `waitForIdle()` after executing `action` anymore.
Read more about child-parent view controller relationships in Apple’s developer [documentation](https://developer.apple.com/documentation/uikit/uiviewcontroller).

If your tests rely on that extra `waitForIdle()` call after the `runOnIdle()` action,
add that call to your tests as needed when you update them for Compose Multiplatform %composeEapVersion%.
### Removed obsolete `platformLayers` option on iOS

### New handling of coroutine delays in tests
The `platformLayers`
experimental option [was introduced in 1.6.0](https://www.jetbrains.com/help/kotlin-multiplatform-dev/whats-new-compose.html#separate-platform-views-for-popups-dialogs-and-dropdowns-ios-desktop)
to allow enabling alternative layering mode and drawing popups and dialogs outside the bounds of the parent container.

This mode is now the default behavior on iOS, and the option to enable it has been removed as obsolete.

### Breaking changes in tests

#### New handling of coroutine delays in tests

Previously, Compose Multiplatform tests would not consider side effects with `delay()` calls idle.
Because of that, this test, for example, would hang indefinitely:
Because of that, the following test, for example, would hang indefinitely:

```kotlin
@Test
Expand All @@ -98,10 +105,11 @@ fun loopInLaunchedEffectTest() = runComposeUiTest {
}
```

In Compose Multiplatform %composeEapVersion%, `waitForIdle()`, `awaitIdle()`, and `runOnIdle()` functions consider Compose
to be idle even when coroutines launched in a composition scope call the `delay()` function.
This fixes the hanging test above but breaks tests that rely on `waitForIdle()`, `awaitIdle()`, and `runOnIdle()`
When coroutines call the `delay()` function after being launched in a composition scope, the `waitForIdle()`, `awaitIdle()`,
and `runOnIdle()` functions now consider Compose to be idle.
This change fixes the hanging test above but breaks tests that rely on `waitForIdle()`, `awaitIdle()`, and `runOnIdle()`
to execute coroutines with `delay()`.

To produce the same results in these cases, advance time artificially:

```kotlin
Expand All @@ -117,9 +125,8 @@ setContent {
}
updateText = true
waitForIdle()

// Since waitForIdle() no longer waits for the delayed LaunchedEffect() to complete,
// the test needs to advance time to make the following assertion correct
// the test needs to advance time to make the following assertion correct:
mainClock.advanceTimeBy(1001)

assertEquals("1", text)
Expand All @@ -128,6 +135,25 @@ assertEquals("1", text)
Tests that already use `mainClock.advanceTimeBy()` calls to advance the test clock may behave differently
with recomposition, layout, drawing, and effects.

#### Implementation of `runOnIdle()` aligned with Android

To bring the Compose Multiplatform implementation of the `runOnIdle()` test function in line with Android behavior,
we’ve introduced the following changes:

* `runOnIdle()` now executes its `action` on the UI thread.
* `runOnIdle()` does not call `waitForIdle()` after executing `action` anymore.

If your tests rely on that extra `waitForIdle()` call after the `runOnIdle()` action,
add the call to your tests as needed when you update them for Compose Multiplatform %composeEapVersion%.

#### Advancing time in tests is decoupled from rendering

In Compose Multiplatform %composeEapVersion%, the `mainClock.advanceTimeBy()` function no longer causes recomposition, layout,
or drawing if the time was not advanced past the point of rendering the next frame (virtual test frames are rendered every 16 ms).

This may break tests that rely on rendering being triggered by every `mainClock.advanceTimeBy()` call.
See the [PR description](https://github.com/JetBrains/compose-multiplatform-core/pull/1618) for details.

## Across platforms

### Variable fonts
Expand Down Expand Up @@ -187,19 +213,6 @@ see the [dedicated article](https://developer.android.com/develop/ui/compose/tou
Compose Multiplatform %composeEapVersion% introduces accessibility support for right-to-left languages,
including proper text direction handling for gestures.

#### Loading accessibility tree on demand

Instead of setting a specific mode of syncing the Compose semantic tree with the iOS accessibility tree,
you can now rely on Compose Multiplatform to handle this process lazily:
the tree is fully loaded after the first request from the iOS accessibility engine
and is disposed of when the screen reader stops interacting with it.

This allows fully supporting iOS Voice Control, VoiceOver,
and other accessibility tools that rely on the accessibility tree.

The `AccessibilitySyncOptions` class, which was [used to configure accessibility tree sync](compose-ios-accessibility.md#choose-the-tree-synchronization-option),
has been removed as it is no longer necessary.

#### Accessibility for scrollable lists

This version improves the performance and accuracy of scrolling boundary and element position calculations.
Expand Down Expand Up @@ -268,6 +281,29 @@ ensuring proper accessibility-state representation.

You can now also use accessible text input in UI testing.

#### Support for control via trackpad and keyboard
Compose Multiplatform for iOS now supports two additional input methods to control your device. Instead of relying on the touchscreen,
you can enable either AssistiveTouch to use a mouse or trackpad, or Full Keyboard Access to use a keyboard:

* AssistiveTouch (**Settings** | **Accessibility** | **Touch** | **AssistiveTouch**) allows you to control your iPhone or
iPad with a pointer from a connected mouse or trackpad. You can use the pointer to click icons on your screen,
navigate through the AssistiveTouch menu, or type using the onscreen keyboard.
* Full Keyboard Access (**Settings** | **Accessibility** | **Keyboards** | **Full Keyboard Access**) enables device control
with a connected keyboard. You can navigate with keys like **Tab** and activate items using **Space**.

#### Loading accessibility tree on demand

Instead of setting a specific mode of syncing the Compose semantic tree with the iOS accessibility tree,
you can now rely on Compose Multiplatform to handle this process lazily.
The tree is fully loaded after the first request from the iOS accessibility engine
and is disposed of when the screen reader stops interacting with it.

This allows fully supporting iOS Voice Control, VoiceOver,
and other accessibility tools that rely on the accessibility tree.

The `AccessibilitySyncOptions` class, which was [used to configure accessibility tree sync](compose-ios-accessibility.md#choose-the-tree-synchronization-option),
has been removed as no longer necessary.

#### Improved accuracy of accessibility property calculations

We’ve updated the accessibility properties
Expand All @@ -280,6 +316,12 @@ to fix several issues related to the incorrect calculation of accessibility prop
such as missing hitboxes for `DropDown` elements,
mismatches between visible text and accessibility labels, and incorrect radio button states.

### Stable API for iOS logging

The API that enables operating system logging on iOS is now stable. The `enableTraceOSLog()` function no longer requires
experimental opt-in and now aligns with Android-style logging. This logging provides trace information that can be analyzed
using Xcode Instruments for debugging and performance analysis.

### Opt-in concurrent rendering
<secondary-label ref="Experimental"/>

Expand Down Expand Up @@ -333,9 +375,38 @@ and navigate to a destination directly when the user pastes a URL with the corre
The `window.bindToNavigation()` method has the optional `getBackStackEntryPath` parameter,
which allows you to customize the translation of route strings into URL fragments.

### Setting the browser cursor
<secondary-label ref="Experimental"/>

We introduced an experimental `PointerIcon.Companion.fromKeyword()` function to manage icons that can be used as mouse
pointers on a browser page. By passing a keyword as a parameter, you can specify the type of cursor to display based on the context.
For example, you can assign different pointer icons to select text, open a context menu, or indicate a loading process.

Check out the full list of available [keywords](https://developer.mozilla.org/en-US/docs/Web/CSS/cursor).

## Desktop

### Support for Windows for ARM64

Compose Multiplatform %composeEapVersion% introduces support for Windows for ARM64 on the JVM,
improving the overall experience of building and running applications on ARM-based Windows devices.

## Gradle plugin

### Support for multiplatform resources in the `androidLibrary` target

Starting with the Android Gradle plugin version 8.8.0, you can use generated assets in the new `androidLibrary` target.
To align Compose Multiplatform with these changes, we’ve introduced support for a new target configuration to work with
multiplatform resources packed into Android assets.

If you are using the `androidLibrary` target, enable resources in your configuration:

```
kotlin {
androidLibrary {
experimentalProperties["android.experimental.kmp.enableAndroidResources"] = true
}
}
```

Otherwise, you’ll encounter the following exception: `org.jetbrains.compose.resources.MissingResourceException: Missing resource with path: …`.
2 changes: 1 addition & 1 deletion v.list
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<var name="composeVersion" value="1.7.3" type="string"/>

<var name="composeEapVersion" value="1.8.0-beta01" type="string"/>
<var name="composeEapVersion" value="1.8.0-beta02" type="string"/>

<var name="kotlinVersion" value="2.0.0" type="string"/>

Expand Down