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

Revamp interop API to align it with Android and make it reusable #1489

Merged
merged 72 commits into from
Aug 12, 2024

Conversation

elijah-semyonov
Copy link

@elijah-semyonov elijah-semyonov commented Aug 5, 2024

Refactor interop API on iOS and Desktop to make it aligned with AndroidView

  • Make an InteropViewHolder a type responsible for configuring and emitting a LayoutNode associated with interop view.
  • Introduce a TypedInteropViewHolder that allows type-bound user-provided callbacks to run and be correctly updated in the scope of InteropViewHolder.
  • Introduce an InteropView composable function as an entry point for all interop implementations.
  • Merge SwingInteropViewHolder and SwingInteropViewHolder2 and wire them with TypedInteropViewHolder.
  • Delete InteropViewUpdater and use interop container resident SnapshotObserver to track updates read by InteropViewHolder.
  • Change Swing update scheduling mechanics to batch them and then synchronously execute along with rendering sequence.
  • Rewire iOS implementation to use of InteropView with UIKitInteropViewControllerHolder, UIKitInteropViewHolder, and UIKitInteropElementHolder containing common parts of former two.
  • Tie UIViewController containment calls with place/unplace.

Release notes

iOS - Breaking changes

  • Actual of expected InteropView on iOS is UIResponder now instead of UIView. It's the first common ancestor for UIViewController and UIView, both of which can be integrated using iOS interop APIs.

@elijah-semyonov elijah-semyonov self-assigned this Aug 5, 2024
@igordmn igordmn removed their request for review August 5, 2024 14:50
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.Density

private val NoOp: Any.() -> Unit = {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is it explicitly scoped to Any. ?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just copied this:

private val STUB_CALLBACK_WITH_RECEIVER: Any.() -> Unit = {}

Is there a better way?

@elijah-semyonov elijah-semyonov marked this pull request as ready for review August 6, 2024 15:18
@elijah-semyonov elijah-semyonov force-pushed the es/commonize-interop-factory-API branch from 0da8553 to a06a6a1 Compare August 8, 2024 09:04
@elijah-semyonov elijah-semyonov changed the title Commonize interop API to align it with Android and make it reusable Revamp interop API to align it with Android and make it reusable Aug 9, 2024
@igordmn
Copy link
Collaborator

igordmn commented Aug 9, 2024

The scheduling code LGTM 👍

@elijah-semyonov
Copy link
Author

Waiting for CI then

@elijah-semyonov
Copy link
Author

CI is green.
@igordmn @MatkovIvan
Awaiting an approval then and let's merge it.


body()
} finally {
synchronized(lock) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mutex for bool seems as overkill. Can it be just atomic?

Copy link
Author

@elijah-semyonov elijah-semyonov Aug 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, access to both needsRequestRedrawOnUpdateScheduled, scheduled is the same critical section.

* Callback to be invoked when the layout of the interop view changes to notify the system
* that something has changed.
*/
fun onInteropViewLayoutChange(holder: InteropViewHolder)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at a way how scheduleUpdate is written on Desktop, having this separate method is questionable again. I doubt that this method is required even on Android. Do you know if implementation of scheduleUpdate will be enough for Android?

Since it's no-op for all platforms, let's comment it out with TODO (please restore TODO about Owner and merge with it)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at a way how scheduleUpdate is written on Desktop, having this separate method is questionable again. I doubt that this method is required even on Android. Do you know if implementation of scheduleUpdate will be enough for Android?

Yes, I think so. If it's not enough, we will iterate on it.

Since it's no-op for all platforms, let's comment it out with TODO (please restore TODO about Owner and merge with it)

Done.

internal fun Modifier.interopViewSemantics(enabled: Boolean, interopViewHolder: InteropViewHolder) =
if (enabled) {
this.semantics { interopView = interopViewHolder.group as UIKitInteropViewGroup }
internal fun Modifier.nativeAccessibility(isEnabled: Boolean, interopWrappingView: InteropWrappingView) =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: align "platform" vs "native" naming

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@elijah-semyonov elijah-semyonov merged commit 7a2dea8 into jb-main Aug 12, 2024
6 checks passed
@elijah-semyonov elijah-semyonov deleted the es/commonize-interop-factory-API branch August 12, 2024 11:57
mazunin-v-jb pushed a commit that referenced this pull request Aug 14, 2024
Refactor interop API on iOS and Desktop to make it aligned with
`AndroidView`

- Make an `InteropViewHolder` a type responsible for configuring and
emitting a `LayoutNode` associated with interop view.
- Introduce a `TypedInteropViewHolder` that allows type-bound
user-provided callbacks to run and be correctly updated in the scope of
`InteropViewHolder`.
- Introduce an `InteropView` composable function as an entry point for
all interop implementations.
- Merge `SwingInteropViewHolder` and `SwingInteropViewHolder2` and wire
them with `TypedInteropViewHolder`.
- Delete `InteropViewUpdater` and use interop container resident
`SnapshotObserver` to track updates read by `InteropViewHolder`.
- Change Swing update scheduling mechanics to batch them and then
synchronously execute along with rendering sequence.
- Rewire iOS implementation to use of `InteropView` with
`UIKitInteropViewControllerHolder`, `UIKitInteropViewHolder`, and
`UIKitInteropElementHolder` containing common parts of former two.
- Tie `UIViewController` containment calls with `place`/`unplace`.

## Release notes

### iOS - Breaking changes

- Actual of expected `InteropView` on iOS is `UIResponder` now instead
of `UIView`. It's the first common ancestor for `UIViewController` and
`UIView`, both of which can be integrated using iOS interop APIs.

---------

Co-authored-by: Ivan Matkov <ivan.matkov@jetbrains.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants