Skip to content

Commit

Permalink
Compose android tv bindings (#202)
Browse files Browse the repository at this point in the history
  • Loading branch information
js-bonin authored Nov 20, 2023
1 parent fea8ccd commit 1335f10
Show file tree
Hide file tree
Showing 29 changed files with 1,367 additions and 1 deletion.
1 change: 1 addition & 0 deletions buildSrc/src/main/kotlin/Project.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ object Project {
const val TRIKOT_VIEWMODELS_DECLARATIVE_SAMPLE_COMMON = ":trikot-viewmodels-declarative:sample:common"
const val TRIKOT_VIEWMODELS_DECLARATIVE_FLOW = ":trikot-viewmodels-declarative-flow:viewmodels-declarative-flow"
const val TRIKOT_VIEWMODELS_DECLARATIVE_COMPOSE_FLOW = ":trikot-viewmodels-declarative-flow:compose-flow"
const val TRIKOT_VIEWMODELS_DECLARATIVE_COMPOSE_TV_FLOW = ":trikot-viewmodels-declarative-flow:compose-tv-flow"
const val TRIKOT_VIEWMODELS_DECLARATIVE_SAMPLE_COMMON_FLOW = ":trikot-viewmodels-declarative-flow:sample:common"
const val TRIKOT_VIEWMODELS_DECLARATIVE_ANNOTATIONS = ":trikot-viewmodels-declarative-annotations:viewmodels-annotations"
const val TRIKOT_VIEWMODELS_DECLARATIVE_COMPILER_CORE = ":trikot-viewmodels-declarative-compiler:viewmodels-declarative-compiler-core"
Expand Down
1 change: 1 addition & 0 deletions buildSrc/src/main/kotlin/Versions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ object Versions {
const val JETPACK_COMPOSE_COMPILER = "1.5.3"
const val JETPACK_COMPOSE_RUNTIME = "1.5.0"
const val JETPACK_COMPOSE_MATERIAL_3 = "1.1.1"
const val JETPACK_COMPOSE_TV = "1.0.0-alpha10"
const val COIL = "2.0.0-rc03"
const val KTLINT = "11.6.1"
const val KOTLINX_SERIALIZATION = "1.6.0"
Expand Down
1 change: 1 addition & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ include(":trikot-viewmodels-declarative:viewmodels-declarative")
include(":trikot-viewmodels-declarative:compose")
include(":trikot-viewmodels-declarative-flow:viewmodels-declarative-flow")
include(":trikot-viewmodels-declarative-flow:compose-flow")
include(":trikot-viewmodels-declarative-flow:compose-tv-flow")
include(":trikot-viewmodels-declarative-annotations:viewmodels-annotations")
include(":trikot-viewmodels-declarative-compiler:viewmodels-declarative-compiler-core")
include(":trikot-viewmodels-declarative-compiler:viewmodels-declarative-compiler-streams")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
public final class com/mirego/trikot/viewmodels/declarative/compose/viewmodel/ComposableSingletons$VMDCheckboxTvKt {
public static final field INSTANCE Lcom/mirego/trikot/viewmodels/declarative/compose/viewmodel/ComposableSingletons$VMDCheckboxTvKt;
public static field lambda-1 Lkotlin/jvm/functions/Function4;
public static field lambda-2 Lkotlin/jvm/functions/Function4;
public fun <init> ()V
public final fun getLambda-1$compose_tv_flow_release ()Lkotlin/jvm/functions/Function4;
public final fun getLambda-2$compose_tv_flow_release ()Lkotlin/jvm/functions/Function4;
}

public final class com/mirego/trikot/viewmodels/declarative/compose/viewmodel/ComposableSingletons$VMDSwitchTvKt {
public static final field INSTANCE Lcom/mirego/trikot/viewmodels/declarative/compose/viewmodel/ComposableSingletons$VMDSwitchTvKt;
public static field lambda-1 Lkotlin/jvm/functions/Function4;
public static field lambda-2 Lkotlin/jvm/functions/Function4;
public fun <init> ()V
public final fun getLambda-1$compose_tv_flow_release ()Lkotlin/jvm/functions/Function4;
public final fun getLambda-2$compose_tv_flow_release ()Lkotlin/jvm/functions/Function4;
}

public final class com/mirego/trikot/viewmodels/declarative/compose/viewmodel/VMDButtonTvKt {
public static final fun VMDButtonTv-121YqSk (Landroidx/compose/ui/Modifier;Lcom/mirego/trikot/viewmodels/declarative/components/VMDButtonViewModel;Landroidx/tv/material3/ButtonGlow;Landroidx/compose/foundation/interaction/MutableInteractionSource;Landroidx/compose/foundation/layout/PaddingValues;Landroidx/tv/material3/ButtonBorder;FLandroidx/tv/material3/ButtonColors;Landroidx/tv/material3/ButtonShape;Landroidx/tv/material3/ButtonScale;Lkotlin/jvm/functions/Function5;Landroidx/compose/runtime/Composer;III)V
}

public final class com/mirego/trikot/viewmodels/declarative/compose/viewmodel/VMDCheckboxTvKt {
public static final fun VMDCheckboxTv (Landroidx/compose/ui/Modifier;Landroidx/compose/ui/Modifier;Lcom/mirego/trikot/viewmodels/declarative/components/VMDToggleViewModel;Landroidx/compose/foundation/interaction/MutableInteractionSource;Landroidx/tv/material3/CheckboxColors;Landroidx/compose/runtime/Composer;II)V
public static final fun VMDCheckboxTv (Landroidx/compose/ui/Modifier;Landroidx/compose/ui/Modifier;Lcom/mirego/trikot/viewmodels/declarative/components/VMDToggleViewModel;Lkotlin/jvm/functions/Function4;Landroidx/compose/foundation/interaction/MutableInteractionSource;Landroidx/tv/material3/CheckboxColors;Landroidx/compose/runtime/Composer;II)V
}

public final class com/mirego/trikot/viewmodels/declarative/compose/viewmodel/VMDSwitchTvKt {
public static final fun VMDSwitchTv (Landroidx/compose/ui/Modifier;Landroidx/compose/ui/Modifier;Lcom/mirego/trikot/viewmodels/declarative/components/VMDToggleViewModel;Landroidx/compose/foundation/interaction/MutableInteractionSource;Landroidx/tv/material3/SwitchColors;Landroidx/compose/runtime/Composer;II)V
public static final fun VMDSwitchTv (Landroidx/compose/ui/Modifier;Landroidx/compose/ui/Modifier;Lcom/mirego/trikot/viewmodels/declarative/components/VMDToggleViewModel;Lkotlin/jvm/functions/Function4;Landroidx/compose/foundation/interaction/MutableInteractionSource;Landroidx/tv/material3/SwitchColors;Landroidx/compose/runtime/Composer;II)V
}

public final class com/mirego/trikot/viewmodels/declarative/compose/viewmodel/VMDTextTvKt {
public static final fun VMDTextTv--4IGK_g (Landroidx/compose/ui/Modifier;Lcom/mirego/trikot/viewmodels/declarative/components/VMDTextViewModel;JJLandroidx/compose/ui/text/font/FontStyle;Landroidx/compose/ui/text/font/FontWeight;Landroidx/compose/ui/text/font/FontFamily;JLandroidx/compose/ui/text/style/TextDecoration;Landroidx/compose/ui/text/style/TextAlign;JIZILjava/util/Map;Lkotlin/jvm/functions/Function1;Landroidx/compose/ui/text/TextStyle;Landroidx/compose/runtime/Composer;III)V
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
plugins {
id("com.android.library")
id("kotlin-android")
id("mirego.publish")
}

group = "com.mirego.trikot"

android {
namespace = "com.mirego.trikot.vmd.flow.compose.tv"
defaultConfig {
compileSdk = Versions.Android.COMPILE_SDK
minSdk = Versions.Android.MIN_SDK
}
buildFeatures {
compose = true
buildConfig = false
}
compileOptions {
sourceCompatibility(JavaVersion.VERSION_17)
targetCompatibility(JavaVersion.VERSION_17)
}
composeOptions {
kotlinCompilerExtensionVersion = Versions.JETPACK_COMPOSE_COMPILER
}
sourceSets.configureEach {
java.srcDirs("src/$name/kotlin")
}
}

dependencies {
implementation(project(Project.TRIKOT_VIEWMODELS_DECLARATIVE_FLOW))
implementation(project(Project.TRIKOT_FOUNDATION))
implementation(project(Project.TRIKOT_VIEWMODELS_DECLARATIVE_COMPOSE_FLOW))
api("androidx.compose.foundation:foundation:${Versions.JETPACK_COMPOSE_RUNTIME}")
api("androidx.compose.material:material:${Versions.JETPACK_COMPOSE_RUNTIME}")
api("androidx.compose.runtime:runtime:${Versions.JETPACK_COMPOSE_RUNTIME}")
api("androidx.compose.ui:ui-tooling:${Versions.JETPACK_COMPOSE_RUNTIME}")
api("androidx.compose.material3:material3:${Versions.JETPACK_COMPOSE_MATERIAL_3}")
api("androidx.lifecycle:lifecycle-viewmodel-compose:2.5.1")
api("androidx.lifecycle:lifecycle-runtime-ktx:2.5.1")
api("io.coil-kt:coil-compose:${Versions.COIL}")
implementation("com.google.accompanist:accompanist-drawablepainter:${Versions.ACCOMPANIST}")
implementation("androidx.appcompat:appcompat:1.5.1")
implementation("org.jetbrains.kotlin:kotlin-reflect:${Versions.KOTLIN}")
implementation("androidx.tv:tv-foundation:${Versions.JETPACK_COMPOSE_TV}")
implementation("androidx.tv:tv-material:${Versions.JETPACK_COMPOSE_TV}")
}

afterEvaluate {
publishing {
publications {
create<MavenPublication>("release") {
from(components["release"])
artifactId = "viewmodels-declarative-compose-tv-flow"
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package com.mirego.trikot.viewmodels.declarative.compose.viewmodel

import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.interaction.collectIsFocusedAsState
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.RowScope
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.tv.material3.Button
import androidx.tv.material3.ButtonBorder
import androidx.tv.material3.ButtonColors
import androidx.tv.material3.ButtonDefaults
import androidx.tv.material3.ButtonGlow
import androidx.tv.material3.ButtonScale
import androidx.tv.material3.ButtonShape
import androidx.tv.material3.ExperimentalTvMaterial3Api
import com.mirego.trikot.viewmodels.declarative.components.VMDButtonViewModel
import com.mirego.trikot.viewmodels.declarative.compose.extensions.isOverridingAlpha
import com.mirego.trikot.viewmodels.declarative.compose.extensions.observeAsState
import com.mirego.trikot.viewmodels.declarative.compose.extensions.vmdModifier
import com.mirego.trikot.viewmodels.declarative.content.VMDContent

@ExperimentalTvMaterial3Api
@Composable
fun <C : VMDContent> VMDButtonTv(
modifier: Modifier = Modifier,
viewModel: VMDButtonViewModel<C>,
glow: ButtonGlow = ButtonDefaults.glow(),
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
contentPadding: PaddingValues = ButtonDefaults.ContentPadding,
border: ButtonBorder = ButtonDefaults.border(),
tonalElevation: Dp = 0.0.dp,
colors: ButtonColors = ButtonDefaults.colors(),
shape: ButtonShape = ButtonDefaults.shape(),
scale: ButtonScale = ButtonDefaults.scale(),
content: @Composable (RowScope.(field: C, isFocused: Boolean) -> Unit)
) {
val buttonViewModel: VMDButtonViewModel<C> by viewModel.observeAsState(excludedProperties = if (modifier.isOverridingAlpha()) listOf(viewModel::isHidden) else emptyList())

val isFocused = interactionSource.collectIsFocusedAsState().value

Button(
modifier = modifier
.vmdModifier(buttonViewModel),
onClick = buttonViewModel.actionBlock,
enabled = buttonViewModel.isEnabled,
glow = glow,
interactionSource = interactionSource,
contentPadding = contentPadding,
border = border,
tonalElevation = tonalElevation,
colors = colors,
shape = shape,
scale = scale,
content = { content(buttonViewModel.content, isFocused) }
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
@file:OptIn(ExperimentalTvMaterial3Api::class)

package com.mirego.trikot.viewmodels.declarative.compose.viewmodel

import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.selection.toggleable
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.tooling.preview.Preview
import androidx.tv.material3.Checkbox
import androidx.tv.material3.CheckboxColors
import androidx.tv.material3.CheckboxDefaults
import androidx.tv.material3.ExperimentalTvMaterial3Api
import androidx.tv.material3.Text
import com.mirego.trikot.viewmodels.declarative.components.VMDToggleViewModel
import com.mirego.trikot.viewmodels.declarative.components.factory.VMDComponents
import com.mirego.trikot.viewmodels.declarative.compose.extensions.isOverridingAlpha
import com.mirego.trikot.viewmodels.declarative.compose.extensions.observeAsState
import com.mirego.trikot.viewmodels.declarative.compose.extensions.vmdModifier
import com.mirego.trikot.viewmodels.declarative.content.VMDContent
import com.mirego.trikot.viewmodels.declarative.content.VMDNoContent
import kotlinx.coroutines.MainScope

@ExperimentalTvMaterial3Api
@Composable
fun VMDCheckboxTv(
modifier: Modifier = Modifier,
componentModifier: Modifier = Modifier,
viewModel: VMDToggleViewModel<VMDNoContent>,
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
colors: CheckboxColors = CheckboxDefaults.colors()
) {
VMDCheckboxTv(
modifier = modifier,
componentModifier = componentModifier,
viewModel = viewModel,
label = {},
interactionSource = interactionSource,
colors = colors
)
}

@Composable
fun <C : VMDContent> VMDCheckboxTv(
modifier: Modifier = Modifier,
componentModifier: Modifier = Modifier,
viewModel: VMDToggleViewModel<C>,
label: @Composable (RowScope.(field: C) -> Unit),
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
colors: CheckboxColors = CheckboxDefaults.colors()
) {
val toggleViewModel: VMDToggleViewModel<C> by viewModel.observeAsState(excludedProperties = if (modifier.isOverridingAlpha()) listOf(viewModel::isHidden) else emptyList())

VMDLabeledComponent(
modifier = modifier
.toggleable(
value = toggleViewModel.isOn,
role = Role.Checkbox,
onValueChange = { checked -> viewModel.onValueChange(checked) },
)
.vmdModifier(toggleViewModel),
label = { label(toggleViewModel.label) },
content = {
Checkbox(
onCheckedChange = null,
modifier = componentModifier,
enabled = toggleViewModel.isEnabled,
checked = toggleViewModel.isOn,
interactionSource = interactionSource,
colors = colors,
)
}
)
}

@Preview
@Composable
private fun EnabledToggleCheckboxPreview() {
val toggleViewModel = VMDComponents.Toggle.withState(true, MainScope())
VMDCheckboxTv(viewModel = toggleViewModel)
}

@Preview
@Composable
private fun DisabledToggleCheckboxPreview() {
val toggleViewModel = VMDComponents.Toggle.withState(false, MainScope())
VMDCheckboxTv(viewModel = toggleViewModel)
}

@Preview
@Composable
private fun SimpleTextToggleCheckboxPreview() {
val toggleViewModel = VMDComponents.Toggle.withText("Label", true, MainScope())
VMDCheckboxTv(viewModel = toggleViewModel, label = { Text(it.text) })
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package com.mirego.trikot.viewmodels.declarative.compose.viewmodel

import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.selection.toggleable
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.tooling.preview.Preview
import androidx.tv.material3.ExperimentalTvMaterial3Api
import androidx.tv.material3.Switch
import androidx.tv.material3.SwitchColors
import androidx.tv.material3.SwitchDefaults
import androidx.tv.material3.Text
import com.mirego.trikot.viewmodels.declarative.components.VMDToggleViewModel
import com.mirego.trikot.viewmodels.declarative.components.factory.VMDComponents
import com.mirego.trikot.viewmodels.declarative.compose.extensions.isOverridingAlpha
import com.mirego.trikot.viewmodels.declarative.compose.extensions.observeAsState
import com.mirego.trikot.viewmodels.declarative.compose.extensions.vmdModifier
import com.mirego.trikot.viewmodels.declarative.content.VMDContent
import com.mirego.trikot.viewmodels.declarative.content.VMDNoContent
import kotlinx.coroutines.MainScope

@ExperimentalTvMaterial3Api
@Composable
fun VMDSwitchTv(
modifier: Modifier = Modifier,
componentModifier: Modifier = Modifier,
viewModel: VMDToggleViewModel<VMDNoContent>,
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
colors: SwitchColors = SwitchDefaults.colors()
) {
VMDSwitchTv(
modifier = modifier,
componentModifier = componentModifier,
viewModel = viewModel,
label = {},
interactionSource = interactionSource,
colors = colors
)
}

@ExperimentalTvMaterial3Api
@Composable
fun <C : VMDContent> VMDSwitchTv(
modifier: Modifier = Modifier,
componentModifier: Modifier = Modifier,
viewModel: VMDToggleViewModel<C>,
label: @Composable (RowScope.(field: C) -> Unit),
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
colors: SwitchColors = SwitchDefaults.colors()
) {
val toggleViewModel: VMDToggleViewModel<C> by viewModel.observeAsState(excludedProperties = if (modifier.isOverridingAlpha()) listOf(viewModel::isHidden) else emptyList())

VMDLabeledComponent(
modifier = modifier
.toggleable(
value = toggleViewModel.isOn,
role = Role.Switch,
onValueChange = { checked -> viewModel.onValueChange(checked) },
)
.vmdModifier(toggleViewModel),
label = { label(toggleViewModel.label) },
content = {
Switch(
modifier = componentModifier,
enabled = toggleViewModel.isEnabled,
checked = toggleViewModel.isOn,
colors = colors,
interactionSource = interactionSource,
onCheckedChange = null
)
}
)
}

@ExperimentalTvMaterial3Api
@Preview
@Composable
private fun EnabledSwitchPreview() {
val toggleViewModel =
VMDComponents.Toggle.withState(true, MainScope())
VMDSwitchTv(viewModel = toggleViewModel)
}

@ExperimentalTvMaterial3Api
@Preview
@Composable
private fun DisabledSwitchPreview() {
val toggleViewModel =
VMDComponents.Toggle.withState(false, MainScope())
VMDSwitchTv(viewModel = toggleViewModel)
}

@ExperimentalTvMaterial3Api
@Preview
@Composable
private fun SimpleTextSwitchPreview() {
val toggleViewModel =
VMDComponents.Toggle.withText("Label", true, MainScope())
VMDSwitchTv(viewModel = toggleViewModel, label = { Text(it.text) })
}
Loading

0 comments on commit 1335f10

Please sign in to comment.