Skip to content

Commit

Permalink
wasm support wip
Browse files Browse the repository at this point in the history
  • Loading branch information
joreilly committed Apr 28, 2024
1 parent 36798c7 commit 8643c4c
Show file tree
Hide file tree
Showing 52 changed files with 1,697 additions and 594 deletions.
1 change: 1 addition & 0 deletions androidApp/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ plugins {
id("com.google.gms.google-services")
id("com.google.firebase.crashlytics")
id("io.github.takahirom.roborazzi")
id("org.jetbrains.compose")
}

configureCompilerOptions()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ fun SpeakersRoute(
when (val state = uiState) {
is SpeakersUiState.Success -> {
if (windowSizeClass.isExpanded) {
SpeakerGridView(state.speakers, component::onSpeakerClicked)
SpeakerGridView(state.conference, state.speakers, component::onSpeakerClicked)
} else {
SpeakerListView(state.speakers, component::onSpeakerClicked)
}
Expand Down
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ tasks.register("quickChecks") {
allprojects {
afterEvaluate {
extensions.findByType<ComposeExtension>()?.apply {
kotlinCompilerPlugin.set("1.5.9-kt-2.0.0-Beta4")
kotlinCompilerPlugin.set("1.5.11-kt-2.0.0-RC1")
}
}
}
1 change: 1 addition & 0 deletions buildSrc/settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pluginManagement {
includeGroupByRegex(".*android.*")
}
}
mavenLocal()
mavenCentral()
gradlePluginPortal()
}
Expand Down
21 changes: 21 additions & 0 deletions compose-desktop/src/main/kotlin/HomeUI.kt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.padding
import androidx.compose.material.BottomNavigation
import androidx.compose.material.BottomNavigationItem
Expand All @@ -7,6 +8,10 @@ import androidx.compose.material.icons.outlined.Home
import androidx.compose.material.icons.outlined.LocationOn
import androidx.compose.material.icons.outlined.Person
import androidx.compose.material.icons.outlined.Search
import androidx.compose.material.icons.outlined.Settings
import androidx.compose.material3.CenterAlignedTopAppBar
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
Expand All @@ -17,6 +22,7 @@ import com.arkivanov.decompose.extensions.compose.stack.Children
import com.arkivanov.decompose.extensions.compose.subscribeAsState
import dev.johnoreilly.confetti.decompose.ConferenceComponent
import dev.johnoreilly.confetti.decompose.HomeComponent
import dev.johnoreilly.confetti.decompose.SessionsUiState
import dev.johnoreilly.confetti.ui.ConferenceMaterialTheme
import dev.johnoreilly.confetti.ui.SessionListGridView

Expand All @@ -38,12 +44,27 @@ fun ConferenceView(component: ConferenceComponent) {
}


@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun HomeView(component: HomeComponent) {
val stack by component.stack.subscribeAsState()
val activeChild = stack.active.instance

val topBarActions: @Composable RowScope.() -> Unit = {
IconButton(onClick = {
component.onSwitchConferenceClicked()
}) {
androidx.compose.material3.Icon(Icons.Outlined.Settings, contentDescription = "Switch Conference")
}
}

Scaffold(
topBar = {
CenterAlignedTopAppBar(
title = { Text("") },
actions = topBarActions
)
},
bottomBar = {
BottomNavigation(backgroundColor = MaterialTheme.colorScheme.surface) {
BottomNavigationItem(
Expand Down
2 changes: 1 addition & 1 deletion compose-desktop/src/main/kotlin/SpeakersUI.kt
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ fun SpeakersUI(component: SpeakersComponent) {
) {
when (val state = uiState) {
is SpeakersUiState.Success -> {
SpeakerGridView(state.speakers, component::onSpeakerClicked)
SpeakerGridView(state.conference, state.speakers, component::onSpeakerClicked)
}
is SpeakersUiState.Loading -> LoadingView()
is SpeakersUiState.Error -> ErrorView {}
Expand Down
52 changes: 52 additions & 0 deletions compose-web/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import org.jetbrains.compose.ExperimentalComposeLibrary

plugins {
kotlin("multiplatform")
id("kotlinx-serialization")
id("org.jetbrains.compose")
}

group = "com.example"
version = "1.0-SNAPSHOT"


val copyWasmResources = tasks.create("copyWasmResourcesWorkaround", Copy::class.java) {
from(project(":shared").file("src/commonMain/composeResources"))
into("build/processedResources/wasmJs/main")
}


afterEvaluate {
project.tasks.getByName("wasmJsProcessResources").finalizedBy(copyWasmResources)
project.tasks.getByName("wasmJsDevelopmentExecutableCompileSync").dependsOn(copyWasmResources)
project.tasks.getByName("wasmJsProductionExecutableCompileSync").dependsOn(copyWasmResources)
}

kotlin {
wasmJs {
moduleName = "confetti"
browser {
commonWebpackConfig {
outputFileName = "confetti.js"
}
}
binaries.executable()
}

sourceSets {
commonMain {
dependencies {
implementation(compose.ui)
implementation(compose.runtime)
implementation(compose.foundation)
implementation(compose.material3)
implementation(compose.components.resources)
implementation(project(":shared"))
}
}
}
}

compose.experimental {
web.application {}
}
222 changes: 222 additions & 0 deletions compose-web/src/wasmJsMain/kotlin/HomeUI.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.safeDrawingPadding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Home
import androidx.compose.material.icons.filled.Person
import androidx.compose.material.icons.outlined.Home
import androidx.compose.material.icons.outlined.Person
import androidx.compose.material.icons.outlined.Settings
import androidx.compose.material3.CenterAlignedTopAppBar
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.NavigationBar
import androidx.compose.material3.NavigationBarItem
import androidx.compose.material3.NavigationRailItem
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi
import androidx.compose.material3.windowsizeclass.WindowSizeClass
import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass
import androidx.compose.material3.windowsizeclass.calculateWindowSizeClass
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.unit.dp
import com.arkivanov.decompose.extensions.compose.stack.Children
import com.arkivanov.decompose.extensions.compose.subscribeAsState
import dev.johnoreilly.confetti.decompose.ConferenceComponent
import dev.johnoreilly.confetti.decompose.HomeComponent
import dev.johnoreilly.confetti.decompose.SessionsComponent
import dev.johnoreilly.confetti.decompose.SessionsUiState
import dev.johnoreilly.confetti.ui.ConferenceMaterialTheme
import dev.johnoreilly.confetti.ui.SessionListGridView
import dev.johnoreilly.confetti.ui.SessionListView
import dev.johnoreilly.confetti.utils.isExpanded


@Composable
fun ConferenceView(component: ConferenceComponent) {
ConferenceMaterialTheme(component.conferenceThemeColor) {
Children(
stack = component.stack,
) {
when (val child = it.instance) {
is ConferenceComponent.Child.Home -> HomeView(child.component)
is ConferenceComponent.Child.SessionDetails -> SessionDetailsUI(child.component)
is ConferenceComponent.Child.SpeakerDetails -> SpeakerDetailsUI(child.component)
is ConferenceComponent.Child.Settings -> {} //SettingsRoute(child.component)
}
}
}
}


@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3WindowSizeClassApi::class)
@Composable
fun HomeView(component: HomeComponent) {
val windowSizeClass = calculateWindowSizeClass()
val shouldShowNavRail = windowSizeClass.isExpanded
Row {
if (shouldShowNavRail) {
NavigationRail(component)
}

Scaffold(
bottomBar = { if (!shouldShowNavRail) BottomBar(component) }
) {
Column(modifier = Modifier.padding(it)) {
Children(stack = component.stack,) {
when (val child = it.instance) {
is HomeComponent.Child.Sessions -> SessionsUI(child.component, windowSizeClass, component::onSwitchConferenceClicked)
is HomeComponent.Child.MultiPane -> Text(text = "Multi-pane mode is not yet supported")
is HomeComponent.Child.Speakers -> SpeakersUI(child.component)
is HomeComponent.Child.Bookmarks -> {}
is HomeComponent.Child.Venue -> VenueUI(child.component)
is HomeComponent.Child.Search -> {}
is HomeComponent.Child.Recommendations -> {}
}
}

}
}
}
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun SessionsUI(component: SessionsComponent, windowSizeClass: WindowSizeClass, onSwitchConferenceSelected: () -> Unit) {

val uiState by component.uiState.subscribeAsState()

val topBarActions: @Composable RowScope.() -> Unit = {
IconButton(onClick = { onSwitchConferenceSelected() }) {
Icon(Icons.Outlined.Settings, contentDescription = "Switch Conference")
}
}

val title = (uiState as? SessionsUiState.Success)?.conferenceName ?: ""
Scaffold(topBar = {
CenterAlignedTopAppBar(
title = { Text(title) },
actions = topBarActions
)
}) {
Column(Modifier.padding(it)) {
if (windowSizeClass.isExpanded) {
SessionListGridView(
uiState = uiState,
sessionSelected = component::onSessionClicked,
onRefresh = {},
addBookmark = {},
removeBookmark = {},
onNavigateToSignIn = {},
isLoggedIn = component.isLoggedIn,
)
} else {
SessionListView(
uiState = uiState,
sessionSelected = component::onSessionClicked,
addBookmark = component::addBookmark,
removeBookmark = component::removeBookmark,
onRefresh = component::refresh,
onNavigateToSignIn = component::onSignInClicked,
isLoggedIn = component.isLoggedIn,
)
}

}
}

}



@Composable
private fun NavigationRail(component: HomeComponent) {
androidx.compose.material3.NavigationRail(
modifier = Modifier.safeDrawingPadding(),
containerColor = Color.Transparent,
contentColor = MaterialTheme.colorScheme.onSurfaceVariant,
) {
NavigationButtons(component = component) { isSelected, selectedIcon, unselectedIcon, text, onClick ->
NavigationRailItem(
selected = isSelected,
onClick = onClick,
icon = {
Icon(
imageVector = if (isSelected) selectedIcon else unselectedIcon,
contentDescription = text
)
},
)
}
}
}



@Composable
private fun BottomBar(component: HomeComponent) {
Column {
HorizontalDivider()
NavigationBar(
contentColor = MaterialTheme.colorScheme.onSurfaceVariant,
tonalElevation = 0.dp,
) {
NavigationButtons(component = component) { isSelected, selectedIcon, unselectedIcon, text, onClick ->
NavigationBarItem(
selected = isSelected,
onClick = onClick,
icon = {
Icon(
imageVector = if (isSelected) selectedIcon else unselectedIcon,
contentDescription = text,
)
},
label = { Text(text) },
)
}
}
}
}


@Composable
private fun <T> T.NavigationButtons(
component: HomeComponent,
content: @Composable T.(
isSelected: Boolean,
selectedIcon: ImageVector,
unselectedIcon: ImageVector,
text: String,
onClick: () -> Unit,
) -> Unit,
) {
val stack by component.stack.subscribeAsState()
val activeChild = stack.active.instance

content(
activeChild is HomeComponent.Child.Sessions,
Icons.Filled.Home,
Icons.Outlined.Home,
"Schedule",
component::onSessionsTabClicked,
)

content(
activeChild is HomeComponent.Child.Speakers,
Icons.Filled.Person,
Icons.Outlined.Person,
"Speakers",
component::onSpeakersTabClicked,
)
}

0 comments on commit 8643c4c

Please sign in to comment.