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
iOS SingleLayerComposeScene with feature flag #920
iOS SingleLayerComposeScene with feature flag #920
Conversation
} | ||
|
||
internal fun getUITextInputTraits(currentImeOptions: ImeOptions?) = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Copied it as is
when (currentImeOptions?.keyboardType) { | ||
KeyboardType.Password, KeyboardType.NumberPassword -> UITextContentTypePassword | ||
KeyboardType.Email -> UITextContentTypeEmailAddress | ||
KeyboardType.Phone -> UITextContentTypeTelephoneNumber | ||
else -> null | ||
} | ||
|
||
override fun isSecureTextEntry(): Boolean = | ||
when (currentImeOptions?.keyboardType) { | ||
KeyboardType.Password, KeyboardType.NumberPassword -> true | ||
else -> false | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It fixes password TextField issue JetBrains/compose-multiplatform#2988
textUIView = IntermediateTextInputUIView( | ||
keyboardEventHandler = keyboardEventHandler, | ||
).also { | ||
rootView.addSubview(it) | ||
it.translatesAutoresizingMaskIntoConstraints = false | ||
NSLayoutConstraint.activateConstraints( | ||
listOf( | ||
it.leftAnchor.constraintEqualToAnchor(rootView.leftAnchor), | ||
it.rightAnchor.constraintEqualToAnchor(rootView.rightAnchor), | ||
it.topAnchor.constraintEqualToAnchor(rootView.topAnchor), | ||
it.bottomAnchor.constraintEqualToAnchor(rootView.bottomAnchor), | ||
).also { | ||
constraints = it | ||
} | ||
) | ||
} | ||
textUIView?.input = createSkikoInput(value) | ||
textUIView?.inputTraits = getUITextInputTraits(imeOptions) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
textUIView it is invisible UIView with userInteraction=false.
But this textUIView can becomeFirstResponder() when Compose TextField comes to focus.
constraints?.let { | ||
NSLayoutConstraint.deactivateConstraints(it) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we can not deactivateConstraints when view removes from super view?
But I think it is good to have explicit deactivation code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Constraints across the boundaries of detachment point are deactivated automatically.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removed this code
_showSoftwareKeyboard() | ||
textUIView?.let { | ||
focusStack.pushAndFocus(it) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Keyboard appearence logic goes to FocusStack
@ExperimentalComposeApi | ||
var platformLayers: Boolean = false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Temporary experimental feature flag.
When we fully migrates to SingleLayerComposeScene, this flag will be removed
internal class IntermediateTextInputUIView( | ||
private val keyboardEventHandler: KeyboardEventHandler, | ||
) : UIView(frame = CGRectZero.readValue()), | ||
UIKeyInputProtocol, UITextInputProtocol { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This IntermediateTextInputUIView helps to solve password TextField problem.
Now when Compose TextField will be focused - this IntermediateTextInputUIView will be created. And removed after unfocus.
So, each new TextField keyboard behavior will be configured from scratch without cahces.
Almost all of implementation just moved from SkikoUIView. (Previously SkikoUIView was implement this behavior)
fun keyboardWillHide(arg: NSNotification) | ||
} | ||
|
||
internal class KeyboardVisibilityListenerImpl( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Implementation of this class just copied moved from ComposeWindow.kt
@@ -191,6 +191,7 @@ internal class InflightCommandBuffers( | |||
internal class MetalRedrawer( | |||
private val metalLayer: CAMetalLayer, | |||
private val callbacks: MetalRedrawerCallbacks, | |||
private val transparentBackground: Boolean, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need transparentBackground for transparent Dialogs (with rounded corners for example) and Popup's like TextFieldSelectionHandle
.
But first root ComposeScene will be rendered opaque by default. It will be transparent only with usage of UIKitView as before.
import platform.UIKit.UIView | ||
import platform.UIKit.UIViewController | ||
|
||
internal interface RootViewControllerState<RootView, SceneView> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need generics for smoother migration from UIView as scene view representation to UIViewController
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's add TODO/comment that this is temporary for transition
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We decided to remove generic params. And just inlined UIViewController as RootView and UIView as SceneView
And naming also changes to Bridges suffix
compose/ui/ui/src/uikitMain/kotlin/androidx/compose/ui/window/IntermediateTextInputUIView.kt
Outdated
Show resolved
Hide resolved
compose/ui/ui/src/uikitMain/kotlin/androidx/compose/ui/window/IntermediateTextInputUIView.kt
Outdated
Show resolved
Hide resolved
private fun IntRange.toUITextRange(): UITextRange = | ||
IntermediateTextRange(start = start, end = endInclusive + 1) | ||
|
||
private fun NSWritingDirection.directionToStr() = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
toString?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is Long type. So better to stay it directionToStr()
compose/ui/ui/src/uikitMain/kotlin/androidx/compose/ui/window/IntermediateTextInputUIView.kt
Outdated
Show resolved
Hide resolved
compose/ui/ui/src/uikitMain/kotlin/androidx/compose/ui/window/LayerState.kt
Outdated
Show resolved
Hide resolved
var input: IOSSkikoInput? = null | ||
var inputTraits: SkikoUITextInputTraits = object : SkikoUITextInputTraits {} | ||
var onAttachedToWindow: (() -> Unit)? = null | ||
private val _isReadyToShowContent: MutableState<Boolean> = mutableStateOf(false) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As discussed - it's better to get rid of compose state primitives inside such classes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For now it is better to leave it here
compose/ui/ui/src/uikitMain/kotlin/androidx/compose/ui/window/SkikoUIView.kt
Outdated
Show resolved
Hide resolved
compose/ui/ui/src/uikitMain/kotlin/androidx/compose/ui/window/SkikoUIViewDelegate.kt
Outdated
Show resolved
Hide resolved
// The calculation is split in two instead of | ||
// `(targetTimestamp * 1e9).toLong()` | ||
// to avoid losing precision for fractional part |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please extract such things to separate functions. It should not be right in the render
function
compose/ui/ui/src/uikitMain/kotlin/androidx/compose/ui/window/SkikoUIViewDelegate.kt
Outdated
Show resolved
Hide resolved
compose/ui/ui/src/uikitMain/kotlin/androidx/compose/ui/window/CreateSceneState.kt
Outdated
Show resolved
Hide resolved
This comment was marked as resolved.
This comment was marked as resolved.
|
||
internal class IOSPlatformContextImpl( | ||
inputServices: PlatformTextInputService, | ||
override val textToolbar: TextToolbar, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like it's always the same as the first parameter
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, but it is different interfaces. So better to pass it as is.
compose/ui/ui/src/uikitMain/kotlin/androidx/compose/ui/window/ComposeUIViewController.uikit.kt
Outdated
Show resolved
Hide resolved
compose/ui/ui/src/uikitMain/kotlin/androidx/compose/ui/window/ComposeUIViewController.uikit.kt
Outdated
Show resolved
Hide resolved
compose/ui/ui/src/uikitMain/kotlin/androidx/compose/ui/window/ComposeSceneMediator.uikit.kt
Outdated
Show resolved
Hide resolved
24334fd
to
76cfbe7
Compare
Added basic iOS implementation for
SingleLayerComposeScene
.Added feature flag to turn it on:
Where are known bug with device rorattion and touch handling.
We need to merge this changes for future cooperative work. This PR contains big architecture changes in iOS
ui:ui
module.By default feauture flag is turned off. And stable way to layout Popups and Dialogs will be used.
Also fixes Issue with password TextField (JetBrains/compose-multiplatform#2988)