-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Initially copy and adapt more ViewModel code from Compose Multiplatform
The added code in the "common" module is temporarily commented out to see whether it's necessary. Under such a condition, an exception is thrown with the message "No ViewModelStoreOwner was provided via LocalViewModelStoreOwner" on JS DOM in an internal app but not in the demo.
- Loading branch information
Showing
7 changed files
with
223 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
25 changes: 25 additions & 0 deletions
25
common/src/jsMain/kotlin/com/huanshankeji/compose/ui/platform/DefaultViewModelOwnerStore.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package com.huanshankeji.compose.ui.platform | ||
|
||
/* | ||
// copied and adapted from "DefaultViewModelOwnerStore.skiko.kt" in `androidx.compose.ui.platform` | ||
import androidx.compose.runtime.Composable | ||
import androidx.compose.runtime.InternalComposeApi | ||
import androidx.compose.runtime.staticCompositionLocalOf | ||
import androidx.lifecycle.ViewModelStoreOwner | ||
/** | ||
* Internal helper to provide [ViewModelStoreOwner] from Compose UI module. | ||
* In applications please use [androidx.lifecycle.viewmodel.compose.LocalViewModelStoreOwner]. | ||
* | ||
* @hide | ||
*/ | ||
internal val LocalInternalViewModelStoreOwner = staticCompositionLocalOf<ViewModelStoreOwner?> { | ||
null | ||
} | ||
@InternalComposeApi | ||
@Composable | ||
fun findComposeDefaultViewModelStoreOwner(): ViewModelStoreOwner? = | ||
LocalInternalViewModelStoreOwner.current | ||
*/ |
28 changes: 28 additions & 0 deletions
28
common/src/jsMain/kotlin/com/huanshankeji/compose/ui/window/ComposeWindow.js.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package com.huanshankeji.compose.ui.window | ||
|
||
/* | ||
import androidx.compose.runtime.Composable | ||
import androidx.compose.runtime.Composition | ||
import androidx.compose.runtime.CompositionLocalProvider | ||
import com.huanshankeji.compose.ui.platform.LocalInternalViewModelStoreOwner | ||
import org.jetbrains.compose.web.dom.DOMScope | ||
import org.jetbrains.compose.web.renderComposableInBody | ||
import org.w3c.dom.HTMLBodyElement | ||
// TODO not used yet so made private | ||
private fun renderComposableInBodyWithLifecycle( | ||
content: @Composable DOMScope<HTMLBodyElement>.() -> Unit | ||
): Composition = | ||
renderComposableInBody { | ||
// copied and adapted from `ComposeWindow` in "ComposeWindow.web.kt" in `androidx.compose.ui.window` | ||
// also see `ComposeViewport` on Wasm JS | ||
CompositionLocalProvider( | ||
//LocalSystemTheme provides systemThemeObserver.currentSystemTheme.value, // TODO add back if needed one day | ||
//LocalLifecycleOwner provides this, // TODO | ||
LocalInternalViewModelStoreOwner provides TODO(), | ||
content = { | ||
content() | ||
} | ||
) | ||
} | ||
*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,56 @@ | ||
package com.huanshankeji.androidx.lifecycle.viewmodel.compose | ||
|
||
import androidx.compose.runtime.Composable | ||
import androidx.lifecycle.HasDefaultViewModelProviderFactory | ||
import androidx.lifecycle.ViewModel | ||
import androidx.lifecycle.ViewModelProvider | ||
import androidx.lifecycle.ViewModelStoreOwner | ||
import androidx.lifecycle.viewmodel.CreationExtras | ||
import kotlin.reflect.KClass | ||
|
||
// https://www.jetbrains.com/help/kotlin-multiplatform-dev/compose-viewmodel.html | ||
|
||
// copied and adapted from "ViewModel.kt" in `androidx.lifecycle.viewmodel.compose` | ||
|
||
|
||
// `expect` can be removed if `expect object LocalViewModelStoreOwner` is added. | ||
@PublishedApi | ||
@Composable | ||
internal expect fun defaultViewModelStoreOwner(): ViewModelStoreOwner | ||
|
||
@PublishedApi | ||
internal fun ViewModelStoreOwner.defaultCreationExtras(): CreationExtras = | ||
if (this is HasDefaultViewModelProviderFactory) { | ||
this.defaultViewModelCreationExtras | ||
} else { | ||
CreationExtras.Empty | ||
} | ||
|
||
|
||
@Composable | ||
expect fun <VM : ViewModel> viewModel( | ||
modelClass: KClass<VM>, | ||
viewModelStoreOwner: ViewModelStoreOwner = defaultViewModelStoreOwner(), | ||
key: String? = null, | ||
factory: ViewModelProvider.Factory? = null, | ||
extras: CreationExtras = viewModelStoreOwner.defaultCreationExtras() | ||
): VM | ||
|
||
@Composable | ||
expect inline fun <reified VM : ViewModel> viewModel( | ||
viewModelStoreOwner: ViewModelStoreOwner = defaultViewModelStoreOwner(), | ||
key: String? = null, | ||
noinline initializer: CreationExtras.() -> VM | ||
): VM | ||
|
||
@Deprecated( | ||
"Use the one with a `viewModelStoreOwner` parameter instead. " + | ||
"This function might be removed in the future. " + | ||
"Make sure you call this function with named arguments please so your source still compile when this is removed." | ||
) | ||
@Composable | ||
inline fun <reified VM : ViewModel> viewModel( | ||
key: String? = null, | ||
noinline initializer: CreationExtras.() -> VM | ||
): VM = | ||
viewModel(defaultViewModelStoreOwner(), key, initializer) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
26 changes: 26 additions & 0 deletions
26
lifecycle-viewmodel/src/jsMain/kotlin/LocalViewModelStoreOwner.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package com.huanshankeji.androidx.lifecycle.viewmodel.compose | ||
|
||
import androidx.compose.runtime.Composable | ||
import androidx.compose.runtime.ProvidedValue | ||
import androidx.compose.runtime.compositionLocalOf | ||
import androidx.lifecycle.ViewModelStoreOwner | ||
|
||
// copied and adapted from "LocalViewModelStoreOwner.kt" and "LocalViewModelStoreOwner.jb.kt" in `androidx.lifecycle.viewmodel.compose` | ||
|
||
object LocalViewModelStoreOwner { | ||
private val LocalViewModelStoreOwner = | ||
compositionLocalOf<ViewModelStoreOwner?> { null } | ||
val current: ViewModelStoreOwner? | ||
@Composable | ||
get() = LocalViewModelStoreOwner.current ?: findViewTreeViewModelStoreOwner() | ||
|
||
infix fun provides(viewModelStoreOwner: ViewModelStoreOwner): | ||
ProvidedValue<ViewModelStoreOwner?> { | ||
return LocalViewModelStoreOwner.provides(viewModelStoreOwner) | ||
} | ||
} | ||
|
||
@Composable | ||
internal fun findViewTreeViewModelStoreOwner(): ViewModelStoreOwner? = | ||
// TODO | ||
null //findComposeDefaultViewModelStoreOwner() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,74 @@ | ||
package com.huanshankeji.androidx.lifecycle.viewmodel.compose | ||
|
||
import androidx.compose.runtime.Composable | ||
import androidx.compose.runtime.remember | ||
import androidx.lifecycle.HasDefaultViewModelProviderFactory | ||
import androidx.lifecycle.ViewModel | ||
import androidx.lifecycle.ViewModelProvider | ||
import androidx.lifecycle.ViewModelStoreOwner | ||
import androidx.lifecycle.viewmodel.CreationExtras | ||
import androidx.lifecycle.viewmodel.initializer | ||
import androidx.lifecycle.viewmodel.viewModelFactory | ||
import kotlin.reflect.KClass | ||
|
||
// copied and adapted from "ViewModel.kt" in `androidx.lifecycle.viewmodel.compose` | ||
|
||
|
||
|
||
@PublishedApi | ||
@Composable | ||
internal actual fun defaultViewModelStoreOwner(): ViewModelStoreOwner = | ||
checkNotNull(LocalViewModelStoreOwner.current) { | ||
"No ViewModelStoreOwner was provided via LocalViewModelStoreOwner" | ||
} | ||
|
||
|
||
@Composable | ||
actual inline fun <reified VM : ViewModel> viewModel(key: String?, noinline initializer: CreationExtras.() -> VM): VM = | ||
actual fun <VM : ViewModel> viewModel( | ||
modelClass: KClass<VM>, | ||
viewModelStoreOwner: ViewModelStoreOwner, | ||
key: String?, | ||
factory: ViewModelProvider.Factory?, | ||
extras: CreationExtras | ||
): VM = viewModelStoreOwner.get(modelClass, key, factory, extras) | ||
|
||
@Composable | ||
actual inline fun <reified VM : ViewModel> viewModel( | ||
viewModelStoreOwner: ViewModelStoreOwner, | ||
key: String?, | ||
noinline initializer: CreationExtras.() -> VM | ||
): VM = viewModel( | ||
VM::class, | ||
viewModelStoreOwner, | ||
key, | ||
viewModelFactory { initializer(initializer) }, | ||
viewModelStoreOwner.defaultCreationExtras() | ||
) | ||
|
||
// TODO remove | ||
/* | ||
@Composable | ||
actual inline fun <reified VM : ViewModel> viewModel( | ||
viewModelStoreOwner: ViewModelStoreOwner, key: String?, noinline initializer: CreationExtras.() -> VM | ||
): VM = | ||
remember(key) { CreationExtras.Empty.initializer() } | ||
*/ | ||
|
||
internal fun <VM : ViewModel> ViewModelStoreOwner.get( | ||
modelClass: KClass<VM>, | ||
key: String?, | ||
factory: ViewModelProvider.Factory?, | ||
extras: CreationExtras | ||
): VM { | ||
val provider = if (factory != null) { | ||
ViewModelProvider.create(this.viewModelStore, factory, extras) | ||
} else if (this is HasDefaultViewModelProviderFactory) { | ||
ViewModelProvider.create(this.viewModelStore, this.defaultViewModelProviderFactory, extras) | ||
} else { | ||
ViewModelProvider.create(this) | ||
} | ||
return if (key != null) { | ||
provider[key, modelClass] | ||
} else { | ||
provider[modelClass] | ||
} | ||
} |