From 1e9fdcc0d27794f5d43a689a137ae4c50e9ce286 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rton=20Braun?= Date: Mon, 20 Jan 2025 15:58:46 +0100 Subject: [PATCH 1/2] Create schedule screen --- gradle/libs.versions.toml | 4 + shared/build.gradle.kts | 49 +++- .../jetbrains/kotlinconf/ConferenceService.kt | 9 +- .../kotlin/org/jetbrains/kotlinconf/View.kt | 2 +- .../kotlinconf/screens/MainScreen.kt | 6 +- .../jetbrains/kotlinconf/screens/Schedule.kt | 40 --- .../kotlinconf/screens/ScheduleScreen.kt | 260 ++++++++++++++++++ .../kotlinconf/screens/ScheduleViewModel.kt | 148 ++++++++++ .../jetbrains/kotlinconf/utils/TextUtils.kt | 12 + .../src/nonWebMain/kotlin/TextUtils.nonWeb.kt | 6 + .../kotlinconf/utils/TextUtils.web.kt | 6 + .../kotlinconf/ui/components/DayHeader.kt | 3 +- .../kotlinconf/ui/components/TalkCard.kt | 47 ++-- 13 files changed, 514 insertions(+), 78 deletions(-) delete mode 100644 shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/screens/Schedule.kt create mode 100644 shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/screens/ScheduleScreen.kt create mode 100644 shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/screens/ScheduleViewModel.kt create mode 100644 shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/utils/TextUtils.kt create mode 100644 shared/src/nonWebMain/kotlin/TextUtils.nonWeb.kt create mode 100644 shared/src/webMain/kotlin/org/jetbrains/kotlinconf/utils/TextUtils.web.kt diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 6a794604..3066e6de 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -18,6 +18,7 @@ compose-android = "1.7.6" compose-multiplatform = "1.8.0-alpha02" compose-hot-reload = "1.0.0-dev.32.1" +coroutines = "1.10.1" coil = "3.0.3" exposed = "0.55.0" h2 = "2.2.224" @@ -30,6 +31,7 @@ logbackClassic = "1.5.6" markdown = "0.29.0" postgresql = "42.7.3" androidx-navigation = "2.8.0-alpha12" +doistx-normalize = "1.0.5" [libraries] @@ -87,8 +89,10 @@ ktor-server-status-pages = { module = "io.ktor:ktor-server-status-pages", versio ktor-server-swagger = { module = "io.ktor:ktor-server-swagger", version.ref = "ktor" } # utility +kotlinx-coroutines-swing = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-swing", version.ref = "coroutines" } kotlinx-datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "kotlinx-datetime" } logback-classic = { module = "ch.qos.logback:logback-classic", version.ref = "logbackClassic" } +doistx-normalize = { module = "com.doist.x:normalize", version.ref = "doistx-normalize" } # images android-svg = { module = "com.caverock:androidsvg-aar", version.ref = "android-svg" } diff --git a/shared/build.gradle.kts b/shared/build.gradle.kts index 42375641..50cf0dab 100644 --- a/shared/build.gradle.kts +++ b/shared/build.gradle.kts @@ -16,7 +16,10 @@ plugins { kotlin { androidTarget { compilerOptions { - freeCompilerArgs.addAll("-P", "plugin:org.jetbrains.kotlin.parcelize:additionalAnnotation=org.jetbrains.kotlinconf.ui.components.zoomable.internal.AndroidParcelize") + freeCompilerArgs.addAll( + "-P", + "plugin:org.jetbrains.kotlin.parcelize:additionalAnnotation=org.jetbrains.kotlinconf.ui.components.zoomable.internal.AndroidParcelize" + ) } } @@ -82,23 +85,41 @@ kotlin { implementation(kotlin("test")) } - androidMain.dependencies { - implementation(libs.android.svg) - implementation(libs.androidx.core.ktx) - implementation(libs.androidx.work.runtime) - implementation(libs.androidx.preference) - implementation(libs.compose.ui.tooling.preview) - implementation(libs.ktor.client.okhttp) + val nonWebMain by creating { + dependsOn(commonMain.get()) + dependencies { + // TODO move this to commonMain once Wasm version is available + implementation(libs.doistx.normalize) + } } - iosMain.dependencies { - implementation(libs.ktor.client.darwin) + androidMain { + dependsOn(nonWebMain) + dependencies { + implementation(libs.android.svg) + implementation(libs.androidx.core.ktx) + implementation(libs.androidx.work.runtime) + implementation(libs.androidx.preference) + implementation(libs.compose.ui.tooling.preview) + implementation(libs.ktor.client.okhttp) + } } - jvmMain.dependencies { - implementation(libs.ktor.client.okhttp) - implementation(compose.desktop.currentOs) - implementation(libs.android.svg) + iosMain { + dependsOn(nonWebMain) + dependencies { + implementation(libs.ktor.client.darwin) + } + } + + jvmMain { + dependsOn(nonWebMain) + dependencies { + implementation(libs.ktor.client.okhttp) + implementation(compose.desktop.currentOs) + implementation(libs.android.svg) + implementation(libs.kotlinx.coroutines.swing) + } } val webMain by creating { diff --git a/shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/ConferenceService.kt b/shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/ConferenceService.kt index eceec320..240baadc 100644 --- a/shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/ConferenceService.kt +++ b/shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/ConferenceService.kt @@ -280,7 +280,14 @@ class ConferenceService( * Get current time synchronized with server. */ private fun now(): GMTDate { - return GMTDate() + (serverTime.timestamp - requestTime.timestamp) + return GMTDate( + seconds = 0, + minutes = 0, + hours = 14, // 2 PM + dayOfMonth = 23, + month = Month.MAY, + year = 2024 + ) } override fun close() { diff --git a/shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/View.kt b/shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/View.kt index 26a195a5..3722dfed 100644 --- a/shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/View.kt +++ b/shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/View.kt @@ -101,7 +101,7 @@ fun List.groupByTime( val isBreak = cards.all { it.isBreak } val isLunch = cards.all { it.isLunch } val isParty = cards.all { it.isParty } - val isLive = start <= now && now < end + val isLive = start.dayOfMonth == 22 && start.hours == 14 && start.month.ordinal == 4 val isFinished = end <= now TimeSlot(start, end, isLive, isFinished, cards, isBreak, isLunch, isParty) diff --git a/shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/screens/MainScreen.kt b/shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/screens/MainScreen.kt index 78ed41fa..83e2b93d 100644 --- a/shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/screens/MainScreen.kt +++ b/shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/screens/MainScreen.kt @@ -78,9 +78,9 @@ fun MainScreen( ) } composable { - Schedule( - service.agenda.collectAsState().value, - onBack = { rootNavController.popBackStack() }, + // TODO implement callbacks + ScheduleScreen( + service, onSession = { rootNavController.navigate(TalkDetailsScreen(it)) }, ) } diff --git a/shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/screens/Schedule.kt b/shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/screens/Schedule.kt deleted file mode 100644 index 370620f5..00000000 --- a/shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/screens/Schedule.kt +++ /dev/null @@ -1,40 +0,0 @@ -package org.jetbrains.kotlinconf.screens - -import androidx.compose.foundation.Image -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Column -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import kotlinconfapp.shared.generated.resources.Res -import kotlinconfapp.shared.generated.resources.arrow_left_24 -import org.jetbrains.compose.resources.painterResource -import org.jetbrains.kotlinconf.Agenda -import org.jetbrains.kotlinconf.SessionId -import org.jetbrains.kotlinconf.ui.components.StyledText - -@Composable -fun Schedule( - agenda: Agenda, - onBack: () -> Unit, - onSession: (sessionId: SessionId) -> Unit, -) { - Column { - Image( - painterResource(Res.drawable.arrow_left_24), - "back", - modifier = Modifier.clickable(onClick = onBack) - ) - StyledText("Schedule") - for (day in agenda.days) { - StyledText(day.title) - for (timeSlot in day.timeSlots) { - StyledText(timeSlot.title) - for (session in timeSlot.sessions) { - StyledText( - session.title, - modifier = Modifier.clickable { onSession(session.id) }) - } - } - } - } -} diff --git a/shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/screens/ScheduleScreen.kt b/shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/screens/ScheduleScreen.kt new file mode 100644 index 00000000..20f46446 --- /dev/null +++ b/shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/screens/ScheduleScreen.kt @@ -0,0 +1,260 @@ +package org.jetbrains.kotlinconf.screens + + +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.LazyListState +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.derivedStateOf +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import androidx.lifecycle.viewmodel.compose.viewModel +import kotlinconfapp.shared.generated.resources.Res +import kotlinconfapp.shared.generated.resources.nav_destination_schedule +import kotlinconfapp.ui_components.generated.resources.bookmark_24 +import kotlinconfapp.ui_components.generated.resources.search_24 +import kotlinx.coroutines.launch +import org.jetbrains.compose.resources.stringResource +import org.jetbrains.kotlinconf.ConferenceService +import org.jetbrains.kotlinconf.SessionId +import org.jetbrains.kotlinconf.ui.components.DayHeader +import org.jetbrains.kotlinconf.ui.components.Emotion +import org.jetbrains.kotlinconf.ui.components.MainHeaderContainer +import org.jetbrains.kotlinconf.ui.components.MainHeaderContainerState +import org.jetbrains.kotlinconf.ui.components.MainHeaderSearchBar +import org.jetbrains.kotlinconf.ui.components.MainHeaderTitleBar +import org.jetbrains.kotlinconf.ui.components.NowButton +import org.jetbrains.kotlinconf.ui.components.NowButtonState +import org.jetbrains.kotlinconf.ui.components.StyledText +import org.jetbrains.kotlinconf.ui.components.Switcher +import org.jetbrains.kotlinconf.ui.components.TalkCard +import org.jetbrains.kotlinconf.ui.components.TalkStatus +import org.jetbrains.kotlinconf.ui.components.TopMenuButton +import org.jetbrains.kotlinconf.ui.theme.KotlinConfTheme +import org.jetbrains.kotlinconf.utils.time +import kotlinconfapp.ui_components.generated.resources.Res as UiRes + +@Composable +fun ScheduleScreen( + service: ConferenceService, + onSession: (SessionId) -> Unit, +) { + val scope = rememberCoroutineScope() + var bookmarkFilterEnabled by remember { mutableStateOf(false) } + var searchQuery by remember { mutableStateOf("") } + val listState = rememberLazyListState() + + val vm = viewModel { ScheduleViewModel(service) } + + val days by vm.days.collectAsState() + val items by vm.items.collectAsState() + + val selectedDayIndex by derivedStateOf { + items.asSequence() + .take(listState.firstVisibleItemIndex + 1) + .findLast { it is DayHeaderItem } + .let { + (it as? DayHeaderItem)?.value?.day?.ordinal ?: 0 + } + } + + var headerState by remember { mutableStateOf(MainHeaderContainerState.Title) } + val isSearch = remember(headerState) { + headerState == MainHeaderContainerState.Search + } + + LaunchedEffect(searchQuery, isSearch) { + vm.setSearchParams(searchQuery, isSearch) + } + + Column(modifier = Modifier.fillMaxSize()) { + Header( + headerState = headerState, + onHeaderStateChange = { headerState = it }, + nowButtonState = NowButtonState.Current, + onNowClicked = {}, + bookmarkFilterEnabled = bookmarkFilterEnabled, + onBookmarkFilter = { bookmarkFilterEnabled = it }, + searchQuery = searchQuery, + onSearchQueryChange = { searchQuery = it }, + ) + + AnimatedVisibility(!isSearch) { + Switcher( + items = days.map { "May ${it.day.ordinal + 22}" }, + selectedIndex = selectedDayIndex, + onSelect = { index -> + scope.launch { + val dayIndex = items.indexOf(DayHeaderItem(days[index])) + listState.animateScrollToItem(dayIndex) + } + }, + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp, vertical = 8.dp) + ) + } + + ScheduleList( + scheduleItems = items, + onSession = onSession, + listState = listState, + onSubmitFeedback = { sessionId, emotion -> + vm.onSubmitFeedback(sessionId, emotion) + }, + onSubmitFeedbackWithComment = { sessionId, emotion, comment -> + vm.onSubmitFeedbackWithComment(sessionId, emotion, comment) + }, + onBookmark = { sessionId, isBookmarked -> + vm.onBookmark(sessionId, isBookmarked) + }, + ) + } +} + +@Composable +private fun Header( + headerState: MainHeaderContainerState, + onHeaderStateChange: (MainHeaderContainerState) -> Unit, + nowButtonState: NowButtonState, + onNowClicked: () -> Unit, + bookmarkFilterEnabled: Boolean, + onBookmarkFilter: (Boolean) -> Unit, + searchQuery: String, + onSearchQueryChange: (String) -> Unit, +) { + MainHeaderContainer( + state = headerState, + titleContent = { + MainHeaderTitleBar( + title = stringResource(Res.string.nav_destination_schedule), + startContent = { + NowButton( + time = nowButtonState, + onClick = { + onNowClicked() + }, + enabled = nowButtonState != NowButtonState.Current, + ) + }, + endContent = { + TopMenuButton( + icon = UiRes.drawable.bookmark_24, + selected = bookmarkFilterEnabled, + onToggle = { onBookmarkFilter(it) }, + contentDescription = "Filter bookmarked" + ) + TopMenuButton( + icon = UiRes.drawable.search_24, + onClick = { onHeaderStateChange(MainHeaderContainerState.Search)}, + contentDescription = "Search" + ) + } + ) + }, + searchContent = { + MainHeaderSearchBar( + searchValue = searchQuery, + onSearchValueChange = { onSearchQueryChange(it) }, + onClose = { + onHeaderStateChange( MainHeaderContainerState.Title) + onSearchQueryChange("") + } + ) + } + ) +} + +@Composable +fun ScheduleList( + scheduleItems: List, + onSession: (SessionId) -> Unit, + listState: LazyListState, + onSubmitFeedback: (SessionId, Emotion?) -> Unit, + onSubmitFeedbackWithComment: (SessionId, Emotion, String) -> Unit, + onBookmark: (SessionId, Boolean) -> Unit, + modifier: Modifier = Modifier, +) { + LazyColumn( + state = listState, + modifier = modifier, + contentPadding = PaddingValues(vertical = 16.dp), + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + items(scheduleItems) { item -> + when (item) { + is DayHeaderItem -> { + val day = item.value + DayHeader( + month = "MAY", + day = (day.day.ordinal + 22).toString(), + line1 = "Conference", + line2 = "Day ${day.day.ordinal + 1}", + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 8.dp) + ) + } + + is TimeSlotItem -> { + val timeSlot = item.value + StyledText( + text = "${timeSlot.startsAt.time()} - ${timeSlot.endsAt.time()}", + style = KotlinConfTheme.typography.h2, + modifier = Modifier + .padding(horizontal = 16.dp, vertical = 8.dp) + ) + } + + is SessionItem -> { + val session = item.value + TalkCard( + title = session.title, + titleHighlights = item.titleHighlights, + bookmarked = session.isFavorite, + onBookmark = { isBookmarked -> onBookmark(session.id, isBookmarked) }, + tags = session.tags, + selectedTags = emptyList(), + speakers = session.speakerLine, + speakerHighlights = item.speakerHighlights, + location = session.locationLine, + lightning = session.isLightning, + time = session.badgeTimeLine, + timeNote = null, + status = when { + session.isFinished -> TalkStatus.Past +// timeSlot.isLive -> TalkStatus.Now + else -> TalkStatus.Upcoming + }, + onSubmitFeedback = { emotion -> + onSubmitFeedback(session.id, emotion) + }, + onSubmitFeedbackWithComment = { emotion, comment -> + onSubmitFeedbackWithComment(session.id, emotion, comment) + }, + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp, vertical = 4.dp) + .clickable { onSession(session.id) } + ) + } + } + } + } +} diff --git a/shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/screens/ScheduleViewModel.kt b/shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/screens/ScheduleViewModel.kt new file mode 100644 index 00000000..34570e13 --- /dev/null +++ b/shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/screens/ScheduleViewModel.kt @@ -0,0 +1,148 @@ +package org.jetbrains.kotlinconf.screens + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.flowOn +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.launch +import org.jetbrains.kotlinconf.Agenda +import org.jetbrains.kotlinconf.ConferenceService +import org.jetbrains.kotlinconf.Day +import org.jetbrains.kotlinconf.Score +import org.jetbrains.kotlinconf.SessionCardView +import org.jetbrains.kotlinconf.SessionId +import org.jetbrains.kotlinconf.TimeSlot +import org.jetbrains.kotlinconf.ui.components.Emotion +import org.jetbrains.kotlinconf.utils.containsDiacritics +import org.jetbrains.kotlinconf.utils.removeDiacritics + +sealed interface ScheduleListItem + +data class DayHeaderItem(val value: Day) : ScheduleListItem +data class TimeSlotItem(val value: TimeSlot) : ScheduleListItem +data class SessionItem( + val value: SessionCardView, + val titleHighlights: List, + val speakerHighlights: List, +) : ScheduleListItem + + +class ScheduleViewModel( + private val service: ConferenceService, +) : ViewModel() { + private val agenda: StateFlow = service.agenda + + val days: StateFlow> = agenda.map { it?.days ?: emptyList() } + .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), emptyList()) + + private val searchQuery = MutableStateFlow("") + private val isSearch = MutableStateFlow(false) + + fun setSearchParams(searchQuery: String, isSearch: Boolean) { + this.searchQuery.value = searchQuery + this.isSearch.value = isSearch + } + + val items = combine(days, searchQuery, isSearch) { x, y, z-> // todo param names + buildItems(x, y, z) + }.flowOn(Dispatchers.Default).stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), emptyList()) + + /** + * Builds a flat list of items for the UI, taking into account the current + * filtering values. + */ + private fun buildItems( + days: List, + searchQuery: String, + isSearch: Boolean, + ): List { + return buildList { + days.forEach { day -> + if (!isSearch) add(DayHeaderItem(day)) + + day.timeSlots.forEach { timeSlot -> + if (!isSearch) add(TimeSlotItem(timeSlot)) + + timeSlot.sessions.forEach { session -> + if (isSearch) { + // Perform search + val titleHighlights = mutableListOf() + val speakerHighlights = mutableListOf() + if (match(session, searchQuery, titleHighlights, speakerHighlights)) { + add(SessionItem(session, titleHighlights, speakerHighlights)) + } + } else { + // Add all sessions + add(SessionItem(session, emptyList(), emptyList())) + } + } + } + } + } + } + + /** + * Checks if a session matches the search query and populates the highlight ranges for + * the session title and speaker line if matches are found. + */ + private fun match( + session: SessionCardView, + searchQuery: String, + titleHighlights: MutableList, + speakerHighlights: MutableList, + ): Boolean { + // Look for exact matches if diacritics are present, ignore all diacritics otherwise + val diacriticsSearch = searchQuery.containsDiacritics() + val targetTitle = + if (diacriticsSearch) session.title + else session.title.removeDiacritics() + val targetSpeakers = + if (diacriticsSearch) session.speakerLine + else session.speakerLine.removeDiacritics() + + titleHighlights.addAll( + searchQuery.toRegex(RegexOption.IGNORE_CASE).findAll(targetTitle).map { it.range }) + + speakerHighlights.addAll( + searchQuery.toRegex(RegexOption.IGNORE_CASE).findAll(targetSpeakers).map { it.range }) + + return titleHighlights.isNotEmpty() || speakerHighlights.isNotEmpty() + } + + fun onSubmitFeedback(sessionId: SessionId, emotion: Emotion?) { + val score = when (emotion) { + Emotion.Positive -> Score.GOOD + Emotion.Neutral -> Score.OK + Emotion.Negative -> Score.BAD + null -> null + } + viewModelScope.launch { + service.vote(sessionId, score) + } + } + + fun onSubmitFeedbackWithComment(sessionId: SessionId, emotion: Emotion, comment: String) { + val score = when (emotion) { + Emotion.Positive -> Score.GOOD + Emotion.Neutral -> Score.OK + Emotion.Negative -> Score.BAD + } + viewModelScope.launch { + service.vote(sessionId, score) + service.sendFeedback(sessionId, comment) + } + } + + fun onBookmark(sessionId: SessionId, bookmarked: Boolean) { + viewModelScope.launch { + // TODO would be nicer if we could pass a boolean in here + service.toggleFavorite(sessionId) + } + } +} diff --git a/shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/utils/TextUtils.kt b/shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/utils/TextUtils.kt new file mode 100644 index 00000000..2518e9da --- /dev/null +++ b/shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/utils/TextUtils.kt @@ -0,0 +1,12 @@ +package org.jetbrains.kotlinconf.utils + +private val diacricitsRegex = "\\p{Mn}+".toRegex() + +fun String.containsDiacritics(): Boolean = normalizeNfd().contains(diacricitsRegex) + +fun String.removeDiacritics() = normalizeNfd().replace(diacricitsRegex, "") + +/** + * Normalize the string to the NDF normal form. + */ +expect fun String.normalizeNfd(): String diff --git a/shared/src/nonWebMain/kotlin/TextUtils.nonWeb.kt b/shared/src/nonWebMain/kotlin/TextUtils.nonWeb.kt new file mode 100644 index 00000000..ce0fa840 --- /dev/null +++ b/shared/src/nonWebMain/kotlin/TextUtils.nonWeb.kt @@ -0,0 +1,6 @@ +package org.jetbrains.kotlinconf.utils + +import doist.x.normalize.Form +import doist.x.normalize.normalize + +actual fun String.normalizeNfd(): String = normalize(Form.NFD) diff --git a/shared/src/webMain/kotlin/org/jetbrains/kotlinconf/utils/TextUtils.web.kt b/shared/src/webMain/kotlin/org/jetbrains/kotlinconf/utils/TextUtils.web.kt new file mode 100644 index 00000000..56469e79 --- /dev/null +++ b/shared/src/webMain/kotlin/org/jetbrains/kotlinconf/utils/TextUtils.web.kt @@ -0,0 +1,6 @@ +package org.jetbrains.kotlinconf.utils + +/** + * No normalize support for web targets for now. Returns the original string. + */ +actual fun String.normalizeNfd(): String = this diff --git a/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/DayHeader.kt b/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/DayHeader.kt index 92f07861..893abca8 100644 --- a/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/DayHeader.kt +++ b/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/DayHeader.kt @@ -4,6 +4,7 @@ import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.widthIn @@ -53,7 +54,7 @@ fun DayHeader( Row( modifier = modifier .background(colorGradient) - .width(300.dp) + .fillMaxWidth() .padding(horizontal = 16.dp, vertical = 6.dp) .semantics(mergeDescendants = true) {}, verticalAlignment = Alignment.CenterVertically, diff --git a/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/TalkCard.kt b/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/TalkCard.kt index b0e2d8a3..0f42c547 100644 --- a/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/TalkCard.kt +++ b/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/TalkCard.kt @@ -36,6 +36,7 @@ import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.graphics.Color import androidx.compose.ui.semantics.Role +import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.unit.dp @@ -55,6 +56,27 @@ import org.jetbrains.kotlinconf.ui.theme.Brand import org.jetbrains.kotlinconf.ui.theme.KotlinConfTheme import org.jetbrains.kotlinconf.ui.theme.PreviewHelper +@Composable +private fun buildHighlightedString( + text: String, + highlights: List, +): AnnotatedString = buildAnnotatedString { + append(text) + highlights.forEach { range -> + // Ignore invalid ranges + if (!range.isEmpty()) { + addStyle( + style = SpanStyle( + color = KotlinConfTheme.colors.primaryTextInverted, + background = Brand.magenta100, + ), + start = range.first, + end = range.last + 1, + ) + } + } +} + enum class TalkStatus { Past, Now, Upcoming, } @@ -70,6 +92,7 @@ fun TalkCard( tags: List, selectedTags: List, speakers: String, + speakerHighlights: List, location: String, lightning: Boolean, time: String, @@ -106,6 +129,7 @@ fun TalkCard( tags = tags, selectedTags = selectedTags, speakers = speakers, + speakerHighlights = speakerHighlights, ) Divider( thickness = 1.dp, @@ -144,30 +168,15 @@ private fun TopBlock( tags: List, selectedTags: List, speakers: String, + speakerHighlights: List, ) { Column( modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(12.dp), ) { Row { - val annotatedTitle = buildAnnotatedString { - append(title) - titleHighlights.forEach { range -> - // Ignore invalid ranges - if (!range.isEmpty()) { - addStyle( - style = SpanStyle( - color = KotlinConfTheme.colors.primaryTextInverted, - background = Brand.magenta100, - ), - start = range.first, - end = range.last + 1, - ) - } - } - } StyledText( - text = annotatedTitle, + text = buildHighlightedString(title, titleHighlights), style = KotlinConfTheme.typography.h3, color = textColor, modifier = Modifier.weight(1f), @@ -207,7 +216,7 @@ private fun TopBlock( } } StyledText( - text = speakers, + text = buildHighlightedString(speakers, speakerHighlights), color = KotlinConfTheme.colors.secondaryText, style = KotlinConfTheme.typography.text2, ) @@ -368,6 +377,7 @@ internal fun TalkCardPreview() { "Kotlin", "Multiplatform", ), speakers = "Sebastian Aigner, Vsevolod Tolstopyatov", + speakerHighlights = listOf(10..15), location = "Auditorium 14", lightning = true, time = "9:00 – 10:00", @@ -389,6 +399,7 @@ internal fun TalkCardPreview() { ), selectedTags = listOf(), speakers = "Sebastian Aigner, Vsevolod Tolstopyatov", + speakerHighlights = emptyList(), location = "Auditorium 14", lightning = true, time = "9:00 – 10:00", From 629981533ac53f6902877c69c5177263c638aa23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rton=20Braun?= Date: Thu, 30 Jan 2025 00:48:53 +0100 Subject: [PATCH 2/2] WIP filtering impl --- .../kotlinconf/screens/MainScreen.kt | 3 +- .../kotlinconf/screens/ScheduleScreen.kt | 112 +++++++++------- .../kotlinconf/screens/ScheduleViewModel.kt | 126 ++++++++++++++++-- shared/store.json | 2 +- .../kotlinconf/ui/components/Filters.kt | 80 +++++------ .../kotlinconf/ui/components/Switcher.kt | 3 +- .../kotlinconf/ui/components/TalkCard.kt | 24 +++- 7 files changed, 236 insertions(+), 114 deletions(-) diff --git a/shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/screens/MainScreen.kt b/shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/screens/MainScreen.kt index 83e2b93d..cf579945 100644 --- a/shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/screens/MainScreen.kt +++ b/shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/screens/MainScreen.kt @@ -78,9 +78,8 @@ fun MainScreen( ) } composable { - // TODO implement callbacks ScheduleScreen( - service, + service = service, onSession = { rootNavController.navigate(TalkDetailsScreen(it)) }, ) } diff --git a/shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/screens/ScheduleScreen.kt b/shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/screens/ScheduleScreen.kt index 20f46446..7dac3500 100644 --- a/shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/screens/ScheduleScreen.kt +++ b/shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/screens/ScheduleScreen.kt @@ -1,11 +1,8 @@ package org.jetbrains.kotlinconf.screens -import androidx.compose.animation.AnimatedVisibility -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Arrangement +import androidx.compose.animation.AnimatedContent import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding @@ -34,13 +31,13 @@ import org.jetbrains.compose.resources.stringResource import org.jetbrains.kotlinconf.ConferenceService import org.jetbrains.kotlinconf.SessionId import org.jetbrains.kotlinconf.ui.components.DayHeader +import org.jetbrains.kotlinconf.ui.components.Divider import org.jetbrains.kotlinconf.ui.components.Emotion +import org.jetbrains.kotlinconf.ui.components.Filters import org.jetbrains.kotlinconf.ui.components.MainHeaderContainer import org.jetbrains.kotlinconf.ui.components.MainHeaderContainerState import org.jetbrains.kotlinconf.ui.components.MainHeaderSearchBar import org.jetbrains.kotlinconf.ui.components.MainHeaderTitleBar -import org.jetbrains.kotlinconf.ui.components.NowButton -import org.jetbrains.kotlinconf.ui.components.NowButtonState import org.jetbrains.kotlinconf.ui.components.StyledText import org.jetbrains.kotlinconf.ui.components.Switcher import org.jetbrains.kotlinconf.ui.components.TalkCard @@ -54,18 +51,19 @@ import kotlinconfapp.ui_components.generated.resources.Res as UiRes fun ScheduleScreen( service: ConferenceService, onSession: (SessionId) -> Unit, + viewModel: ScheduleViewModel = viewModel { ScheduleViewModel(service) }, ) { val scope = rememberCoroutineScope() + // TODO implement bookmark filtering var bookmarkFilterEnabled by remember { mutableStateOf(false) } var searchQuery by remember { mutableStateOf("") } val listState = rememberLazyListState() - val vm = viewModel { ScheduleViewModel(service) } + val days by viewModel.days.collectAsState() + val items by viewModel.items.collectAsState() - val days by vm.days.collectAsState() - val items by vm.items.collectAsState() - - val selectedDayIndex by derivedStateOf { + // Header selection state calculated from the scroll state + val computedDayIndex by derivedStateOf { items.asSequence() .take(listState.firstVisibleItemIndex + 1) .findLast { it is DayHeaderItem } @@ -73,6 +71,9 @@ fun ScheduleScreen( (it as? DayHeaderItem)?.value?.day?.ordinal ?: 0 } } + // Override for the header selection + var targetDayIndex by remember { mutableStateOf(null) } + val selectedDayIndex = targetDayIndex ?: computedDayIndex var headerState by remember { mutableStateOf(MainHeaderContainerState.Title) } val isSearch = remember(headerState) { @@ -80,35 +81,54 @@ fun ScheduleScreen( } LaunchedEffect(searchQuery, isSearch) { - vm.setSearchParams(searchQuery, isSearch) + viewModel.setSearchParams(searchQuery, isSearch) } Column(modifier = Modifier.fillMaxSize()) { Header( headerState = headerState, onHeaderStateChange = { headerState = it }, - nowButtonState = NowButtonState.Current, - onNowClicked = {}, bookmarkFilterEnabled = bookmarkFilterEnabled, onBookmarkFilter = { bookmarkFilterEnabled = it }, searchQuery = searchQuery, onSearchQueryChange = { searchQuery = it }, ) + Divider( + thickness = 1.dp, + color = KotlinConfTheme.colors.strokePale, + ) - AnimatedVisibility(!isSearch) { - Switcher( - items = days.map { "May ${it.day.ordinal + 22}" }, - selectedIndex = selectedDayIndex, - onSelect = { index -> - scope.launch { - val dayIndex = items.indexOf(DayHeaderItem(days[index])) - listState.animateScrollToItem(dayIndex) - } - }, - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 16.dp, vertical = 8.dp) - ) + AnimatedContent(isSearch) { isSearch -> + if (isSearch) { + val tags by viewModel.filterItems.collectAsState() + Filters( + tags = tags, + toggleItem = { item, selected -> viewModel.toggleFilter(item, selected) }, + modifier = Modifier.padding(vertical = 16.dp, horizontal = 12.dp), + ) + } else { + Switcher( + items = days.map { + // TODO proper date handling + "May ${it.day.ordinal + 22}" + }, + selectedIndex = selectedDayIndex, + onSelect = { index -> + scope.launch { + val dayItemIndex = items.indexOf(DayHeaderItem(days[index])) + // Temporarily override the scroll state based selection + targetDayIndex = index + // Scroll to the item + listState.animateScrollToItem(dayItemIndex) + // Remove override, let scroll state determine the selection + targetDayIndex = null + } + }, + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 12.dp, vertical = 8.dp) + ) + } } ScheduleList( @@ -116,13 +136,13 @@ fun ScheduleScreen( onSession = onSession, listState = listState, onSubmitFeedback = { sessionId, emotion -> - vm.onSubmitFeedback(sessionId, emotion) + viewModel.onSubmitFeedback(sessionId, emotion) }, onSubmitFeedbackWithComment = { sessionId, emotion, comment -> - vm.onSubmitFeedbackWithComment(sessionId, emotion, comment) + viewModel.onSubmitFeedbackWithComment(sessionId, emotion, comment) }, onBookmark = { sessionId, isBookmarked -> - vm.onBookmark(sessionId, isBookmarked) + viewModel.onBookmark(sessionId, isBookmarked) }, ) } @@ -132,8 +152,6 @@ fun ScheduleScreen( private fun Header( headerState: MainHeaderContainerState, onHeaderStateChange: (MainHeaderContainerState) -> Unit, - nowButtonState: NowButtonState, - onNowClicked: () -> Unit, bookmarkFilterEnabled: Boolean, onBookmarkFilter: (Boolean) -> Unit, searchQuery: String, @@ -145,13 +163,7 @@ private fun Header( MainHeaderTitleBar( title = stringResource(Res.string.nav_destination_schedule), startContent = { - NowButton( - time = nowButtonState, - onClick = { - onNowClicked() - }, - enabled = nowButtonState != NowButtonState.Current, - ) + // TODO Now Button }, endContent = { TopMenuButton( @@ -162,7 +174,7 @@ private fun Header( ) TopMenuButton( icon = UiRes.drawable.search_24, - onClick = { onHeaderStateChange(MainHeaderContainerState.Search)}, + onClick = { onHeaderStateChange(MainHeaderContainerState.Search) }, contentDescription = "Search" ) } @@ -171,9 +183,10 @@ private fun Header( searchContent = { MainHeaderSearchBar( searchValue = searchQuery, + // clearing the input should also reset tags onSearchValueChange = { onSearchQueryChange(it) }, onClose = { - onHeaderStateChange( MainHeaderContainerState.Title) + onHeaderStateChange(MainHeaderContainerState.Title) onSearchQueryChange("") } ) @@ -194,8 +207,6 @@ fun ScheduleList( LazyColumn( state = listState, modifier = modifier, - contentPadding = PaddingValues(vertical = 16.dp), - verticalArrangement = Arrangement.spacedBy(8.dp) ) { items(scheduleItems) { item -> when (item) { @@ -208,17 +219,17 @@ fun ScheduleList( line2 = "Day ${day.day.ordinal + 1}", modifier = Modifier .fillMaxWidth() - .padding(vertical = 8.dp) + .padding(vertical = 16.dp) ) } - is TimeSlotItem -> { + is SectionTitleItem -> { val timeSlot = item.value StyledText( text = "${timeSlot.startsAt.time()} - ${timeSlot.endsAt.time()}", style = KotlinConfTheme.typography.h2, modifier = Modifier - .padding(horizontal = 16.dp, vertical = 8.dp) + .padding(horizontal = 12.dp, vertical = 8.dp) ) } @@ -230,7 +241,7 @@ fun ScheduleList( bookmarked = session.isFavorite, onBookmark = { isBookmarked -> onBookmark(session.id, isBookmarked) }, tags = session.tags, - selectedTags = emptyList(), + tagHighlights = item.tagMatches, speakers = session.speakerLine, speakerHighlights = item.speakerHighlights, location = session.locationLine, @@ -238,6 +249,7 @@ fun ScheduleList( time = session.badgeTimeLine, timeNote = null, status = when { + // TODO time handling session.isFinished -> TalkStatus.Past // timeSlot.isLive -> TalkStatus.Now else -> TalkStatus.Upcoming @@ -248,10 +260,10 @@ fun ScheduleList( onSubmitFeedbackWithComment = { emotion, comment -> onSubmitFeedbackWithComment(session.id, emotion, comment) }, + onClick = { onSession(session.id) }, modifier = Modifier .fillMaxWidth() - .padding(horizontal = 16.dp, vertical = 4.dp) - .clickable { onSession(session.id) } + .padding(horizontal = 12.dp, vertical = 8.dp) ) } } diff --git a/shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/screens/ScheduleViewModel.kt b/shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/screens/ScheduleViewModel.kt index 34570e13..3805d6e0 100644 --- a/shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/screens/ScheduleViewModel.kt +++ b/shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/screens/ScheduleViewModel.kt @@ -10,6 +10,7 @@ import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import org.jetbrains.kotlinconf.Agenda import org.jetbrains.kotlinconf.ConferenceService @@ -19,67 +20,155 @@ import org.jetbrains.kotlinconf.SessionCardView import org.jetbrains.kotlinconf.SessionId import org.jetbrains.kotlinconf.TimeSlot import org.jetbrains.kotlinconf.ui.components.Emotion +import org.jetbrains.kotlinconf.ui.components.FilterItem +import org.jetbrains.kotlinconf.ui.components.FilterItemType import org.jetbrains.kotlinconf.utils.containsDiacritics import org.jetbrains.kotlinconf.utils.removeDiacritics sealed interface ScheduleListItem +// TODO add service events +// TODO separate workshop events from the rest data class DayHeaderItem(val value: Day) : ScheduleListItem -data class TimeSlotItem(val value: TimeSlot) : ScheduleListItem +data class SectionTitleItem(val value: TimeSlot) : ScheduleListItem data class SessionItem( val value: SessionCardView, - val titleHighlights: List, - val speakerHighlights: List, + val tagMatches: List = emptyList(), + val titleHighlights: List = emptyList(), + val speakerHighlights: List = emptyList(), ) : ScheduleListItem +// TODO get categories from the service? +private val categoryTags = listOf( + "Server-side", + "Multiplatform", + "Android", + "Extensibility/Tooling", + "Languages and Best Practices", + "Other", +) +private val levelTags = listOf( + "Introductory and overview", + "Intermediate", + "Advanced", +) +private val formatTags = listOf( + "Workshop", + "Regular Session", + "Lightning Session", +) class ScheduleViewModel( private val service: ConferenceService, ) : ViewModel() { - private val agenda: StateFlow = service.agenda + private val agenda: StateFlow = service.agenda - val days: StateFlow> = agenda.map { it?.days ?: emptyList() } + val days: StateFlow> = agenda.map { it.days } .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), emptyList()) private val searchQuery = MutableStateFlow("") private val isSearch = MutableStateFlow(false) + private fun List.toTags(type: FilterItemType): List { + return map { FilterItem(type, it, false) } + } + + val filterItems = MutableStateFlow>( + categoryTags.toTags(FilterItemType.Category) + + levelTags.toTags(FilterItemType.Level) + + formatTags.toTags(FilterItemType.Format) + ) + + private fun MutableList.replace(old: T, new: T) { + val index = indexOf(old) + if (index >= 0) { + set(index, new) + } + } + + fun toggleFilter(item: FilterItem, selected: Boolean) { + val newItem = item.copy(isSelected = selected) + filterItems.update { + it.toMutableList().apply { + replace(item, newItem) + } + } + } + fun setSearchParams(searchQuery: String, isSearch: Boolean) { this.searchQuery.value = searchQuery this.isSearch.value = isSearch } - val items = combine(days, searchQuery, isSearch) { x, y, z-> // todo param names - buildItems(x, y, z) - }.flowOn(Dispatchers.Default).stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), emptyList()) + private val searchState = combine(searchQuery, isSearch) { query, isSearch -> + query to isSearch + } + + val items = combine( + days, + searchState, + filterItems, + ) { days, (query, isSearch), tags -> + buildItems( + days = days, + searchQuery = query, + isSearch = isSearch, + tags = tags, + ) + }.flowOn(Dispatchers.Default) + .stateIn( + scope = viewModelScope, + started = SharingStarted.WhileSubscribed(5000), + initialValue = emptyList() + ) /** * Builds a flat list of items for the UI, taking into account the current - * filtering values. + * filtering values and active filters. */ private fun buildItems( days: List, searchQuery: String, isSearch: Boolean, + tags: List, ): List { + val tagValues = tags.filter { it.isSelected }.map { it.value } + return buildList { days.forEach { day -> if (!isSearch) add(DayHeaderItem(day)) day.timeSlots.forEach { timeSlot -> - if (!isSearch) add(TimeSlotItem(timeSlot)) + if (!isSearch) add(SectionTitleItem(timeSlot)) timeSlot.sessions.forEach { session -> if (isSearch) { // Perform search + val tagMatches = mutableListOf() val titleHighlights = mutableListOf() val speakerHighlights = mutableListOf() - if (match(session, searchQuery, titleHighlights, speakerHighlights)) { - add(SessionItem(session, titleHighlights, speakerHighlights)) + if ( + match( + session = session, + searchQuery = searchQuery, + tagMatches = tagMatches, + titleHighlights = titleHighlights, + speakerHighlights = speakerHighlights, + tags = tagValues, + ) + ) { + add( + SessionItem( + value = session, + tagMatches = tagMatches, + titleHighlights = titleHighlights, + speakerHighlights = speakerHighlights, + ) + ) } } else { - // Add all sessions - add(SessionItem(session, emptyList(), emptyList())) + // Add filtered sessions + add(SessionItem(session)) } } } @@ -94,8 +183,10 @@ class ScheduleViewModel( private fun match( session: SessionCardView, searchQuery: String, + tagMatches: MutableList, titleHighlights: MutableList, speakerHighlights: MutableList, + tags: List, ): Boolean { // Look for exact matches if diacritics are present, ignore all diacritics otherwise val diacriticsSearch = searchQuery.containsDiacritics() @@ -106,6 +197,13 @@ class ScheduleViewModel( if (diacriticsSearch) session.speakerLine else session.speakerLine.removeDiacritics() + if (tags.isNotEmpty()) { + tagMatches.addAll(session.tags.filter { it in tags }) + if (tagMatches.isEmpty()) { + return false + } + } + titleHighlights.addAll( searchQuery.toRegex(RegexOption.IGNORE_CASE).findAll(targetTitle).map { it.range }) diff --git a/shared/store.json b/shared/store.json index 8a10b89a..ab912240 100644 --- a/shared/store.json +++ b/shared/store.json @@ -1 +1 @@ -{"values":{}} +{"values":{"_themeStorage":"\"DARK\"","userId2024":"null","conferenceCache":"{\"sessions\":[{\"id\":\"616759\",\"title\":\"Kotlin Multiplatform Beyond the Basics. Part 1\",\"description\":\"This is an intermediate / advanced workshop for experienced Android developers. It is aimed at engineers who have built projects with Kotlin and Jetpack Compose and now want to progress onto multiplatform application development.\\r\\n\\r\\nThe workshop is split into two parts. In the morning session, we’ll build an application entirely using Kotlin Multiplatform libraries. This will feature a Compose Multiplatform user interface, testing with kotlin.test and Kotest, and networking with Ktor and coroutines. Additional libraries will be used to show data caching, dependency injection, serialization, and more.\\r\\n\\r\\nIn the afternoon session, we’ll explore real-world issues associated with taking these kinds of applications into production. We’ll explore general issues with architecture and deployment but then shift our focus to issues specific to iOS. In particular, we’ll cover how best to package and expose Kotlin APIs to be consumed by Swift code, and vice versa. We’ll also explore how to share business logic with a SwiftUI interface, work with XCode, and distribute your application.\\r\\n\\r\\nMorning Topics\\r\\n- Review the basics of KMP development.\\r\\n- Introducing the workshop sample application.\\r\\n- Adding shared business logic with unit tests.\\r\\n- Platform integration with expected and actual declarations.\\r\\n- Extending the existing Compose Multiplatform UI.\\r\\n- Interacting with services via Ktor and coroutines.\\r\\n- Creating integration tests at different levels.\\r\\n- Refactoring the app to use dependency injection.\\r\\n- Adding client side caching to improve performance.\\r\\n\\r\\nAfternoon Topics\\r\\n- Best practices for building multiplatform applications.\\r\\n- Guidelines for creating and distributing your KMP library.\\r\\n- Making the most out of the existing KMP ecosystem.\\r\\n- A primer for using XCode effectively in KMP apps.\\r\\n- Effectively sharing Kotlin APIs with Swift codebases.\\r\\n- Mixing Compose Multiplatform and SwiftUI components.\\r\\n- Options for testing a Compose Multiplatform UI in iOS.\\r\\n- Distributing your shared code to iOS teammates.\",\"speakerIds\":[\"0fd04388-0a57-4c8e-9505-89d7962c2dba\",\"877c0f18-0545-40a7-b670-1f8593fa6f50\",\"62216efe-dd8b-4d8b-9800-1d51b57c4001\"],\"location\":\"Room 173\",\"startsAt\":\"2024-05-22T09:00:00\",\"endsAt\":\"2024-05-22T10:30:00\",\"tags\":[\"Workshop\",\"Intermediate\",\"Other\"]},{\"id\":\"616766\",\"title\":\"Mastering Kotlin Refactoring – Tools and Techniques. Part 1\",\"description\":\"The needs of a codebase change over time. We have to implement new features that weren’t anticipated when the product was first designed, changing existing code to model a combination of old and new behaviors. Refactoring is an essential skill that allows us to accommodate new requirements without ever-increasing complexity.\\r\\n\\r\\nDuncan McGregor and Nat Pryce are authors of the book “Java to Kotlin: A Refactoring Guidebook”. Join them in this workshop to continue the journey. Together, you will refactor a web application from Kotlin to even better Kotlin, combining language features to ensure greater type safety, more explicit data flow, and a clear architecture.\\r\\n\\r\\nIn this workshop, you’ll learn how to:\\r\\n\\r\\n- Master the IntelliJ Platform’s Kotlin refactoring tools.\\r\\n- Devise a test strategy to safely refactor with confidence.\\r\\n- Plan multistep refactorings so that code continues to build and run.\\r\\n- Migrate from mutable objects to immutable data classes, functions, and state machines modeled with sealed class hierarchies.\\r\\n- Migrate a layered or Hexagon software architecture to - Functional Core, Imperative Shell.\\r\\n- Use AI to improve refactoring productivity.\",\"speakerIds\":[\"c471c1b0-53d7-45cf-a12c-340714972d83\",\"30cc8bd5-49a1-4609-bf70-ff5e6b12b3c2\"],\"location\":\"Room 176\",\"startsAt\":\"2024-05-22T09:00:00\",\"endsAt\":\"2024-05-22T10:30:00\",\"tags\":[\"Workshop\",\"Intermediate\"]},{\"id\":\"616765\",\"title\":\"Hands-On Kotlin Web Development with Ktor. Part 1\",\"description\":\"Ktor is a lightweight and flexible toolkit for building HTTP applications. This workshop will use the Kotlin programming language, the Ktor framework, the Exposed database access library, and several other Kotlin and Java libraries to build a feature-complete web application.\\r\\n\\r\\nWe’ll start with the basics by exploring the Ktor framework and learning how to build a simple web application using essential functions. We’ll cover topics like handling HTTP requests, working with WebSockets, database access, authentication, logging, and deployment.\\r\\n\\r\\nFor testing, we will look into the APIs that Ktor provides but also use the Testcontainers library for integration testing. Finally, we will explore the plugin API and write a simple plugin for our web application.\\r\\n\\r\\nBy the end of the workshop, you will know:\\r\\n\\r\\n- How to structure your Ktor project\\r\\n- How to test Ktor applications\\r\\n- How to create and deploy RESTful services using Ktor\\r\\n- How to integrate Ktor with external libraries\\r\\n\\r\\nThis will be a fast-paced workshop where attendees will spend most of their time coding. You will walk away armed with a cookbook of various Ktor recipes for building web applications.\",\"speakerIds\":[\"f58eda10-92dc-41a0-ac4a-b1a9f2bd7e97\",\"35f8da6a-8cfc-4e0d-9660-f616ca218e93\"],\"location\":\"Room 178\",\"startsAt\":\"2024-05-22T09:00:00\",\"endsAt\":\"2024-05-22T10:30:00\",\"tags\":[\"Workshop\",\"Intermediate\"]},{\"id\":\"616761\",\"title\":\"Functional Programming in Kotlin. Part 1\",\"description\":\"Functional programming has been on the rise, given its advantages in code readability and maintenance. In this workshop, we’ll look at concepts from functional programming that are directly applicable to Kotlin code. We’ll use Arrow as a supporting library, which includes many useful types and extensions to make a functional style even more pleasant. This workshop covers:\\r\\n\\r\\n- How to model your domain using hierarchies of data classes.\\r\\n- The importance of immutability and how it impacts your code style.\\r\\n- How to approach validation in a more composable way.\\r\\n- Keeping track of contexts and side effects.\\r\\n- Making asynchronous code more resilient with Arrow Fx.\",\"speakerIds\":[\"ea32e9a2-b68e-44c5-b4b7-6d2aa0dc3141\",\"3c5ac1d8-444e-48ee-89ff-d092279e950b\"],\"location\":\"Room 179\",\"startsAt\":\"2024-05-22T09:00:00\",\"endsAt\":\"2024-05-22T10:30:00\",\"tags\":[\"Workshop\",\"Intermediate\",\"Other\"]},{\"id\":\"616779\",\"title\":\"Reactive Spring Boot With Coroutines and Virtual Threads. Part 1\",\"description\":\"If you want to get the most out of Spring Boot in terms of low latency, high throughput, and resource efficiency, there’s no way around Spring Boot’s reactive stack WebFlux. However, the price you pay in terms of WebFlux code’s complexity, readability, and maintainability is rather high and will likely give you a lot of headaches.\\r\\n\\r\\nIn this workshop, you’ll learn how Spring Boot’s coroutine support will wipe out all the downsides of the ‘raw’ WebFlux approach and provide you with the best of both worlds: reactive characteristics without the complexity.\\r\\n\\r\\nYou’ll also explore Kotlin’s reactive building blocks, such as coroutines, channels, and flows, and apply them in Spring Boot. By building a reactive API in Spring Boot from scratch, you’ll learn how to:\\r\\n\\r\\n- Perform non-blocking remote API calls using WebClient.\\r\\n- Access a relational database with the reactive R2DBC driver.\\r\\n- Apply parallelism in your business logic.\\r\\n- Write and test reactive API endpoints.\\r\\n- Create an advanced streaming API based on Server-Sent Events that combines coroutines and flows.\\r\\n\\r\\nBy the end of the workshop, you’ll know all the ins and outs of reactive programming in Spring Boot with coroutines, as well as the benefits they offer over the WebFlux abstractions Mono and Flux.\\r\\n\\r\\nFurthermore, you’ll explore Project Loom’s virtual threads and see how they fit into the picture. You’ll also learn how virtual threads can further leverage the power of coroutines.\",\"speakerIds\":[\"7df2c791-134f-4279-bb68-23f8899bb1ac\",\"a9cd5609-7f60-4d7c-bea3-052c42118f16\"],\"location\":\"Room 180\",\"startsAt\":\"2024-05-22T09:00:00\",\"endsAt\":\"2024-05-22T10:30:00\",\"tags\":[\"Workshop\",\"Intermediate\"]},{\"id\":\"616757\",\"title\":\"Asynchronous Programming With Kotlin Coroutines. Part 1\",\"description\":\"In this workshop, you’ll learn everything you need to know about how to be productive with coroutines in Kotlin. We’ll start with the basics of asynchronous programming, its differences from blocking code, and the concepts of suspending functions and coroutines. We’ll explore coroutine contexts, concurrent decomposition of work via deferreds, and structured concurrency with coroutine scopes.\\r\\n\\r\\nThe second part of the workshop will be devoted to Kotlin Flows. We’ll study how Kotlin Flows are designed on a basic level, learn the difference between hot and cold flows, discuss their typical usage patterns, and explore how they incorporate ideas from reactive streams. To deepen our understanding, we’ll also take a peek at some of the implementations behind flows and collectors. Throughout, we’ll see how they help you in writing safe and reliable concurrent systems, and how modern applications can use them to work with asynchronous streams of data, manage system state, and broadcast events.\\r\\n\\r\\nThrough this workshop, you’ll enhance your coroutines-related vocabulary, understand how to spot and avoid common problems, and be able to effectively and confidently use coroutines and flows in your own projects.\",\"speakerIds\":[\"0f769b19-d5f2-49fb-aa78-a086aa046b7e\",\"a82c6942-6e2b-4d80-9883-0b84b932d6ef\",\"b2a19517-6d18-4ec1-9c40-7e29f4d862b1\"],\"location\":\"Room 181\",\"startsAt\":\"2024-05-22T09:00:00\",\"endsAt\":\"2024-05-22T10:30:00\",\"tags\":[\"Workshop\",\"Intermediate\",\"Other\"]},{\"id\":\"646517\",\"title\":\"Kotlin Multiplatform Beyond the Basics. Part 2\",\"description\":\"This is an intermediate / advanced workshop for experienced Android developers. It is aimed at engineers who have built projects with Kotlin and Jetpack Compose and now want to progress onto multiplatform application development.\\r\\n\\r\\nThe workshop is split into two parts. In the morning session, we’ll build an application entirely using Kotlin Multiplatform libraries. This will feature a Compose Multiplatform user interface, testing with kotlin.test and Kotest, and networking with Ktor and coroutines. Additional libraries will be used to show data caching, dependency injection, serialization, and more.\\r\\n\\r\\nIn the afternoon session, we’ll explore real-world issues associated with taking these kinds of applications into production. We’ll explore general issues with architecture and deployment but then shift our focus to issues specific to iOS. In particular, we’ll cover how best to package and expose Kotlin APIs to be consumed by Swift code, and vice versa. We’ll also explore how to share business logic with a SwiftUI interface, work with XCode, and distribute your application.\\r\\n\\r\\nMorning Topics\\r\\n- Review the basics of KMP development.\\r\\n- Introducing the workshop sample application.\\r\\n- Adding shared business logic with unit tests.\\r\\n- Platform integration with expected and actual declarations.\\r\\n- Extending the existing Compose Multiplatform UI.\\r\\n- Interacting with services via Ktor and coroutines.\\r\\n- Creating integration tests at different levels.\\r\\n- Refactoring the app to use dependency injection.\\r\\n- Adding client side caching to improve performance.\\r\\n\\r\\nAfternoon Topics\\r\\n- Best practices for building multiplatform applications.\\r\\n- Guidelines for creating and distributing your KMP library.\\r\\n- Making the most out of the existing KMP ecosystem.\\r\\n- A primer for using XCode effectively in KMP apps.\\r\\n- Effectively sharing Kotlin APIs with Swift codebases.\\r\\n- Mixing Compose Multiplatform and SwiftUI components.\\r\\n- Options for testing a Compose Multiplatform UI in iOS.\\r\\n- Distributing your shared code to iOS teammates.\",\"speakerIds\":[\"0fd04388-0a57-4c8e-9505-89d7962c2dba\",\"62216efe-dd8b-4d8b-9800-1d51b57c4001\"],\"location\":\"Room 173\",\"startsAt\":\"2024-05-22T11:00:00\",\"endsAt\":\"2024-05-22T12:30:00\",\"tags\":[\"Workshop\",\"Intermediate\",\"Other\"]},{\"id\":\"646507\",\"title\":\"Mastering Kotlin Refactoring – Tools and Techniques. Part 2\",\"description\":\"The needs of a codebase change over time. We have to implement new features that weren’t anticipated when the product was first designed, changing existing code to model a combination of old and new behaviors. Refactoring is an essential skill that allows us to accommodate new requirements without ever-increasing complexity.\\r\\n\\r\\nDuncan McGregor and Nat Pryce are authors of the book “Java to Kotlin: A Refactoring Guidebook”. Join them in this workshop to continue the journey. Together, you will refactor a web application from Kotlin to even better Kotlin, combining language features to ensure greater type safety, more explicit data flow, and a clear architecture.\\r\\n\\r\\nIn this workshop, you’ll learn how to:\\r\\n\\r\\n- Master the IntelliJ Platform’s Kotlin refactoring tools.\\r\\n- Devise a test strategy to safely refactor with confidence.\\r\\n- Plan multistep refactorings so that code continues to build and run.\\r\\n- Migrate from mutable objects to immutable data classes, functions, and state machines modeled with sealed class hierarchies.\\r\\n- Migrate a layered or Hexagon software architecture to - Functional Core, Imperative Shell.\\r\\n- Use AI to improve refactoring productivity.\",\"speakerIds\":[\"c471c1b0-53d7-45cf-a12c-340714972d83\",\"30cc8bd5-49a1-4609-bf70-ff5e6b12b3c2\"],\"location\":\"Room 176\",\"startsAt\":\"2024-05-22T11:00:00\",\"endsAt\":\"2024-05-22T12:30:00\",\"tags\":[\"Workshop\",\"Intermediate\"]},{\"id\":\"646495\",\"title\":\"Hands-On Kotlin Web Development with Ktor. Part 2\",\"description\":\"Ktor is a lightweight and flexible toolkit for building HTTP applications. This workshop will use the Kotlin programming language, the Ktor framework, the Exposed database access library, and several other Kotlin and Java libraries to build a feature-complete web application.\\r\\n\\r\\nWe’ll start with the basics by exploring the Ktor framework and learning how to build a simple web application using essential functions. We’ll cover topics like handling HTTP requests, working with WebSockets, database access, authentication, logging, and deployment.\\r\\n\\r\\nFor testing, we will look into the APIs that Ktor provides but also use the Testcontainers library for integration testing. Finally, we will explore the plugin API and write a simple plugin for our web application.\\r\\n\\r\\nBy the end of the workshop, you will know:\\r\\n\\r\\n- How to structure your Ktor project\\r\\n- How to test Ktor applications\\r\\n- How to create and deploy RESTful services using Ktor\\r\\n- How to integrate Ktor with external libraries\\r\\n\\r\\nThis will be a fast-paced workshop where attendees will spend most of their time coding. You will walk away armed with a cookbook of various Ktor recipes for building web applications.\",\"speakerIds\":[\"f58eda10-92dc-41a0-ac4a-b1a9f2bd7e97\",\"35f8da6a-8cfc-4e0d-9660-f616ca218e93\"],\"location\":\"Room 178\",\"startsAt\":\"2024-05-22T11:00:00\",\"endsAt\":\"2024-05-22T12:30:00\",\"tags\":[\"Workshop\",\"Intermediate\"]},{\"id\":\"646512\",\"title\":\"Functional Programming in Kotlin. Part 2\",\"description\":\"Functional programming has been on the rise, given its advantages in code readability and maintenance. In this workshop, we’ll look at concepts from functional programming that are directly applicable to Kotlin code. We’ll use Arrow as a supporting library, which includes many useful types and extensions to make a functional style even more pleasant. This workshop covers:\\r\\n\\r\\n- How to model your domain using hierarchies of data classes.\\r\\n- The importance of immutability and how it impacts your code style.\\r\\n- How to approach validation in a more composable way.\\r\\n- Keeping track of contexts and side effects.\\r\\n- Making asynchronous code more resilient with Arrow Fx.\",\"speakerIds\":[\"ea32e9a2-b68e-44c5-b4b7-6d2aa0dc3141\",\"3c5ac1d8-444e-48ee-89ff-d092279e950b\"],\"location\":\"Room 179\",\"startsAt\":\"2024-05-22T11:00:00\",\"endsAt\":\"2024-05-22T12:30:00\",\"tags\":[\"Workshop\",\"Intermediate\",\"Other\"]},{\"id\":\"646477\",\"title\":\"Reactive Spring Boot With Coroutines and Virtual Threads. Part 2\",\"description\":\"If you want to get the most out of Spring Boot in terms of low latency, high throughput, and resource efficiency, there’s no way around Spring Boot’s reactive stack WebFlux. However, the price you pay in terms of WebFlux code’s complexity, readability, and maintainability is rather high and will likely give you a lot of headaches.\\r\\n\\r\\nIn this workshop, you’ll learn how Spring Boot’s coroutine support will wipe out all the downsides of the ‘raw’ WebFlux approach and provide you with the best of both worlds: reactive characteristics without the complexity.\\r\\n\\r\\nYou’ll also explore Kotlin’s reactive building blocks, such as coroutines, channels, and flows, and apply them in Spring Boot. By building a reactive API in Spring Boot from scratch, you’ll learn how to:\\r\\n\\r\\n- Perform non-blocking remote API calls using WebClient.\\r\\n- Access a relational database with the reactive R2DBC driver.\\r\\n- Apply parallelism in your business logic.\\r\\n- Write and test reactive API endpoints.\\r\\n- Create an advanced streaming API based on Server-Sent Events that combines coroutines and flows.\\r\\n\\r\\nBy the end of the workshop, you’ll know all the ins and outs of reactive programming in Spring Boot with coroutines, as well as the benefits they offer over the WebFlux abstractions Mono and Flux.\\r\\n\\r\\nFurthermore, you’ll explore Project Loom’s virtual threads and see how they fit into the picture. You’ll also learn how virtual threads can further leverage the power of coroutines.\",\"speakerIds\":[\"7df2c791-134f-4279-bb68-23f8899bb1ac\",\"a9cd5609-7f60-4d7c-bea3-052c42118f16\"],\"location\":\"Room 180\",\"startsAt\":\"2024-05-22T11:00:00\",\"endsAt\":\"2024-05-22T12:30:00\",\"tags\":[\"Workshop\",\"Intermediate\"]},{\"id\":\"646520\",\"title\":\"Asynchronous Programming With Kotlin Coroutines. Part 2\",\"description\":\"In this workshop, you’ll learn everything you need to know about how to be productive with coroutines in Kotlin. We’ll start with the basics of asynchronous programming, its differences from blocking code, and the concepts of suspending functions and coroutines. We’ll explore coroutine contexts, concurrent decomposition of work via deferreds, and structured concurrency with coroutine scopes.\\r\\n\\r\\nThe second part of the workshop will be devoted to Kotlin Flows. We’ll study how Kotlin Flows are designed on a basic level, learn the difference between hot and cold flows, discuss their typical usage patterns, and explore how they incorporate ideas from reactive streams. To deepen our understanding, we’ll also take a peek at some of the implementations behind flows and collectors. Throughout, we’ll see how they help you in writing safe and reliable concurrent systems, and how modern applications can use them to work with asynchronous streams of data, manage system state, and broadcast events.\\r\\n\\r\\nThrough this workshop, you’ll enhance your coroutines-related vocabulary, understand how to spot and avoid common problems, and be able to effectively and confidently use coroutines and flows in your own projects.\",\"speakerIds\":[\"a82c6942-6e2b-4d80-9883-0b84b932d6ef\",\"b2a19517-6d18-4ec1-9c40-7e29f4d862b1\",\"5307510b-c3fa-4f9c-a340-36d198198ef5\"],\"location\":\"Room 181\",\"startsAt\":\"2024-05-22T11:00:00\",\"endsAt\":\"2024-05-22T12:30:00\",\"tags\":[\"Workshop\",\"Intermediate\",\"Other\"]},{\"id\":\"646518\",\"title\":\"Kotlin Multiplatform Beyond the Basics. Part 3\",\"description\":\"This is an intermediate / advanced workshop for experienced Android developers. It is aimed at engineers who have built projects with Kotlin and Jetpack Compose and now want to progress onto multiplatform application development.\\r\\n\\r\\nThe workshop is split into two parts. In the morning session, we’ll build an application entirely using Kotlin Multiplatform libraries. This will feature a Compose Multiplatform user interface, testing with kotlin.test and Kotest, and networking with Ktor and coroutines. Additional libraries will be used to show data caching, dependency injection, serialization, and more.\\r\\n\\r\\nIn the afternoon session, we’ll explore real-world issues associated with taking these kinds of applications into production. We’ll explore general issues with architecture and deployment but then shift our focus to issues specific to iOS. In particular, we’ll cover how best to package and expose Kotlin APIs to be consumed by Swift code, and vice versa. We’ll also explore how to share business logic with a SwiftUI interface, work with XCode, and distribute your application.\\r\\n\\r\\nMorning Topics\\r\\n- Review the basics of KMP development.\\r\\n- Introducing the workshop sample application.\\r\\n- Adding shared business logic with unit tests.\\r\\n- Platform integration with expected and actual declarations.\\r\\n- Extending the existing Compose Multiplatform UI.\\r\\n- Interacting with services via Ktor and coroutines.\\r\\n- Creating integration tests at different levels.\\r\\n- Refactoring the app to use dependency injection.\\r\\n- Adding client side caching to improve performance.\\r\\n\\r\\nAfternoon Topics\\r\\n- Best practices for building multiplatform applications.\\r\\n- Guidelines for creating and distributing your KMP library.\\r\\n- Making the most out of the existing KMP ecosystem.\\r\\n- A primer for using XCode effectively in KMP apps.\\r\\n- Effectively sharing Kotlin APIs with Swift codebases.\\r\\n- Mixing Compose Multiplatform and SwiftUI components.\\r\\n- Options for testing a Compose Multiplatform UI in iOS.\\r\\n- Distributing your shared code to iOS teammates.\",\"speakerIds\":[\"0fd04388-0a57-4c8e-9505-89d7962c2dba\",\"62216efe-dd8b-4d8b-9800-1d51b57c4001\"],\"location\":\"Room 173\",\"startsAt\":\"2024-05-22T13:30:00\",\"endsAt\":\"2024-05-22T15:00:00\",\"tags\":[\"Workshop\",\"Intermediate\",\"Other\"]},{\"id\":\"646509\",\"title\":\"Mastering Kotlin Refactoring – Tools and Techniques. Part 3\",\"description\":\"The needs of a codebase change over time. We have to implement new features that weren’t anticipated when the product was first designed, changing existing code to model a combination of old and new behaviors. Refactoring is an essential skill that allows us to accommodate new requirements without ever-increasing complexity.\\r\\n\\r\\nDuncan McGregor and Nat Pryce are authors of the book “Java to Kotlin: A Refactoring Guidebook”. Join them in this workshop to continue the journey. Together, you will refactor a web application from Kotlin to even better Kotlin, combining language features to ensure greater type safety, more explicit data flow, and a clear architecture.\\r\\n\\r\\nIn this workshop, you’ll learn how to:\\r\\n\\r\\n- Master the IntelliJ Platform’s Kotlin refactoring tools.\\r\\n- Devise a test strategy to safely refactor with confidence.\\r\\n- Plan multistep refactorings so that code continues to build and run.\\r\\n- Migrate from mutable objects to immutable data classes, functions, and state machines modeled with sealed class hierarchies.\\r\\n- Migrate a layered or Hexagon software architecture to - Functional Core, Imperative Shell.\\r\\n- Use AI to improve refactoring productivity.\",\"speakerIds\":[\"c471c1b0-53d7-45cf-a12c-340714972d83\",\"30cc8bd5-49a1-4609-bf70-ff5e6b12b3c2\"],\"location\":\"Room 176\",\"startsAt\":\"2024-05-22T13:30:00\",\"endsAt\":\"2024-05-22T15:00:00\",\"tags\":[\"Workshop\",\"Intermediate\"]},{\"id\":\"646497\",\"title\":\"Hands-On Kotlin Web Development with Ktor. Part 3\",\"description\":\"Ktor is a lightweight and flexible toolkit for building HTTP applications. This workshop will use the Kotlin programming language, the Ktor framework, the Exposed database access library, and several other Kotlin and Java libraries to build a feature-complete web application.\\r\\n\\r\\nWe’ll start with the basics by exploring the Ktor framework and learning how to build a simple web application using essential functions. We’ll cover topics like handling HTTP requests, working with WebSockets, database access, authentication, logging, and deployment.\\r\\n\\r\\nFor testing, we will look into the APIs that Ktor provides but also use the Testcontainers library for integration testing. Finally, we will explore the plugin API and write a simple plugin for our web application.\\r\\n\\r\\nBy the end of the workshop, you will know:\\r\\n\\r\\n- How to structure your Ktor project\\r\\n- How to test Ktor applications\\r\\n- How to create and deploy RESTful services using Ktor\\r\\n- How to integrate Ktor with external libraries\\r\\n\\r\\nThis will be a fast-paced workshop where attendees will spend most of their time coding. You will walk away armed with a cookbook of various Ktor recipes for building web applications.\",\"speakerIds\":[\"f58eda10-92dc-41a0-ac4a-b1a9f2bd7e97\",\"35f8da6a-8cfc-4e0d-9660-f616ca218e93\"],\"location\":\"Room 178\",\"startsAt\":\"2024-05-22T13:30:00\",\"endsAt\":\"2024-05-22T15:00:00\",\"tags\":[\"Workshop\",\"Intermediate\"]},{\"id\":\"646513\",\"title\":\"Functional Programming in Kotlin. Part 3\",\"description\":\"Functional programming has been on the rise, given its advantages in code readability and maintenance. In this workshop, we’ll look at concepts from functional programming that are directly applicable to Kotlin code. We’ll use Arrow as a supporting library, which includes many useful types and extensions to make a functional style even more pleasant. This workshop covers:\\r\\n\\r\\n- How to model your domain using hierarchies of data classes.\\r\\n- The importance of immutability and how it impacts your code style.\\r\\n- How to approach validation in a more composable way.\\r\\n- Keeping track of contexts and side effects.\\r\\n- Making asynchronous code more resilient with Arrow Fx.\",\"speakerIds\":[\"ea32e9a2-b68e-44c5-b4b7-6d2aa0dc3141\",\"3c5ac1d8-444e-48ee-89ff-d092279e950b\"],\"location\":\"Room 179\",\"startsAt\":\"2024-05-22T13:30:00\",\"endsAt\":\"2024-05-22T15:00:00\",\"tags\":[\"Workshop\",\"Intermediate\",\"Other\"]},{\"id\":\"646491\",\"title\":\"Reactive Spring Boot With Coroutines and Virtual Threads. Part 3\",\"description\":\"If you want to get the most out of Spring Boot in terms of low latency, high throughput, and resource efficiency, there’s no way around Spring Boot’s reactive stack WebFlux. However, the price you pay in terms of WebFlux code’s complexity, readability, and maintainability is rather high and will likely give you a lot of headaches.\\r\\n\\r\\nIn this workshop, you’ll learn how Spring Boot’s coroutine support will wipe out all the downsides of the ‘raw’ WebFlux approach and provide you with the best of both worlds: reactive characteristics without the complexity.\\r\\n\\r\\nYou’ll also explore Kotlin’s reactive building blocks, such as coroutines, channels, and flows, and apply them in Spring Boot. By building a reactive API in Spring Boot from scratch, you’ll learn how to:\\r\\n\\r\\n- Perform non-blocking remote API calls using WebClient.\\r\\n- Access a relational database with the reactive R2DBC driver.\\r\\n- Apply parallelism in your business logic.\\r\\n- Write and test reactive API endpoints.\\r\\n- Create an advanced streaming API based on Server-Sent Events that combines coroutines and flows.\\r\\n\\r\\nBy the end of the workshop, you’ll know all the ins and outs of reactive programming in Spring Boot with coroutines, as well as the benefits they offer over the WebFlux abstractions Mono and Flux.\\r\\n\\r\\nFurthermore, you’ll explore Project Loom’s virtual threads and see how they fit into the picture. You’ll also learn how virtual threads can further leverage the power of coroutines.\",\"speakerIds\":[\"7df2c791-134f-4279-bb68-23f8899bb1ac\",\"a9cd5609-7f60-4d7c-bea3-052c42118f16\"],\"location\":\"Room 180\",\"startsAt\":\"2024-05-22T13:30:00\",\"endsAt\":\"2024-05-22T15:00:00\",\"tags\":[\"Workshop\",\"Intermediate\"]},{\"id\":\"646521\",\"title\":\"Asynchronous Programming With Kotlin Coroutines. Part 3\",\"description\":\"In this workshop, you’ll learn everything you need to know about how to be productive with coroutines in Kotlin. We’ll start with the basics of asynchronous programming, its differences from blocking code, and the concepts of suspending functions and coroutines. We’ll explore coroutine contexts, concurrent decomposition of work via deferreds, and structured concurrency with coroutine scopes.\\r\\n\\r\\nThe second part of the workshop will be devoted to Kotlin Flows. We’ll study how Kotlin Flows are designed on a basic level, learn the difference between hot and cold flows, discuss their typical usage patterns, and explore how they incorporate ideas from reactive streams. To deepen our understanding, we’ll also take a peek at some of the implementations behind flows and collectors. Throughout, we’ll see how they help you in writing safe and reliable concurrent systems, and how modern applications can use them to work with asynchronous streams of data, manage system state, and broadcast events.\\r\\n\\r\\nThrough this workshop, you’ll enhance your coroutines-related vocabulary, understand how to spot and avoid common problems, and be able to effectively and confidently use coroutines and flows in your own projects.\",\"speakerIds\":[\"a82c6942-6e2b-4d80-9883-0b84b932d6ef\",\"b2a19517-6d18-4ec1-9c40-7e29f4d862b1\",\"5307510b-c3fa-4f9c-a340-36d198198ef5\"],\"location\":\"Room 181\",\"startsAt\":\"2024-05-22T13:30:00\",\"endsAt\":\"2024-05-22T15:00:00\",\"tags\":[\"Workshop\",\"Intermediate\",\"Other\"]},{\"id\":\"646519\",\"title\":\"Kotlin Multiplatform Beyond the Basics. Part 4\",\"description\":\"This is an intermediate / advanced workshop for experienced Android developers. It is aimed at engineers who have built projects with Kotlin and Jetpack Compose and now want to progress onto multiplatform application development.\\r\\n\\r\\nThe workshop is split into two parts. In the morning session, we’ll build an application entirely using Kotlin Multiplatform libraries. This will feature a Compose Multiplatform user interface, testing with kotlin.test and Kotest, and networking with Ktor and coroutines. Additional libraries will be used to show data caching, dependency injection, serialization, and more.\\r\\n\\r\\nIn the afternoon session, we’ll explore real-world issues associated with taking these kinds of applications into production. We’ll explore general issues with architecture and deployment but then shift our focus to issues specific to iOS. In particular, we’ll cover how best to package and expose Kotlin APIs to be consumed by Swift code, and vice versa. We’ll also explore how to share business logic with a SwiftUI interface, work with XCode, and distribute your application.\\r\\n\\r\\nMorning Topics\\r\\n- Review the basics of KMP development.\\r\\n- Introducing the workshop sample application.\\r\\n- Adding shared business logic with unit tests.\\r\\n- Platform integration with expected and actual declarations.\\r\\n- Extending the existing Compose Multiplatform UI.\\r\\n- Interacting with services via Ktor and coroutines.\\r\\n- Creating integration tests at different levels.\\r\\n- Refactoring the app to use dependency injection.\\r\\n- Adding client side caching to improve performance.\\r\\n\\r\\nAfternoon Topics\\r\\n- Best practices for building multiplatform applications.\\r\\n- Guidelines for creating and distributing your KMP library.\\r\\n- Making the most out of the existing KMP ecosystem.\\r\\n- A primer for using XCode effectively in KMP apps.\\r\\n- Effectively sharing Kotlin APIs with Swift codebases.\\r\\n- Mixing Compose Multiplatform and SwiftUI components.\\r\\n- Options for testing a Compose Multiplatform UI in iOS.\\r\\n- Distributing your shared code to iOS teammates.\",\"speakerIds\":[\"0fd04388-0a57-4c8e-9505-89d7962c2dba\",\"62216efe-dd8b-4d8b-9800-1d51b57c4001\"],\"location\":\"Room 173\",\"startsAt\":\"2024-05-22T15:30:00\",\"endsAt\":\"2024-05-22T17:00:00\",\"tags\":[\"Workshop\",\"Intermediate\",\"Other\"]},{\"id\":\"646510\",\"title\":\"Mastering Kotlin Refactoring – Tools and Techniques. Part 4\",\"description\":\"The needs of a codebase change over time. We have to implement new features that weren’t anticipated when the product was first designed, changing existing code to model a combination of old and new behaviors. Refactoring is an essential skill that allows us to accommodate new requirements without ever-increasing complexity.\\r\\n\\r\\nDuncan McGregor and Nat Pryce are authors of the book “Java to Kotlin: A Refactoring Guidebook”. Join them in this workshop to continue the journey. Together, you will refactor a web application from Kotlin to even better Kotlin, combining language features to ensure greater type safety, more explicit data flow, and a clear architecture.\\r\\n\\r\\nIn this workshop, you’ll learn how to:\\r\\n\\r\\n- Master the IntelliJ Platform’s Kotlin refactoring tools.\\r\\n- Devise a test strategy to safely refactor with confidence.\\r\\n- Plan multistep refactorings so that code continues to build and run.\\r\\n- Migrate from mutable objects to immutable data classes, functions, and state machines modeled with sealed class hierarchies.\\r\\n- Migrate a layered or Hexagon software architecture to - Functional Core, Imperative Shell.\\r\\n- Use AI to improve refactoring productivity.\",\"speakerIds\":[\"c471c1b0-53d7-45cf-a12c-340714972d83\",\"30cc8bd5-49a1-4609-bf70-ff5e6b12b3c2\"],\"location\":\"Room 176\",\"startsAt\":\"2024-05-22T15:30:00\",\"endsAt\":\"2024-05-22T17:00:00\",\"tags\":[\"Workshop\",\"Intermediate\"]},{\"id\":\"646498\",\"title\":\"Hands-On Kotlin Web Development with Ktor. Part 4\",\"description\":\"Ktor is a lightweight and flexible toolkit for building HTTP applications. This workshop will use the Kotlin programming language, the Ktor framework, the Exposed database access library, and several other Kotlin and Java libraries to build a feature-complete web application.\\r\\n\\r\\nWe’ll start with the basics by exploring the Ktor framework and learning how to build a simple web application using essential functions. We’ll cover topics like handling HTTP requests, working with WebSockets, database access, authentication, logging, and deployment.\\r\\n\\r\\nFor testing, we will look into the APIs that Ktor provides but also use the Testcontainers library for integration testing. Finally, we will explore the plugin API and write a simple plugin for our web application.\\r\\n\\r\\nBy the end of the workshop, you will know:\\r\\n\\r\\n- How to structure your Ktor project\\r\\n- How to test Ktor applications\\r\\n- How to create and deploy RESTful services using Ktor\\r\\n- How to integrate Ktor with external libraries\\r\\n\\r\\nThis will be a fast-paced workshop where attendees will spend most of their time coding. You will walk away armed with a cookbook of various Ktor recipes for building web applications.\",\"speakerIds\":[\"f58eda10-92dc-41a0-ac4a-b1a9f2bd7e97\",\"35f8da6a-8cfc-4e0d-9660-f616ca218e93\"],\"location\":\"Room 178\",\"startsAt\":\"2024-05-22T15:30:00\",\"endsAt\":\"2024-05-22T17:00:00\",\"tags\":[\"Workshop\",\"Intermediate\"]},{\"id\":\"646514\",\"title\":\"Functional Programming in Kotlin. Part 4\",\"description\":\"Functional programming has been on the rise, given its advantages in code readability and maintenance. In this workshop, we’ll look at concepts from functional programming that are directly applicable to Kotlin code. We’ll use Arrow as a supporting library, which includes many useful types and extensions to make a functional style even more pleasant. This workshop covers:\\r\\n\\r\\n- How to model your domain using hierarchies of data classes.\\r\\n- The importance of immutability and how it impacts your code style.\\r\\n- How to approach validation in a more composable way.\\r\\n- Keeping track of contexts and side effects.\\r\\n- Making asynchronous code more resilient with Arrow Fx.\",\"speakerIds\":[\"ea32e9a2-b68e-44c5-b4b7-6d2aa0dc3141\",\"3c5ac1d8-444e-48ee-89ff-d092279e950b\"],\"location\":\"Room 179\",\"startsAt\":\"2024-05-22T15:30:00\",\"endsAt\":\"2024-05-22T17:00:00\",\"tags\":[\"Workshop\",\"Intermediate\",\"Other\"]},{\"id\":\"646493\",\"title\":\"Reactive Spring Boot With Coroutines and Virtual Threads. Part 4\",\"description\":\"If you want to get the most out of Spring Boot in terms of low latency, high throughput, and resource efficiency, there’s no way around Spring Boot’s reactive stack WebFlux. However, the price you pay in terms of WebFlux code’s complexity, readability, and maintainability is rather high and will likely give you a lot of headaches.\\r\\n\\r\\nIn this workshop, you’ll learn how Spring Boot’s coroutine support will wipe out all the downsides of the ‘raw’ WebFlux approach and provide you with the best of both worlds: reactive characteristics without the complexity.\\r\\n\\r\\nYou’ll also explore Kotlin’s reactive building blocks, such as coroutines, channels, and flows, and apply them in Spring Boot. By building a reactive API in Spring Boot from scratch, you’ll learn how to:\\r\\n\\r\\n- Perform non-blocking remote API calls using WebClient.\\r\\n- Access a relational database with the reactive R2DBC driver.\\r\\n- Apply parallelism in your business logic.\\r\\n- Write and test reactive API endpoints.\\r\\n- Create an advanced streaming API based on Server-Sent Events that combines coroutines and flows.\\r\\n\\r\\nBy the end of the workshop, you’ll know all the ins and outs of reactive programming in Spring Boot with coroutines, as well as the benefits they offer over the WebFlux abstractions Mono and Flux.\\r\\n\\r\\nFurthermore, you’ll explore Project Loom’s virtual threads and see how they fit into the picture. You’ll also learn how virtual threads can further leverage the power of coroutines.\",\"speakerIds\":[\"7df2c791-134f-4279-bb68-23f8899bb1ac\",\"a9cd5609-7f60-4d7c-bea3-052c42118f16\"],\"location\":\"Room 180\",\"startsAt\":\"2024-05-22T15:30:00\",\"endsAt\":\"2024-05-22T17:00:00\",\"tags\":[\"Workshop\",\"Intermediate\"]},{\"id\":\"646523\",\"title\":\"Asynchronous Programming With Kotlin Coroutines. Part 4\",\"description\":\"In this workshop, you’ll learn everything you need to know about how to be productive with coroutines in Kotlin. We’ll start with the basics of asynchronous programming, its differences from blocking code, and the concepts of suspending functions and coroutines. We’ll explore coroutine contexts, concurrent decomposition of work via deferreds, and structured concurrency with coroutine scopes.\\r\\n\\r\\nThe second part of the workshop will be devoted to Kotlin Flows. We’ll study how Kotlin Flows are designed on a basic level, learn the difference between hot and cold flows, discuss their typical usage patterns, and explore how they incorporate ideas from reactive streams. To deepen our understanding, we’ll also take a peek at some of the implementations behind flows and collectors. Throughout, we’ll see how they help you in writing safe and reliable concurrent systems, and how modern applications can use them to work with asynchronous streams of data, manage system state, and broadcast events.\\r\\n\\r\\nThrough this workshop, you’ll enhance your coroutines-related vocabulary, understand how to spot and avoid common problems, and be able to effectively and confidently use coroutines and flows in your own projects.\",\"speakerIds\":[\"a82c6942-6e2b-4d80-9883-0b84b932d6ef\",\"b2a19517-6d18-4ec1-9c40-7e29f4d862b1\",\"5307510b-c3fa-4f9c-a340-36d198198ef5\"],\"location\":\"Room 181\",\"startsAt\":\"2024-05-22T15:30:00\",\"endsAt\":\"2024-05-22T17:00:00\",\"tags\":[\"Workshop\",\"Intermediate\",\"Other\"]},{\"id\":\"623200\",\"title\":\"Opening Keynote\",\"description\":\"\",\"speakerIds\":[\"9ff98d8b-f176-49b9-a871-339cf8fad50b\",\"08416a0a-bb37-4e33-b1e5-2d1f2e2102eb\",\"cdc62a79-11fb-4c29-b021-81935c453521\",\"fd9a742d-2e4a-4c87-86ee-b8e03a0984a0\",\"5b2f8184-971a-400c-982d-c33683fd5d61\",\"b2a19517-6d18-4ec1-9c40-7e29f4d862b1\",\"a82c6942-6e2b-4d80-9883-0b84b932d6ef\",\"0f769b19-d5f2-49fb-aa78-a086aa046b7e\",\"c53e7302-d53c-4c56-ae42-693a74de8ba6\"],\"location\":\"Hall A\",\"startsAt\":\"2024-05-23T09:00:00\",\"endsAt\":\"2024-05-23T10:00:00\",\"tags\":[\"Regular Session\",\"Introductory and overview\"]},{\"id\":\"587051\",\"title\":\"A Tale of Two Languages\",\"description\":\"Java has been part of the industry for almost 30 years. Kotlin joined the party around 12 years ago. Their evolution has been exciting, but more importantly, mutually beneficial. This talk compares the evolution of Java and Kotlin and highlights areas where they are influencing and improving each other.\",\"speakerIds\":[\"b94daf79-b12a-4257-8556-38d500bb414b\"],\"location\":\"Hall A\",\"startsAt\":\"2024-05-23T10:15:00\",\"endsAt\":\"2024-05-23T11:00:00\",\"tags\":[\"Regular Session\",\"Intermediate\",\"Other\"]},{\"id\":\"586193\",\"title\":\"Unlocking the Power of Arrow 2.0: A Comprehensive Guide\",\"description\":\"We’ll dive into Arrow 2.0, a transformative update to Kotlin's functional programming landscape. Join the maintainer for an enlightening tour of Arrow 2.0's advancements, including typed error handling for safer code, seamless integration with Kotlin Coroutines for concurrent programming, resilient programming techniques, and elegant approaches to working with immutable data structures. Arrow 2.0 represents a significant milestone in our journey to make Functional Programming in Kotlin truly idiomatic, simple, and elegant to empower developers to write expressive, efficient, and reliable code. Whether you're a seasoned functional programmer or a Kotlin enthusiast, this session promises practical insights into mastering Arrow 2.0 and navigating the functional frontier in Kotlin.\",\"speakerIds\":[\"ea32e9a2-b68e-44c5-b4b7-6d2aa0dc3141\"],\"location\":\"Auditorium 15\",\"startsAt\":\"2024-05-23T10:15:00\",\"endsAt\":\"2024-05-23T11:00:00\",\"tags\":[\"Regular Session\",\"Introductory and overview\",\"Libraries\"]},{\"id\":\"584799\",\"title\":\"Compose Multiplatform on mobile at Instabee for over a year\",\"description\":\"Kotlin Multiplatform and Compose Multiplatform: Our experience of experimenting and developing some cross-platform apps targeting Android and iOS, and the lessons we learnt running it in production for over a year.\",\"speakerIds\":[\"9369d066-526c-434b-9dea-d5925d03940f\",\"4029e453-72f6-473f-bb08-e3ad5da66f84\"],\"location\":\"Auditorium 12\",\"startsAt\":\"2024-05-23T10:15:00\",\"endsAt\":\"2024-05-23T11:00:00\",\"tags\":[\"Regular Session\",\"Intermediate\",\"Multiplatform\"]},{\"id\":\"585375\",\"title\":\"There's more than a mouse - how to truly integrate your app on the Desktop\",\"description\":\"With Compose Multiplatform, it has become easier than ever to bring your apps to the Desktop. However, to achieve a deep integration into the platform, it takes more than porting the UI. Like mobile platforms, the Desktop has unique interaction features, for example drag and drop, file associations, menu bars, system tray, and the system clipboard. Compose Multiplatform assists you in utilizing some of them, but a true integration takes more. This talk identifies Desktop-specific interaction features and explains how to integrate them into your app, using Compose Multiplatform and some additional libraries.\",\"speakerIds\":[\"b18a2e1f-3904-48e8-b0bb-45b3942ebc69\"],\"location\":\"Auditorium 11\",\"startsAt\":\"2024-05-23T10:15:00\",\"endsAt\":\"2024-05-23T11:00:00\",\"tags\":[\"Regular Session\",\"Advanced\",\"Multiplatform\"]},{\"id\":\"627087\",\"title\":\"K2: How to make a better compiler but keep Kotlin the same\",\"description\":\"As a former TechLead of the K2 project, I’ll tell you how and why we switched from refactoring to rewriting the Compiler Frontend. Beginning the not-inconsiderable journey that brought us to Kotlin 2.0\\r\\n\\r\\n“We need a better architecture” - probably, everyone in software development heard at least once.\\r\\nHowever, “OK, let’s make it” rarely follows. \\r\\nBut, one does not simply refactor the Kotlin 1.1 compiler to solve its problems.\\r\\nSo… We decided to re-write a considerable part of it.\\r\\n\\r\\nI’ll tell you about: \\r\\n- Why did we re-implement the huge compiler part, and what does an FIR tree have to do with it\\r\\n- How we test the compiler and ensure a smooth transition to the new version\\r\\n- How to make the new compiler but keep the language the same\\r\\n- Last, what is EAP feedback, and why is it so important \\r\\n\",\"speakerIds\":[\"e2f202a0-595e-42d4-921c-f94433fa68e5\"],\"location\":\"Auditorium 10 (Lightning talks)\",\"startsAt\":\"2024-05-23T10:15:00\",\"endsAt\":\"2024-05-23T10:30:00\",\"tags\":[\"Lightning talk\",\"Introductory and overview\",\"Other\"]},{\"id\":\"586856\",\"title\":\"kotlinx.rpc – a brand new approach for multiplatform RPC\",\"description\":\"kotlinx.rpc is a multiplatform library that allows its users to easily set up RPC (Remote Procedure Calls) services for their needs.\\r\\n\\r\\nThe library is purely Kotlin, and that is more than just being written in Kotlin - we use language constructs to represent the work with the network and services. For example, we use Kotlin interfaces to declare a service and then we use its implementation to provide server functionality. This makes the setup very straightforward and also works for seamless navigation in your IDE. We utilize the power of Kotlin Multiplatform to provide the best code-sharing experience. We use coroutines to make network calls and manage request lifecycles. We forward exceptions from the server and form the stacktrace as there were no intermediate steps in between. And many more.\\r\\n\\r\\nThis talk will familiarize the audience with the library and give the knowledge of how to start using the library in their projects, making their network code even more concise and easy to understand. The audience will have a brief knowledge of how it all works internally without the need to dive deep into the source code.\",\"speakerIds\":[\"155ea7e0-6dc1-45c7-94c8-055475838101\"],\"location\":\"Auditorium 10 (Lightning talks)\",\"startsAt\":\"2024-05-23T10:40:00\",\"endsAt\":\"2024-05-23T10:55:00\",\"tags\":[\"Lightning talk\",\"Intermediate\",\"Libraries\"]},{\"id\":\"671726\",\"title\":\"Kotlin Language Features in 2.0 and Beyond\",\"description\":\"This talk will provide an overview of the enhancements and additions in Kotlin 2.0, including the new control flow engine and frontend intermediate representation and how it helps with language consistency. We will also discuss the long-term vision for Kotlin, focusing on how the upcoming language features, such as context parameters, signature management, and immutability, will support modern software development trends and challenges that we face today in our ecosystem\",\"speakerIds\":[\"08416a0a-bb37-4e33-b1e5-2d1f2e2102eb\"],\"location\":\"Hall A\",\"startsAt\":\"2024-05-23T11:15:00\",\"endsAt\":\"2024-05-23T12:00:00\",\"tags\":[\"Regular Session\",\"Intermediate\",\"Other\"]},{\"id\":\"664992\",\"title\":\"Hitchhiker’s Guide to Kotlin Multiplatform Libraries\",\"description\":\"This talk will use the various Kotlin Multiplatform (KMP) samples I've been working on over the last 5+ years to provide a guided tour of a number of the key libraries used within them.\\r\\n\\r\\nIt will include overview and examples of the following KMP/CMP libraries:\\r\\n- Persistence: SQLDelight, Realm, Apollo Kotlin, Jetpack Room, Multiplatform Settings, Jetpack DataStore\\r\\n- Remote API requests: Ktor, Apollo Kotlin\\r\\n- Dependency Injection: Koin\\r\\n- ViewModel/Component sharing: KMM-ViewModel, Jetpack ViewModel, Decompose\\r\\n- Navigation: Voyager, Jetpack Navigation\\r\\n- Swift/Kotlin interop: KMP-NativeCoroutines, SKIE\\r\\n- Packaging: Multiplatform Swift Package, KMMBridge\\r\\n- Compose UI Multiplatform: Window Size Class, Markdown Renderer, Coil, KoalaPlot, Compose on iOS\\r\\n\\r\\nIt will also cover examples from the various clients which were developed using:\\r\\n- SwiftUI (on iOS, watchOS, and macOS)\\r\\n- Jetpack Compose (on Android and Wear OS)\\r\\n- Compose Multiplatform on Desktop, Web (using Wasm) and iOS (also includes examples of sharing Compose UI across multiple platforms).\",\"speakerIds\":[\"0392772c-28d4-47f6-bd39-47d743fb4a81\"],\"location\":\"Auditorium 15\",\"startsAt\":\"2024-05-23T11:15:00\",\"endsAt\":\"2024-05-23T12:00:00\",\"tags\":[\"Regular Session\",\"Intermediate\",\"Multiplatform\"]},{\"id\":\"569136\",\"title\":\"Harmonizing Kotlin codebase with Konsist\",\"description\":\"Jane had always been passionate about coding, and the opportunity to work as a Kotlin developer was a dream come true. Shortly after starting a new job, Jane was assigned her first significant task: adding a new use case to the project. Excitement bubbled within her. This was a chance to prove herself, to make a meaningful impact. The task seemed straightforward enough, but she wanted to make sure she aligned her work with the established patterns of the project codebase. So, Jane began exploring the existing use cases, opening file after file, and digging into the structures and logic. She expected to find a consistent pattern in the project codebase, something that would guide her in crafting the new use case. But what she found was a bit overwhelming — every use case was different…\\r\\n\\r\\nWe've all been in this situation — stepping into a new project and taking a moment to build a mental picture of the project. The project's complexity is often attributed to a code base that's riddled with inconsistencies, tangled connections, and disarray. \\r\\n\\r\\nWhat if we could quickly create rules for guarding project consistency? Imagine being able to swiftly enforce coding standards tailored to your project and modify them with ease when necessary.\\r\\n\\r\\nEmbark on a journey with Konsist: the next-generation structural linter destined to revolutionize Kotlin code consistency. Imagine a tool so sharp, it transforms your coding conventions into a symphony of synchronized tests. Konsist goes beyond standard linting tools; Konsist is your bespoke guardian of tailored code quality.\\r\\n\\r\\nKonsist unparalleled flexibility allows you to customize checks and conventions to fit the unique style of your project, whether it's enterprise-scale, open-source, or the next disruptive tech innovation.\\r\\n\\r\\nJoin us as we explore Konsist's unique features and demonstrate how Konsist can \\r\\nautomate codebase consistency checks like never before. Unlock the potential of uniform coding practices; learn how Konsist can be the cornerstone of maintaining a Konsistent codebase.\",\"speakerIds\":[\"1db23323-e852-4faa-87e3-94d5f05d0b96\",\"1b6696dd-e240-49c2-a383-26d3e8f656d3\"],\"location\":\"Auditorium 12\",\"startsAt\":\"2024-05-23T11:15:00\",\"endsAt\":\"2024-05-23T12:00:00\",\"tags\":[\"Regular Session\",\"Intermediate\",\"Libraries\"]},{\"id\":\"583665\",\"title\":\"Unlocking SQL Databases with Kotlin Data Analytics: A Practical Exploration\",\"description\":\"Throughout the session, I will cover a range of key use cases, demonstrating the versatile capabilities of Kotlin DataFrame for seamless interaction with SQL databases (MariaDB or PostgreSQL, for example).\\r\\n\\r\\nWe will start from the basics of exploring and understanding the structure of SQL databases with Kotlin DataFrame metadata reading methods.\\r\\n\\r\\nAfter that, we will learn how to effortlessly extract data from tables, execute custom SQL queries, or utilize existing ResultSet objects (for JDBC fans) using Kotlin DataFrame, streamlining the data retrieval process.\\r\\n\\r\\nIn the third part, I will demonstrate to you the dynamic generation of classes and schemas on the fly for the tables or results of SQL queries, empowering you to construct flexible data processing pipelines in Kotlin DataFrame with ease.\\r\\n\\r\\nIt's funny to see how your data from an SQL database could be quickly drawn with charts, bar plots, and heat maps. Kandy plotting library will help us better understand the nature of data stored in SQL databases.\\r\\n\\r\\nIn the end, we will see how it is to join together the data from \\r\\nmultiple databases. \\r\\n\\r\\nJoin me on this comprehensive journey where we unravel the intricacies of SQL databases using Kotlin DataFrame, empowering you with the skills to navigate, retrieve, visualize, and process data efficiently.\",\"speakerIds\":[\"8451e1e0-951a-4058-8a22-bb68d2c8f52e\"],\"location\":\"Auditorium 11\",\"startsAt\":\"2024-05-23T11:15:00\",\"endsAt\":\"2024-05-23T12:00:00\",\"tags\":[\"Regular Session\",\"Intermediate\",\"Other\"]},{\"id\":\"614971\",\"title\":\"Custom Fleet Plugins for Your Kotlin Codebase\",\"description\":\"You have a vast codebase in Kotlin and want to compute various metrics about it. What is its cyclomatic complexity? What's the average number of methods per class? How many classes exist in your longest inheritance line? I hope it's fewer than 5… There's a possibility that a specific metric you are interested in isn't implemented in your favorite code analysis tool.\\r\\n\\r\\nLet's address this issue by creating a custom Fleet plugin: Fleet already has some knowledge about your codebase, and we'll ask about it! In this presentation, we will go through the essential steps of Fleet plugin development, starting from creating a plugin template to running Fleet with your new plugin installed. Along the way, we will learn how to consult Fleet data structures and present the results within Fleet itself.\\r\\n\\r\\nThe Fleet SDK supports plugin development across various areas, from simple user interface extensions to Language Server Protocol connections. Although Fleet APIs are still a work in progress, we can already begin exploring them. By the end of this presentation, you can develop your own plugins.\",\"speakerIds\":[\"cb316e0e-8407-472b-bdb6-bfa4291cc3dd\"],\"location\":\"Auditorium 10 (Lightning talks)\",\"startsAt\":\"2024-05-23T11:15:00\",\"endsAt\":\"2024-05-23T11:30:00\",\"tags\":[\"Lightning talk\",\"Intermediate\",\"Other\"]},{\"id\":\"613974\",\"title\":\"Simplifying Build Configuration with Amper\",\"description\":\"Join us for a tour of Amper, a new build and project configuration tool from JetBrains, designed to make Kotlin project tooling approachable for everyone. With its declarative approach, Amper can provide a great user experience and intelligent IDE support for setting up your projects. This lets you spend less time on maintaining your build and focus on what really matters: creating great software.\\r\\n\\r\\nIn this session, you’ll learn how to easily set up Kotlin Multiplatform projects with Amper, see the tooling that’s made possible by declarative configuration, and learn about the latest developments in the project.\",\"speakerIds\":[\"5307510b-c3fa-4f9c-a340-36d198198ef5\"],\"location\":\"Auditorium 10 (Lightning talks)\",\"startsAt\":\"2024-05-23T11:40:00\",\"endsAt\":\"2024-05-23T11:55:00\",\"tags\":[\"Lightning talk\",\"Introductory and overview\",\"Multiplatform\"]},{\"id\":\"616537\",\"title\":\"Virtual Machinations: Leveraging the Linguistic Bytecode of Large Language Models to Emulate Program\",\"description\":\"If AI is the new embodiment of computing, we need to adjust the way we as humans communicate with and instruct AIs to perform desired tasks. However, natural language is inefficient for expressing ideas and instructions precisely. This is why computer scientists create programming languages. All programming languages share the design principles of *abstraction*, naming arbirtrary things, and refering to these things by their names; and *parametrization*, leaving named holes for things that can be filled in by actual things via application.\\r\\n\\r\\nWe will demonstrate the design of a natural language based programming language that is also based the prinples of abstraction and parametrization. Moreover, we will show how we can implement this language by using a large language model as its virtual machine on top of an instruction set implemented in KotlinScript. This approach leverages the LLM's capacity as a general sequence predictor, transforming it into a tool for generating sequences of instructions for our newly designed language.\\r\\n\\r\\nThe correspondence between LLMs and VMs enables the transfer of numerous techniques and insights from the programming language domain to the realm of LLMs. This cross-pollination of concepts opens up new avenues for utilizing LLMs to effectively execute complex computational tasks. By leveraging the strengths of both natural language and programming languages, we can bridge the communication gap between humans and AI systems, paving the way for a future of seamless and intuitive AI interaction.\\r\\n\",\"speakerIds\":[\"8bcbaefb-2d28-49a7-9797-56754de90160\"],\"location\":\"Hall A\",\"startsAt\":\"2024-05-23T13:00:00\",\"endsAt\":\"2024-05-23T13:45:00\",\"tags\":[\"Regular Session\",\"Intermediate\",\"Libraries\"]},{\"id\":\"552805\",\"title\":\"Lifecycles, coroutines and scopes\",\"description\":\"Structured concurrency is one of the key ideas in the Kotlin language, ensuring correct and intuitive cancellation and supervision of jobs. In this talk we look at how these ideas translate when coroutines are introduced in other frameworks with their own lifecycles, like Spring services or Android applications.\\r\\n\\r\\nAnother way to think about this talk is a search for every usage of CoroutineScope in Kotlin libraries, and understand how that bridges the world of coroutines.\\r\\n\\r\\nJobs are not the only lifecycle-aware pattern in Kotlin. The Arrow library provides other two examples: resource management, and distributed transactions. By the end of the talk, you'll be able to see the commonalities, and have a better understanding of all those interfaces ending in Scope.\",\"speakerIds\":[\"6194c065-3bcc-42b5-b1d1-9a25af6b86be\"],\"location\":\"Auditorium 15\",\"startsAt\":\"2024-05-23T13:00:00\",\"endsAt\":\"2024-05-23T13:45:00\",\"tags\":[\"Regular Session\",\"Intermediate\",\"Libraries\"]},{\"id\":\"577491\",\"title\":\"Generating Kotlin SDKs with Smithy\",\"description\":\"As software becomes increasingly distributed and the number of APIs available for consumption grows, the challenge of maintaining synchronization among numerous clients and servers becomes progressively cumbersome. How do clients and servers agree on the API used to communicate with one another? How can the API evolve such that existing clients continue to work without redeploying? How do teams ensure a consistent experience across APIs? Join us for a deep dive into how AWS uses Smithy and code generation to address many of these challenges and how you can do the same.\\r\\n\\r\\nSmithy is an interface definition language (IDL) and set of tools that empowers developers to build clients and servers in multiple languages. It is used to define the APIs for AWS services and generate the AWS SDKs, including the AWS SDK for Kotlin.\\r\\n\\r\\nIn this session you'll see how the Kotlin code generator for Smithy works, what features it provides, and how to leverage it to build Kotlin (multiplatform) SDKs for your own services. No prerequisite knowledge of Smithy required.\",\"speakerIds\":[\"9057aae9-da68-4346-87e2-220d354997bd\",\"9f2b5627-1d42-423f-a6e9-f5e5e356edee\"],\"location\":\"Auditorium 12\",\"startsAt\":\"2024-05-23T13:00:00\",\"endsAt\":\"2024-05-23T13:45:00\",\"tags\":[\"Regular Session\",\"Advanced\",\"Libraries\"]},{\"id\":\"572379\",\"title\":\"Guide to Improving Compose Performance\",\"description\":\"The Compose compiler gives you that ability to know whether composable methods will be skipped during recomposition. The compiler gives you analytics on whether methods are skippable and restartable. In this talk, I’ll do a deep dive on what’s going on under the hood based on how you write your compose code. We’ll explore the consequences of performance when composable parameters are unstable. By the end of this talk, you'll have an understanding of how to better write compose code to get the most performance.\\r\\n\",\"speakerIds\":[\"a79f3682-df5c-40e4-8aa8-1b6eaa7bdeec\"],\"location\":\"Auditorium 11\",\"startsAt\":\"2024-05-23T13:00:00\",\"endsAt\":\"2024-05-23T13:45:00\",\"tags\":[\"Regular Session\",\"Advanced\",\"Mobile\"]},{\"id\":\"587001\",\"title\":\"Uniting Native SDKs into KMP\",\"description\":\"Join us for an in-depth exploration into the process of creating a error monitoring API using Kotlin Multiplatform (KMP). We'll showcase how we use the expect/actual API to seamlessly integrate our native Java and Cocoa SDKs into our SDK.\\r\\n\\r\\nThroughout this session, attendees will be guided through practical design methodologies, emphasizing the aspects that enabled a seamless integration across diverse platforms. We'll provide insights drawn from hands-on experiences, detailing the challenges encountered and the solutions that made our shared error and performance monitoring API a reality. Get ready for code snippets and practical use cases.\\r\\n\\r\\nWhile this session caters to individuals familiar with KMP, it's equally accessible to anyone eager to explore Kotlin Multiplatform (KMP). Our primary goal is to demonstrate the seamless incorporation of existing native SDKs within KMP's framework, enabling a unified SDK across platforms.\\r\\n\\r\\nTo summarize, this session will cover the following:\\r\\n\\r\\n- Integration and challenges with existing native SDKs, emphasizing the efficiency of not requiring complete rewrites\\r\\n- Alternative implementation strategies utilizing `actual typealias`\",\"speakerIds\":[\"0f25b6f3-dbd3-4c7e-ad54-a13414f9b5c2\"],\"location\":\"Auditorium 10 (Lightning talks)\",\"startsAt\":\"2024-05-23T13:00:00\",\"endsAt\":\"2024-05-23T13:15:00\",\"tags\":[\"Lightning talk\",\"Intermediate\",\"Multiplatform\"]},{\"id\":\"657076\",\"title\":\"Mature KMP adoption models for native mobile teams\",\"description\":\"Touchlab’s new maturity model and approach to introducing and scaling KMP, using new tools for integration and deployment.\\r\\n\\r\\nKMP tech for native mobile is mature. Best-practice for teams is not. This lab is for native mobile teams adopting KMP for their non-UI logic and architecture.\\r\\n\\r\\nYou’ll get hands-on experience with Touchlab’s latest professional approach to KMP.\\r\\n\\r\\nWe’ll focus on 3 phases:\\r\\n\\r\\n1. Piloting - low-friction KMP introduction\\r\\n2. Production - monitoring and tuning to ensure success\\r\\n3. Perfecting - scale KMP adoption in a realistic scenario with the “deadline simulator”\\r\\n\\r\\nThere’s a lot to cover. Required reading and prerequisites are posted here: https://touchlab.co/codelabs.\\r\\n\\r\\nQ&A session will follow, time permitting.\\r\\n\",\"speakerIds\":[\"1bdf0b7f-2a71-4d40-a3e1-cb481f328361\",\"b0dd9228-8897-4fa2-b858-f8a3edbb511a\"],\"location\":\"CodeLab\",\"startsAt\":\"2024-05-23T13:00:00\",\"endsAt\":\"2024-05-23T13:45:00\",\"tags\":[\"Intermediate\"]},{\"id\":\"587174\",\"title\":\"The rollercoaster of releasing an Android, iOS, and macOS app with Kotlin Multiplatform\",\"description\":\"With the rise of Kotlin Multiplatform, the possibility of expanding to multiple platforms has increased, especially for Android Developers. It's easier than before to build for other platforms.\\r\\n\\r\\nBut how to release your app to multiple platforms? \\r\\n\\r\\nIn this talk, I will share all the things I've learned around distributing FeedFlow, an Android, iOS, and macOS app built with Kotlin Multiplatform, coming from an Android development background. \\r\\n\\r\\nWe will cover the deployment of the binary, automating everything with CI, crash reporting, logging, internationalization, and all you need to know to successfully distribute your KMP app.\",\"speakerIds\":[\"aeddc24f-0e47-4934-ad76-2de7a9dc9fac\"],\"location\":\"Auditorium 10 (Lightning talks)\",\"startsAt\":\"2024-05-23T13:20:00\",\"endsAt\":\"2024-05-23T13:35:00\",\"tags\":[\"Lightning talk\",\"Intermediate\",\"Multiplatform\"]},{\"id\":\"623652\",\"title\":\"Enabling Kotlin Multiplatform Success: The Android Jetpack Journey\",\"description\":\"Join Android’s Jetpack Team for some exciting new updates and a technical deep dive into the next chapter of our Kotlin Multiplatform journey!\\r\\n\\r\\nIn this talk, we’ll be giving an overview of the state of Kotlin Multiplatform in Jetpack and providing updates on Kotlin Multiplatform-enabled Jetpack libraries. We will also share our process of migrating a well-established Jetpack library - from leveraging Kotlin to its full potential for technical groundwork, to resolving complex dependencies across platforms by extending existing tools or introducing powerful new Multiplatform APIs.\\r\\n\\r\\nJoin us for a behind-the-scenes look at Kotlin Multiplatform in Jetpack & learn how you can apply these techniques to your projects!\",\"speakerIds\":[\"1224bcba-11e0-4f5a-a1b2-c7d533bc42f4\",\"2b198f3a-5df1-4c1f-ba0c-2f3f4f25f1bd\",\"4aff37ce-2304-496a-af9e-965f47fc3e78\"],\"location\":\"Hall A\",\"startsAt\":\"2024-05-23T14:30:00\",\"endsAt\":\"2024-05-23T15:15:00\",\"tags\":[\"Regular Session\",\"Intermediate\",\"Multiplatform\"]},{\"id\":\"587120\",\"title\":\"DataFrame: Kotlin's Innovative Approach to Data Structures\",\"description\":\"We'll talk about Dataframe — a library and a data structure that can help to read, write, generate, transform and organize data for displaying or plotting. It supports not only flat data structures but also hierarchical ones and thus can represent CSV, JSON or even subgraphs of objects in memory. While dataframes are usually mentioned in the context of data analytics, Kotlin Dataframe is also focused on general data cases and perfect for both professional and personal projects.\\r\\nWe'll start with how it all works in Kotlin Notebook — an environment where you can write and execute fragments of code. It’s a good fit for prototyping and trying out ideas. The IDE provides beautiful interactive tables that can display hierarchical data. Also, in the notebooks, the types of dataframe variables are updated after each fragment execution. It means that columns of the dataframe will appear in completion together with their content type.\\r\\nKotlin Dataframe’s new compiler plugin takes this idea even further and infers on-the-fly the types of columns while data wrangling. Come over, and we’ll show it in action and share what Kotlin language features make it possible\",\"speakerIds\":[\"b1a17a8e-db4d-4046-b2e6-34a3608a33f1\"],\"location\":\"Auditorium 15\",\"startsAt\":\"2024-05-23T14:30:00\",\"endsAt\":\"2024-05-23T15:15:00\",\"tags\":[\"Regular Session\",\"Introductory and overview\",\"Libraries\"]},{\"id\":\"575249\",\"title\":\"Pushing the limits of the Server Side UI platform with KMP\",\"description\":\"Over the past five years at Allegro, we have been building the in-house Server Side UI platform MBox. It allows developers to build mobile app screens on the backend, enabling them to implement it once for both Android and iOS. \\r\\n\\r\\nHowever, one critical element was missing, causing hesitation in adopting it on a broader scale: the capability to define logic and construct fully interactive screens. It turned out Kotlin Multiplatform was the solution for our problem!\\r\\n\\r\\nIn this presentation, I will share how we used Kotlin Multiplatform to implement a client-side logic engine, which became an integral part of our Server-Side UI project. You will learn the arguments for using KMP, architecture of the solution and what lessons we learned along the way.\",\"speakerIds\":[\"d3841a2b-b09c-41f7-afa6-26734c05a277\"],\"location\":\"Auditorium 12\",\"startsAt\":\"2024-05-23T14:30:00\",\"endsAt\":\"2024-05-23T15:15:00\",\"tags\":[\"Regular Session\",\"Intermediate\",\"Multiplatform\"]},{\"id\":\"580612\",\"title\":\"The state of code coverage for Kotlin\",\"description\":\"Nowadays it’s not anymore a question whether we want to write tests or not. Writing unit tests is not “nice-to-have” it’s an essential part of our everyday job. While that’s already a great step forward, how can we be sure our tests are actually testing something. To check this we all use code coverage tools.\\r\\n\\r\\nIn this presentation you will learn how code coverage for Kotlin works, which tools we can use and what are the challenges and limitations of various approaches. You will learn the difference between line, instruction and condition coverage and how to read and interpret coverage results in Kotlin.\\r\\n\\r\\nIn the last part of this presentation we will cover the future for Kotlin Code Coverage, what is missing and what can be improved in the future.\",\"speakerIds\":[\"eeb25beb-5d37-4fb7-acac-170357a1d89b\",\"d2ddc9e3-35b6-44a9-8daa-144d89cabaff\"],\"location\":\"Auditorium 11\",\"startsAt\":\"2024-05-23T14:30:00\",\"endsAt\":\"2024-05-23T15:15:00\",\"tags\":[\"Regular Session\",\"Intermediate\",\"Libraries\"]},{\"id\":\"621119\",\"title\":\"‘Context parameters’ from the language design perspective\",\"description\":\"‘Context parameters’ is one of the most anticipated Kotlin features. Last year we unveiled a preliminary version which generated a lot of feedback. The Kotlin team has been working hard since then to finalize its design. The talk will overview the current design status of ‘Context parameters’. We’ll discuss the following topics:\\r\\n- The motivation behind adding ‘Context parameters’;\\r\\n- How it fits into the existing syntax;\\r\\n- Practical examples of how it could be applied.\",\"speakerIds\":[\"7a141668-a505-4cee-bbb4-ea3bd3d4f403\"],\"location\":\"Auditorium 10 (Lightning talks)\",\"startsAt\":\"2024-05-23T14:30:00\",\"endsAt\":\"2024-05-23T14:45:00\",\"tags\":[\"Lightning talk\",\"Introductory and overview\",\"Other\"]},{\"id\":\"585611\",\"title\":\"Kotlin + Power-Assert = ❤️\",\"description\":\"Kotlin 2.0 will ship with a new, experimental, compiler plugin that enables power-assert style diagrams on assert calls. But I hear you asking: What are power-assert diagrams? How do I use this compiler plugin? What about other function calls? Well have I got answers for you!\\r\\n\\r\\nJoin me to see how the power-assert compiler plugin can make your testing easier. How you can enable this plugin on your project and maybe even use your existing assertion library. And even some other ways you can use this plugin outside of tests!\",\"speakerIds\":[\"63733e27-0704-401e-a342-8173a51b83c9\"],\"location\":\"Auditorium 10 (Lightning talks)\",\"startsAt\":\"2024-05-23T14:55:00\",\"endsAt\":\"2024-05-23T15:10:00\",\"tags\":[\"Lightning talk\",\"Introductory and overview\",\"Libraries\"]},{\"id\":\"613830\",\"title\":\"Evolving Compose Multiplatform on iOS and Beyond\",\"description\":\"New flagship features are landing in Compose Multiplatform: common previews, common resources, common lifecycle, common navigation, and further updates for the iOS and target and beyond!\",\"speakerIds\":[\"a82c6942-6e2b-4d80-9883-0b84b932d6ef\"],\"location\":\"Hall A\",\"startsAt\":\"2024-05-23T15:45:00\",\"endsAt\":\"2024-05-23T16:30:00\",\"tags\":[\"Regular Session\",\"Introductory and overview\",\"Multiplatform\"]},{\"id\":\"624953\",\"title\":\"From Zero to Billions: Building a High-Performance Kotlin App in Two Months\",\"description\":\"Join us as we unravel the journey of building a Kotlin app capable of handling billions of events in just two months. Within weeks of our first client using the SDK, we found ourselves analyzing approximately 5 terabytes of data.\\r\\n\\r\\nThe challenge was immense: how to store this vast amount of data without skyrocketing cloud consumption? Which data to retain and which to discard? How to ensure the frontend performance remains unaffected while loading pages?\\r\\n\\r\\nThanks to the flexibility of the Google Cloud Platform, we were able to design an infrastructure that is as reliable as it is scalable. But the work didn't stop there. We had to simultaneously develop new features.\\r\\n\\r\\nIn this presentation, we'll share the technology choices we made that enabled us to deliver quickly. We'll delve into our use of Ktor, Exposed, and Koin for our Kotlin web application development.\\r\\n\\r\\nJoin us to learn how we navigated these (crazy) challenges and successfully delivered a high-performing, data-intensive application.\\r\\n\",\"speakerIds\":[\"66fbb80a-cd18-4ba1-931d-d070d060ab95\"],\"location\":\"Auditorium 15\",\"startsAt\":\"2024-05-23T15:45:00\",\"endsAt\":\"2024-05-23T16:30:00\",\"tags\":[\"Regular Session\",\"Introductory and overview\",\"Server-Side\"]},{\"id\":\"586918\",\"title\":\"Exploring the Exposed Library: A Kotlin Solution to Database Access\",\"description\":\"Exposed is a database access library built with Kotlin that serves as an abstraction layer providing multiple database connectivity options. In addition to reducing the boilerplate code necessary to interface with a database, the library ensures type-safe SQL and reliable interactions as a seamless extension of a Kotlin developer’s code.\\r\\n\\r\\nThis talk ultimately seeks to provide Kotlin developers with a basic understanding of the current state of the Exposed library and its core functionality. We'll introduce the necessary configuration for a database connection, followed by an insight into the concept of transactions and their managers. We'll then examine schema definition, which will lead into an exploration of the different approaches for defining and manipulating relational data: the domain-specific language approach, the data access object pattern, and using plain SQL.\\r\\n\\r\\nLastly, to give perspective on the extended capabilities of Exposed, we’ll lightly touch on topics geared towards enabling a tailored developer experience, such as: user-defined column types and functions; custom extensions for controlled SQL query building; and statement lifecycle interceptors.\",\"speakerIds\":[\"aa4f4219-1d5a-4d23-bcb3-42284ff37fb0\"],\"location\":\"Auditorium 12\",\"startsAt\":\"2024-05-23T15:45:00\",\"endsAt\":\"2024-05-23T16:30:00\",\"tags\":[\"Regular Session\",\"Introductory and overview\",\"Libraries\"]},{\"id\":\"587019\",\"title\":\"Compose beyond the UI: Molecule at Swedish Railways\",\"description\":\"With the advent of Jetpack Compose UI, it has become easier than ever to create elegant, dynamic user interfaces for our applications. However, Jetpack Compose's capabilities extend beyond UI creation. This talk aims to show how you can harness the power of Jetpack Compose for other parts of your applications using a framework called Molecule. Molecule is a framework that lets you build Flow streams using Jetpack Compose. This may not sound like much but it opens up a whole new frontier for using Jetpack Compose. \\r\\n\\r\\nIn this talk we will explore our learnings of using Molecule in a major refactoring of the Swedish Railways (SJ) app during the past year.\\r\\n\\r\\nWe will start off with an introduction to molecule and then move on to exploring how we can leverage Jetpack Compose and Molecule in our presentation layers. This part will show how to combine multiple reactive streams in a manner that is more maintainable and easier to test than the common flow combine function. We will also explore using LaunchedEffect for side effects and periodic updates using real world scenarios. We will end this section by discussing gotchas related to handling hot flows.\\r\\n\\r\\nNext, we will push the boundaries and test the limits of Molecule by trying to rewrite a repository. Can you represent a network request by a composable? How would you handle errors and retries? How do you share data between Molecule flows? This talk will be concluded by discussing some architectural pitfalls we stumbled upon during our adventures.\",\"speakerIds\":[\"e0d9f3b5-55c9-48ae-aef4-84786b04e329\"],\"location\":\"Auditorium 11\",\"startsAt\":\"2024-05-23T15:45:00\",\"endsAt\":\"2024-05-23T16:30:00\",\"tags\":[\"Regular Session\",\"Intermediate\",\"Mobile\"]},{\"id\":\"614934\",\"title\":\"It's Compose O'Clock, draw on my watch!\",\"description\":\"Compose Canvas APIs are a simple and powerful foundation to draw and animate nice things. If you didn't try those yet, you might be missing out!\\r\\n\\r\\nAlso, now, with Compose O'Clock, we can render to a watch face on any smartwatch running Wear OS.\\r\\n\\r\\nIn this talk, you'll see short snippets to draw the time in many different, and, hopefully beautiful ways, using simple and short building blocks from Compose Canvas, or built on top of it.\\r\\n\\r\\nHopefully, it inspires you to draw nice things you didn't know you could, whatever your target platform is, thanks to Compose now being Multiplatform!\",\"speakerIds\":[\"7c1cede6-5f59-46bb-ad1e-22b63758dae7\"],\"location\":\"Auditorium 10 (Lightning talks)\",\"startsAt\":\"2024-05-23T15:45:00\",\"endsAt\":\"2024-05-23T16:00:00\",\"tags\":[\"Lightning talk\",\"Introductory and overview\",\"Other\"]},{\"id\":\"657080\",\"title\":\"Close the Platform Gap With the “Bad Swift Simulation”\",\"description\":\"Most Kotlin devs don’t really “know” Swift, they know about it. The Kotlin compiler will export any Kotlin to Swift, but the “magic” is lost along the way.\\r\\n\\r\\nGood KMP requires understanding bad KMP.\\r\\n\\r\\nExperience Touchlab’s “Bad Swift Simulation”: Kotlin calling Kotlin through a Swift-like lens. Then learn what to do about it.\\r\\n\\r\\nIn this lab we will:\\r\\n\\r\\n- Feel their Pain - Bad Swift is meaningless if you’re not a Swift expert, but bad Kotlin is a different story. See bad KMP with the “BSS”\\r\\n\\r\\n- Fix it - using Kotlin best-practice, SKIE and other tools.\\r\\n\\r\\n- Incrementally - SKIE changes types. Incremental application is key for existing code.\\r\\n\\r\\nFollow up this lab with Pamela Hill’s talk “KMP Alchemy” on KMP/Swift interop.\\r\\n\\r\\nRequired reading and prerequisites are posted here: https://touchlab.co/codelabs.\",\"speakerIds\":[\"969813cd-0231-4310-9c61-745967bd94c5\",\"b2bfc2d3-c516-4479-9b56-85634606fb99\"],\"location\":\"CodeLab\",\"startsAt\":\"2024-05-23T15:45:00\",\"endsAt\":\"2024-05-23T16:30:00\",\"tags\":[\"Intermediate\"]},{\"id\":\"585280\",\"title\":\"Hacking Sony Cameras for Fun and Profit\",\"description\":\"Great hardware needs amazing software. Sony makes some of the best Mirrorless cameras, but some of the software is less than ideal.\\r\\n\\r\\nIn this talk, we will explore the world of Bluetooth LE with Kotlin Multiplatform. We will write an amazing Remote Camera app from start to finish that works on both desktop and mobile platforms after having reverse-engineered the undocumented BLE protocol used by modern Sony cameras.\\r\\n\\r\\nAdditionally, we will look at using Sony's Remote Camera SDK for some advanced features. Spolier alert; its a C SDK so there will be some cinterop fun involved.\",\"speakerIds\":[\"9caa9624-350a-4e69-8ac4-88db14bdb5bf\"],\"location\":\"Auditorium 10 (Lightning talks)\",\"startsAt\":\"2024-05-23T16:15:00\",\"endsAt\":\"2024-05-23T16:30:00\",\"tags\":[\"Lightning talk\",\"Intermediate\",\"Multiplatform\"]},{\"id\":\"581244\",\"title\":\"Grow with the Flow: How Kotlin Flow Became a Game-Changer for our Business\",\"description\":\"Kotlin’s Flow is a powerful abstraction with unprecedented potential that revolutionized data exchange of my client in the telecom industry.\\r\\n\\r\\nThis talk will explore this success story with Kotlin Flow as the main actor that powered a groundbreaking streaming application using server-sent events. This application had a disruptive impact both in B2B interactions and internally.\\r\\n\\r\\nStarting with a crisp and understandable exploration of Kotlin Flow and its brothers StateFlow and SharedFlow, we will live-code the essentials of the game-changing solution step by step. Along the way, we will show off all the crucial capabilities of the Flow family on stage, revealing how all aspects enable you to build a cutting-edge, mission-critical streaming application. \\r\\n\\r\\nFinally, discover how Flow not only facilitated the development of a game-changing streaming API but also became the cornerstone of our Event-Driven Architecture. This shift allowed us to bypass traditional messaging solutions like Kafka entirely, simplifying our infrastructure and significantly reducing operational overhead.\\r\\n\\r\\nAfter this session, you will have tasted the transformative power of Kotlin's Flow and how to leverage it to your benefit so that you, too, can 'Grow with the Flow'!\\r\\n\",\"speakerIds\":[\"7df2c791-134f-4279-bb68-23f8899bb1ac\"],\"location\":\"Hall A\",\"startsAt\":\"2024-05-23T16:45:00\",\"endsAt\":\"2024-05-23T17:30:00\",\"tags\":[\"Regular Session\",\"Intermediate\",\"Server-Side\"]},{\"id\":\"575677\",\"title\":\"Kotlin's Elegant Deceptions: Simple APIs, Unusual Tactics\",\"description\":\"What untapped potential lies within Kotlin for creating APIs that are not just functional, but artfully elegant? Dive into the exploration of Kotlin's innovative methods, beyond conventional usage. Discover the language's blend of elegance and advanced features can enrich and elevate your approach to API development, moving beyond the ordinary towards the extraordinary.\\r\\n\\r\\nIn this talk, we're going to dive into how you can use Kotlin's thoughtful language features to build APIs that are not just good, but great. We'll cover the theory behind each technique and showcase it's use by diving behind the scenes in some established open source projects.\\r\\n\\r\\nAttendees will gain practical techniques from this session, ready to be applied in their Kotlin projects for immediate impact. The insights into little-known features for API design will empower them to enhance their development work, fostering elegance and efficiency in their APIs from the outset.\\r\\n\\r\\nGet ready to challenge your usual way of doing things and unlock some seriously innovative programming tricks!\",\"speakerIds\":[\"b3f34b70-b68f-4325-8ffe-b599217e1f4c\"],\"location\":\"Auditorium 15\",\"startsAt\":\"2024-05-23T16:45:00\",\"endsAt\":\"2024-05-23T17:30:00\",\"tags\":[\"Regular Session\",\"Intermediate\",\"Libraries\"]},{\"id\":\"587178\",\"title\":\"Kotlin/Wasm: Present and Future\",\"description\":\"Kotlin is a modern statically typed programming language developed by JetBrains, designed to be used across different platforms.\\r\\nWebAssembly a portable binary format, designed to be fast and safe, enables running high-performance code in various environments.\\r\\n\\r\\nCombining the two technologies, Kotlin/Wasm allows developers to write efficient and portable code that can be executed in any Wasm-enabled environment and build from high-performance web applications to serverless functions.\\r\\n\\r\\nIn this talk, we’ll have a look at the most recent developments in Kotlin/Wasm: tools, compiler, and the ecosystem around it.\\r\\nWe will showcase practical examples, demonstrating how Kotlin/Wasm could be used inside and outside of browsers.\\r\\nLooking ahead, we will see the future prospects of Kotlin & WebAssembly.\\r\\nCome and learn what's new and exciting!\",\"speakerIds\":[\"12a549cb-145e-4d13-8bb3-ccfe162200a3\"],\"location\":\"Auditorium 12\",\"startsAt\":\"2024-05-23T16:45:00\",\"endsAt\":\"2024-05-23T17:30:00\",\"tags\":[\"Regular Session\",\"Introductory and overview\",\"Multiplatform\"]},{\"id\":\"577200\",\"title\":\"Kotlin Multiplatform Alchemy: Making Gold out of Your Swift Interop\",\"description\":\"Now that Kotlin Multiplatform has reached Stable, the technology is ready to be adopted and deployed into production. However, one aspect frequently causes irritation in the mobile use case: Kotlin/Swift interoperability. This issue often leads to compromise on one or both sides, with solutions that are not idiomatic in either language. So how can this be mitigated, if not completely resolved?\\r\\n\\r\\nIn this talk, I will focus on the current state of Kotlin/Swift interoperability and the limitations you can expect to encounter when developing your Kotlin Multiplatform apps. I will share tips and tricks on making Kotlin Multiplatform APIs that will make your team's integration code shine. I will also explain JetBrains' exciting plans for improving Kotlin/Swift interoperability.\\r\\n\\r\\nJoin the session to discover how to turn your interop difficulties into Multiplatform gold!\",\"speakerIds\":[\"62216efe-dd8b-4d8b-9800-1d51b57c4001\"],\"location\":\"Auditorium 11\",\"startsAt\":\"2024-05-23T16:45:00\",\"endsAt\":\"2024-05-23T17:30:00\",\"tags\":[\"Regular Session\",\"Intermediate\",\"Multiplatform\"]},{\"id\":\"583997\",\"title\":\"Refactoring to Expressive Kotlin\",\"description\":\"Kotlin was built from the beginning as an expressive language, but we still scratch our heads when reading some code, especially if it is trying to do something complicated.\\r\\n\\r\\nJoin Duncan and Dmitry as they examine code examples and use the power of the Kotlin language and IntelliJ to refactor them into code that reads as it works. We’ll learn how to express intent with the scope functions: let, run, with, apply, and also. We’ll see how defining our own extension functions allows code to flow, and move on to more advanced topics like separating pure from impure functions, cohesion, tiny types and domain specific languages.\",\"speakerIds\":[\"c471c1b0-53d7-45cf-a12c-340714972d83\",\"9aa1160b-ce4f-4992-a1ad-b6da7d62c033\"],\"location\":\"Hall A\",\"startsAt\":\"2024-05-23T17:45:00\",\"endsAt\":\"2024-05-23T18:30:00\",\"tags\":[\"Regular Session\",\"Intermediate\",\"Other\"]},{\"id\":\"587118\",\"title\":\"Tools & Techniques for Java to Kotlin Migrations\",\"description\":\"Large organizations including Google, Uber, and Meta have volumes of legacy Java code that'd ideally be migrated to Kotlin so their developers can be more productive and ultimately get to more reliable apps and servers. In this panel we will hear why these organizations want to migrate to Kotlin, the approaches they've taken, and the tools they've developed.\",\"speakerIds\":[\"6a3de662-ef86-4c62-bb68-2f7ebe607f76\",\"c53e7302-d53c-4c56-ae42-693a74de8ba6\",\"6cf514a7-0d9a-4e66-944b-672e39700c63\",\"5c84d73d-1b13-4383-a7ec-e7ce3151794e\",\"2945cb69-3e28-4cae-9fd8-c01ce9f10869\"],\"location\":\"Auditorium 15\",\"startsAt\":\"2024-05-23T17:45:00\",\"endsAt\":\"2024-05-23T18:30:00\",\"tags\":[\"Regular Session\",\"Introductory and overview\",\"Mobile\"]},{\"id\":\"587119\",\"title\":\"Making the Big Kotlin Multiplatform Decision\",\"description\":\"Why is adopting Kotlin Multiplatform Mobile not an easy decision to make? After all, it can potentially save a business millions of dollars by cutting down duplicate iOS and Android code and saving many developer hours. \\r\\n\\r\\nBut when you have large, complicated codebases and investment in a mobile organization with specific skill sets, it can be an expensive decision to put time and resources into shifting into KMM instead. It can be a hard decision to reverse, and a risky call to make. But it doesn't have to be!\\r\\n\\r\\nIn this talk I’ll lay out a decision-making framework to approach KMM adoption - not just from an engineering perspective, but a leadership one too. We’ll reference case studies and talk about: \\r\\n\\r\\n* Evaluating KMM for different kinds of projects - standard mobile codebases as well as those in custom frameworks like RIBS and Workflow\\r\\n* The important factors - build support for Android vs iOS, resourcing KMM expertise, and flexibility, all of which impact long-term risks and outcomes\\r\\n* Evaluating cultural support - what kind of teams and organizations are best set up for KMM success? \\r\\n* Finding the right engineering levers to make adoption more successful\\r\\n \\r\\nAt Square, I’ve had to make that call for my team, and I’ve worked with other teams that faced similar decisions. I’ll reference real learnings as we discuss wisely and successfully steering a team into new Kotlin waters. \\r\\n\",\"speakerIds\":[\"265b1a56-e32c-459d-8580-6d0d4ed5fc63\"],\"location\":\"Auditorium 12\",\"startsAt\":\"2024-05-23T17:45:00\",\"endsAt\":\"2024-05-23T18:30:00\",\"tags\":[\"Regular Session\",\"Intermediate\",\"Mobile\"]},{\"id\":\"576195\",\"title\":\"Using C & native platforms in Kotlin : Building a multi-platform advanced library\",\"description\":\"Kotlin/Multiplatform is an amazing tech which allows you to develop your business code once and deploy it to every mobile platform. However, to do things, you need to access APIs that are either provided by the platform in its native language (Obj-C, Swift) or as native libraries (C, C++, Rust).\\r\\nIn this live coding talk, we will see how to use different types of APIs in a Kotlin Multi-platform library that can be used on Kotlin/Multiplatform. Using Cryptography primitives as an excuse, we will see how to configure, compile, test and deploy a simple algorithmic library, and how to use it in a Kotlin/Multiplatform Mobile (KMM) project.\\r\\nWe will first demonstrate how to create a library with a native C dependency for the JVM, Android, Kotlin/Native & iOS, the Web, and more specifically to align JVM JNI, Kotlin/Native C-interop and JS WebAssembly.\\r\\nFinally, we will explore how to use Swift iOS SDKs in conjunction with Kotlin Android SDKs to commonize advanced platform features, such as embedded cryptography.\\r\\n\",\"speakerIds\":[\"24586433-c018-4271-bf89-43bae78dfa77\"],\"location\":\"Auditorium 11\",\"startsAt\":\"2024-05-23T17:45:00\",\"endsAt\":\"2024-05-23T18:30:00\",\"tags\":[\"Regular Session\",\"Advanced\",\"Multiplatform\"]},{\"id\":\"617143\",\"title\":\"The best programmer I know\",\"description\":\"I believe great programmers are not born, they are made. Or rather, they make themselves, carefully and deliberately over time. I am not talking about the folks who rote-learn the l33t answers and throw their egos around; I mean the ones who build great products using simple, understandable code, while lifting up those around them.\\r\\n\\r\\nI have worked with some great programmers over the years, and met some others along the way. I want to tell you about the best programmer I know. To start with, they have “an insatiable curiosity and the belief they can convince a computer to do anything. Plus a healthy disregard for language and tool zealotry.”\\r\\n\\r\\nYou might recognise some of their traits in yourself; you might decide you want to aspire to some of them; you might choose to refer to them as an interviewer, or as a candidate. My hope is simply that you find this useful and in some way inspiring.\",\"speakerIds\":[\"d06cbb07-240c-4dd9-9c3d-4fd585e084fd\"],\"location\":\"Hall A\",\"startsAt\":\"2024-05-24T09:00:00\",\"endsAt\":\"2024-05-24T10:00:00\",\"tags\":[\"Regular Session\",\"Introductory and overview\",\"Other\"]},{\"id\":\"580409\",\"title\":\"Compose UI for... a light switch?\",\"description\":\"It runs on Android, iOS, desktop, and the web, but in this talk we'll cover how to get Compose UI running on a smart light switch built on embedded Linux.\\r\\n\\r\\nFollow along as we journey through the process of discovering the device backdoor, figuring out how to run custom software, standing up Kotlin and Compose UI for embedded Linux, and finally building our own UI for the switch. We'll cover the intended use case of this effort, as well as other potential uses of this technology. Finally, the actual switch will be in the building for a live demo.\",\"speakerIds\":[\"3eabdd46-6cb5-4083-9eb8-1ad9a3b7a5eb\"],\"location\":\"Hall A\",\"startsAt\":\"2024-05-24T10:15:00\",\"endsAt\":\"2024-05-24T11:00:00\",\"tags\":[\"Regular Session\",\"Intermediate\",\"Multiplatform\"]},{\"id\":\"570564\",\"title\":\"Turbocharge Your Data: Harnessing Kotlin and gRPC to Handle Real-Time Data From Connected Cars\",\"description\":\"In the era of connected cars, real-time data streaming is the key to innovation, safety, and convenience. This talk at KotlinConf will explore leveraging the combination of Kotlin and gRPC to simplify the handling of real-time streaming data from connected cars.\\r\\nOur presentation will dive into the main challenges and complexities of managing real-time data from connected cars, and we will showcase the elegant solutions that Kotlin and gRPC offer. We will walk you through the fundamentals of gRPC, highlighting its suitability for efficient communication between cars, the cloud, and the mobile app. You'll learn how to use Kotlin to build robust and maintainable applications for handling real-time data.\\r\\nKey Takeaways:\\r\\n1. Kotlin's Power: Discover how Kotlin, coupled with gRPC, makes it an ideal choice for developing reliable applications tailored for real-time data streams.\\r\\n2. gRPC for Efficient Communication: Learn how gRPC, a high-performance and language-agnostic framework for building remote APIs, simplifies the process of communicating between connected cars, mobile applications, and backend servers.\\r\\n3. Real-World Use Cases: Explore real-world use cases where Kotlin and gRPC have transformed the handling of streaming real-time data at Volvo Cars, elevating user experiences and unlocking new opportunities.\\r\\n4. Best Practices: Gain insights into best practices and design patterns for building efficient, scalable, and secure real-time streaming applications.\\r\\nBy the end of this session, you'll have a good grasp of the combined power of Kotlin and gRPC for effective real-time data management. You'll be equipped with knowledge and tools to kickstart your own projects and onboard your backend teams.\\r\\nJoin us at KotlinConf and gain valuable insights into implementing Kotlin and gRPC in your apps. Take the opportunity to steer your projects and career towards an exciting future!\",\"speakerIds\":[\"8707cb07-3a1b-4806-8787-6f5e56f1bd60\",\"feb160de-17c4-4b74-9919-bae886909898\"],\"location\":\"Auditorium 15\",\"startsAt\":\"2024-05-24T10:15:00\",\"endsAt\":\"2024-05-24T11:00:00\",\"tags\":[\"Regular Session\",\"Advanced\",\"Mobile\"]},{\"id\":\"584014\",\"title\":\"Developer-first Gradle builds\",\"description\":\"In the ever-evolving landscape of software development, the efficiency of build systems plays a pivotal role in project success. Part of our vision for Gradle is to deliver an elegant and extensible declarative build language that allows developers to describe any kind of software in a clear and understandable way. Our current effort is described in https://blog.gradle.org/declarative-gradle.\\r\\n\\r\\nThis session delves into the challenges faced by developers when understanding and maintaining complex build scripts and demonstrates an innovative approach that harnesses the expressiveness of Kotlin while imposing restrictions to enhance clarity and maintainability. Attendees will gain insights into the rationale behind adopting a declarative paradigm for build definition and the benefits it brings to project workflows.\\r\\n\\r\\nKey topics covered include:\\r\\n\\r\\nDeclarative Build Principles: Understand the advantages of a declarative build language and its impact on project maintainability, readability, and collaboration.\\r\\n\\r\\nExpressive DSL: Explore the capabilities of the DSL and how it serves as a powerful tool for expressing build configuration concisely.\\r\\n\\r\\nImpact on projects: Explore case studies of projects that use a declarative build language, showcasing improvements in build performance, understanding, and maintenance.\\r\\n\\r\\nBy attending this session, software developers and build engineers will leave with practical insights and knowledge about crafting a more maintainable, expressive, and declarative Gradle build definition. \\r\\n\",\"speakerIds\":[\"f296664b-274f-4e11-90a4-b632afab99cc\",\"ebc612d5-a764-46b6-8524-0adb9638dd5c\"],\"location\":\"Auditorium 12\",\"startsAt\":\"2024-05-24T10:15:00\",\"endsAt\":\"2024-05-24T11:00:00\",\"tags\":[\"Regular Session\",\"Introductory and overview\",\"Other\"]},{\"id\":\"582224\",\"title\":\"KMP libraries evolution: format and publication model\",\"description\":\"In 2023, we released a stable version of KMP, but are not stopping there. We continue to evolve Kotlin as a technology for multiplatform development.\\r\\n\\r\\nThe core part of this technology is klib’s – a special binary format for KMP libraries.\\r\\nWe will start with an overview of the current state of klib’s, including:\\r\\n- how they are published to Maven Central\\r\\n- The klib format itself: what is inside\\r\\n\\r\\nAfter that, we will discuss the future of KMP libraries:\\r\\n- ongoing changes in the inline function semantic\\r\\n- change in the KMP format and publication\\r\\n- and finally, discuss compatibility and migration\\r\\n\",\"speakerIds\":[\"7ad82c43-738a-4d09-9032-2fafb26f6858\"],\"location\":\"Auditorium 11\",\"startsAt\":\"2024-05-24T10:15:00\",\"endsAt\":\"2024-05-24T11:00:00\",\"tags\":[\"Regular Session\",\"Advanced\",\"Libraries\"]},{\"id\":\"586541\",\"title\":\"Going fast with Kotlin\",\"description\":\"Kotlin is leaning on JVM a lot, making most Java features accessible and easy to use. Sometimes, however, this results in curiously unexpected results during execution if you are trying to optimise your library and squeeze every last ounce of performance.\\r\\n\\r\\nAndrei spent last year optimising performance of Compose on Android. Written fully in Kotlin, it relies on performance-oriented features of the language to optimize the runtime as much as possible. This talk shares some interesting gotchas about Kotlin performance and guardrails that Compose team have setup for themselves to ensure it keeps going fast.\",\"speakerIds\":[\"1e19e15d-18c9-4cd9-82b2-280120a8c8a6\"],\"location\":\"Auditorium 10 (Lightning talks)\",\"startsAt\":\"2024-05-24T10:15:00\",\"endsAt\":\"2024-05-24T10:30:00\",\"tags\":[\"Lightning talk\",\"Intermediate\",\"Libraries\"]},{\"id\":\"581520\",\"title\":\"Kotlin Multiplatform in Google Workspace\",\"description\":\"Google Workspace has been working on a large migration from a Java-oriented multiplatform foundation to Kotlin Multiplatform. The primary drivers for this migration are to take better advantage of Kotlin, its ecosystem, and the capabilities of Kotlin Multiplatform (e.g. native interop & runtime performance). This session will share the current state of the migration and lessons learned.\",\"speakerIds\":[\"4f541219-75cb-4e12-a1e9-4d9382652d0d\"],\"location\":\"Auditorium 10 (Lightning talks)\",\"startsAt\":\"2024-05-24T10:40:00\",\"endsAt\":\"2024-05-24T10:55:00\",\"tags\":[\"Lightning talk\",\"Intermediate\",\"Multiplatform\"]},{\"id\":\"671939\",\"title\":\"AI and Kotlin: A Perfect Mix\",\"description\":\"Dive into the latest advancements in AI coding assistance and see how JetBrains AI is changing the Kotlin programming in your IDE.\\r\\n\\r\\nIs OpenAI “all you need” today or does custom Language Models offer superior quality? What really drives effective code generation: the context window or the size of the model? And is there more to AI coding assistance than just generating code?\\r\\n\\r\\nWe'll navigate through the fundamental concepts of Machine Learning, explore relevant cloud concepts, and a lot of Kotlin to discover the answers together.\",\"speakerIds\":[\"7bbb257c-a5db-4e6f-8769-03dd0a7fe522\"],\"location\":\"Hall A\",\"startsAt\":\"2024-05-24T11:15:00\",\"endsAt\":\"2024-05-24T12:00:00\",\"tags\":[\"Regular Session\",\"Introductory and overview\",\"Other\"]},{\"id\":\"558194\",\"title\":\"Have your Serverless Kotlin Functions and Eat Them Too\",\"description\":\"It’s a sad reality that JVM functions have poor cold-start performance on serverless platforms, like AWS Lambda. You may have been tempted to compile your jar to a native image, or to pay extra to keep your functions warm. You may have decided that serverless is only suited to asynchronous tasks without latency requirements. But it doesn’t have to be this way.\\r\\n\\r\\nYou can have your Kotlin Functions and you can eat them too. You can run an entire API service; but only if you design it right. In this talk, I’m going to teach you how to minimize your function’s init phase, abandon your heavyweight dependencies, and even eliminate the need for reflection. When we’re done, you won’t have to settle for other languages.\",\"speakerIds\":[\"9f10694b-6552-4023-bc47-41a8daed6896\"],\"location\":\"Auditorium 15\",\"startsAt\":\"2024-05-24T11:15:00\",\"endsAt\":\"2024-05-24T12:00:00\",\"tags\":[\"Regular Session\",\"Intermediate\",\"Server-Side\"]},{\"id\":\"548456\",\"title\":\"A walk in the Lindenmayer fractal forests with a Kotlin notebook\",\"description\":\"Some pieces of Kotlin code are better discovered through exploration. Code for a Lindenmayer system (Lsystem) is an example of this. These systems can generate beautiful organic looking fractal structures. A few small tweaks cause unexpected variety: perfect for experimentation. Kotlin Notebooks are especially suited for experimental and exploratory coding.\\r\\n\\r\\nThis talk will showcase the use of Kotlin Notebooks to draw a series of Lsystem trees. It will be a live code session in IntelliJ with a shareable Kotlin Notebook as a result.\\r\\n\\r\\nYou do not need to be a data scientist to enjoy this talk.\\r\\n\\r\\nThe audience will:\\r\\n\\r\\n- See Kotlin Notebooks in action with the focus on reusable canvas drawing\\r\\n- See an iterative coding workflow that explores code and visuals\\r\\n- Learn about Lindenmayer systems\\r\\n- Receive a link to the talk Notebook which they can copy and modify to continue the experiments in their own time\",\"speakerIds\":[\"2313d8eb-7d6e-444d-8e8d-4d223f896ce8\"],\"location\":\"Auditorium 12\",\"startsAt\":\"2024-05-24T11:15:00\",\"endsAt\":\"2024-05-24T12:00:00\",\"tags\":[\"Regular Session\",\"Intermediate\",\"Other\"]},{\"id\":\"542869\",\"title\":\"Debugging the Future: Exploring Coroutine Debugger Tools\",\"description\":\"Coroutines is a shining feature of the Kotlin language, however when having hundreds of them running, debugging becomes a challenging task! In this talk, we will take a deep dive into the core of coroutine debugging, debunking its internals and reviewing available tools.\\r\\n\\r\\nDuring the first part of the talk I will give the overview of the coroutine debugging tooling available in Intellij IDEA and how to use it: \\r\\n1. Asynchronous stack traces \\r\\n2. How the debugger handles stepping inside coroutines, where after pressing the 'step over' button you may wake up in a different world.\\r\\n3. Coroutine Panel\\r\\n4. Stack trace recovery (https://github.com/Kotlin/kotlinx.coroutines/blob/master/docs/topics/debugging.md#stacktrace-recovery)\\r\\n5. The \\\"-Xdebug\\\" kotlin compiler flag that allows users to view variables that would normally be optimised. \\r\\nWhile presenting the tooling, I will also uncover the machinery behind it. \\r\\n\\r\\nThe second part of the talk will cover the tooling for coroutine debugging developed by the community:\\r\\n1. Stack Trace Decoroutinator (https://github.com/Anamorphosee/stacktrace-decoroutinator)\\r\\n2. Coroutine Stacks\\r\\n(https://github.com/nikita-nazarov/coroutine-stacks)\\r\\nI will give an overview of how to use it, which problems it covers and how it is different from what exists in Intellij.\",\"speakerIds\":[\"1d007157-b8e7-439b-9c88-6db97e0505d3\"],\"location\":\"Auditorium 11\",\"startsAt\":\"2024-05-24T11:15:00\",\"endsAt\":\"2024-05-24T12:00:00\",\"tags\":[\"Regular Session\",\"Intermediate\",\"Other\"]},{\"id\":\"625045\",\"title\":\"Android, Compose, Multiplatform & Server - Inject them all with Koin\",\"description\":\"Whether you're crafting a modern Android app with Jetpack Compose, extending your codebase across iOS and desktop environments through Kotlin Multiplatform, or even orchestrating layers of components on server side with Ktor, Koin emerges as the central integration platform.\\r\\n\\r\\nJoin me for this session through the wide Kotlin landscape and see how Koin, the well-known Kotlin dependency injection open-source framework, seamlessly integrates across the entire ecosystem.\\r\\n\\r\\nWe'll discover upcoming features of Koin 4.0. Get ready for a great journey into the present and future of Kotlin development with Koin!\",\"speakerIds\":[\"66fbb80a-cd18-4ba1-931d-d070d060ab95\"],\"location\":\"Auditorium 10 (Lightning talks)\",\"startsAt\":\"2024-05-24T11:15:00\",\"endsAt\":\"2024-05-24T11:30:00\",\"tags\":[\"Lightning talk\",\"Introductory and overview\",\"Libraries\"]},{\"id\":\"586412\",\"title\":\"Why we can't have nice things\",\"description\":\"Have you ever wondered what challenges Kotlin standard libraries encounter? How is the new API affected by insect collection in 1800s and trade routes with Australia? What twitter polls have to do with Kotlin compiler not working in Turkey? Or maybe how the missing alarm makes us add a new parameter to a function?\\r\\n\\r\\nIn my talk, I'll answer these questions and briefly cover some unusual problems we tackle on a regular basis in Kotlin Libraries.\",\"speakerIds\":[\"b2a19517-6d18-4ec1-9c40-7e29f4d862b1\"],\"location\":\"Auditorium 10 (Lightning talks)\",\"startsAt\":\"2024-05-24T11:40:00\",\"endsAt\":\"2024-05-24T11:55:00\",\"tags\":[\"Lightning talk\",\"Introductory and overview\",\"Libraries\"]},{\"id\":\"587199\",\"title\":\"Write your own Kotlin lint checks!\",\"description\":\"Android Lint is a static analysis tool which supports analyzing Kotlin code, Java code, and soon, KMP. \\r\\n\\r\\nWith 500 built-in checks, it ships with Android Studio and runs in the code editor and as part of the build system and is therefore used by millions of developers. But it's not only used to analyze Android apps and the Android platform; despite the name, it's not actually Android specific -- it's also used to analyze *all* server Kotlin and Java code inside of Google!\\r\\n\\r\\nIn this talk, Tor Norbye will cover the basic features of Android Lint and then show how you can easily extend lint by writing your own checks.\",\"speakerIds\":[\"d4d861f4-0319-49d3-8ca1-7778cd2fb6dc\"],\"location\":\"Hall A\",\"startsAt\":\"2024-05-24T13:00:00\",\"endsAt\":\"2024-05-24T13:45:00\",\"tags\":[\"Regular Session\",\"Advanced\",\"Other\"]},{\"id\":\"571571\",\"title\":\"Channels in Kotlin Coroutines\",\"description\":\"Have you ever wondered how channels in Kotlin coroutines work under the hood? Recently, we redesigned their implementation, significantly improving performance and memory footprint. This talk will introduce the high-level design of the underlying algorithms. You will learn the semantics of rendezvous and buffered channels, how they are implemented, and what influenced this implementation.\",\"speakerIds\":[\"ffcac92c-d9e9-48e9-8de0-4e4e684c58e2\"],\"location\":\"Auditorium 15\",\"startsAt\":\"2024-05-24T13:00:00\",\"endsAt\":\"2024-05-24T13:45:00\",\"tags\":[\"Regular Session\",\"Advanced\",\"Other\"]},{\"id\":\"584974\",\"title\":\"Microservices with Restate and Kotlin\",\"description\":\"Developing applications in a microservice architecture is hard. For all the benefits that it brings over monolithic application architectures, they expose developers to all sorts of tough distributed systems problems, making it non-trivial to build applications that are consistent, scalable, and resilient. Wouldn't it be great if you could stop worrying about all possible failure scenarios and race conditions such as charging customers twice, users withdrawing more cash than they have, and selling a single ticket multiple times?\\r\\n\\r\\nIn this session, we share ideas from the open source system we are developing, called 'Restate'. Our work is inspired by event-sourcing and stream processing systems, but rethought from the ground up for microservices and workflows. Restate connects services with each other and with other systems, provides durable execution, and manages crucial aspects like reliable messaging, durable timers, failover and consistent state. Moreover, Restate is designed to work out of the box with existing serverless deployment platforms.\\r\\n\\r\\nJoin us for a live demo of a real-world application powered by Restate and Kotlin coroutines and see how patterns that are hard to get right are streamlined into a few lines of code.\",\"speakerIds\":[\"eb6d6054-e6f7-40ff-b5d1-a1863c70d841\",\"29714cd6-635b-4d48-b373-e7b27689b965\"],\"location\":\"Auditorium 12\",\"startsAt\":\"2024-05-24T13:00:00\",\"endsAt\":\"2024-05-24T13:45:00\",\"tags\":[\"Regular Session\",\"Introductory and overview\",\"Server-Side\"]},{\"id\":\"578918\",\"title\":\"Compose Multiplatform: performance on iOS\",\"description\":\"One of the main goals of Compose Multiplatform for iOS is providing absolutely smooth performance, even on high-refresh-rate-displays. \\r\\n\\r\\nIn this talk we deep dive into details what challenges Compose Multiplatform team has faced to achieve the goal. The session will contain real-world cases where we saw frame-drops and how we were solving each particular case.\\r\\n\",\"speakerIds\":[\"e2bc74a2-0838-4c15-921c-25f3439e3683\"],\"location\":\"Auditorium 11\",\"startsAt\":\"2024-05-24T13:00:00\",\"endsAt\":\"2024-05-24T13:45:00\",\"tags\":[\"Regular Session\",\"Advanced\",\"Multiplatform\"]},{\"id\":\"581753\",\"title\":\"Compose Migration Side Effects - What Can Go Wrong?\",\"description\":\"Android development has been revolving around the adoption of Compose lately. Compose is still the shiny, new, declarative - and now also multiplatform - way of building UIs. However, there are tons of projects out there that were built with Views, UIKit, or other favored UI solutions of platforms, while engineers also accumulated knowledge about all the quirks, issues, and workarounds with the framework they had to use or have chosen.\\r\\n\\r\\nIn this talk, we'll look at some less-than-ideal scenarios when jumping on the Compose train in a project unprepared might cause long-term headaches, and how we can avoid falling into future traps that we unconsciously set up today.\",\"speakerIds\":[\"1767e159-e7cf-4102-9765-cf5c99486183\"],\"location\":\"Auditorium 10 (Lightning talks)\",\"startsAt\":\"2024-05-24T13:00:00\",\"endsAt\":\"2024-05-24T13:15:00\",\"tags\":[\"Lightning talk\",\"Advanced\",\"Mobile\"]},{\"id\":\"579085\",\"title\":\"Kotlin/Native BigDecimal - a drop-in replacement for java.math.BigDecimal\",\"description\":\"When porting an app to iOS using Kotlin/Native, it turned out that I needed a BigDecimal implementation. But there was no drop-in replacement that I could use, so I decided that I would port java.math.BigDecimal from the Android (AOSP) sources to Kotlin/Native.\\r\\n\\r\\nIn this presentation, you will learn some details about how java.math.BigDecimal is implemented, how I've converted it to Kotlin, and about how I've rewritten the JNI code to cinterop to call a 3rd party library (BoringSSL) that is used for the actual big number computation.\\r\\n\\r\\nThe talk will discuss technical difficulties of converting the Java sources to Kotlin (easy task), building BoringSSL for iOS Simulator and device (advanced task), and creating the glue code to call the 3rd party native library via cinterop (hard task).\\r\\n\\r\\nKotlin/Native BigDecimal is available under Apache License v2 and the source code is hosted on GitHub:\\r\\n\\r\\n https://github.com/kendy/Kotlin-Native-BigDecimal\\r\\n\\r\\nIt is used in production in HiPER Scientific Calculator that has over 40 million downloads on Android, and achieved 500 thousand downloads on iOS in a year.\",\"speakerIds\":[\"d08e5fe8-0a12-4913-80cb-456badc5585e\"],\"location\":\"Auditorium 10 (Lightning talks)\",\"startsAt\":\"2024-05-24T13:25:00\",\"endsAt\":\"2024-05-24T13:40:00\",\"tags\":[\"Lightning talk\",\"Advanced\",\"Libraries\"]},{\"id\":\"576782\",\"title\":\"Revamping and Extending Kotlin's Type System\",\"description\":\"You might be surprised to learn that Kotlin's type system is undecidable and unsound; we can reliably cause the type-checker to stack-overflow, and we can trick it into thinking a String object is an Int. And that's before considering type inference or advanced features like platform types. Yet, understandably, developers are always requesting more features, like union and intersection types, and the Kotlin team would like to provide such features, but without jumping off a cliff of unrecoverable complexity. So how can we achieve this?\\r\\n\\r\\nKotlin is not alone in these issues; in fact, I discovered many of these problems in Java first. Yet, in discovering them, I also recognized how unnatural these problematic programs were. That is, they do not seem to be programs any pragmatic person would actually write. Rather, they represented expressiveness in the language that no one actually seems to need but yet manages to complicate the typing algorithms and even the language design.\\r\\n\\r\\nRecently, the Kotlin team and I started to explore how we might remove the unnecessarily problematic expressiveness—in a way that no practical developer would ever notice—so that we can lay a better foundation for supporting the features the developers actually want. In this session, I will offer a sneak peek into the changes we are exploring: the pragmatic restrictions, the new algorithmic foundations, and the extensions like efficient unions and intersections we hope to add. While this is a long-term project, we hope this session will convey the design strategy we are pursuing, as well as provide an opportunity for developers to share feedback and insights that can help us ensure the improvements serve their needs over the coming years.\",\"speakerIds\":[\"7b42f61c-5e49-45ac-96a7-5d6fb0391ebd\"],\"location\":\"Hall A\",\"startsAt\":\"2024-05-24T14:00:00\",\"endsAt\":\"2024-05-24T14:45:00\",\"tags\":[\"Regular Session\",\"Advanced\",\"Other\"]},{\"id\":\"554617\",\"title\":\"Diving into Advanced Compose Multiplatform Modifiers and Their Impact on Multiplatform Development\",\"description\":\"The advent of Compose Multiplatform has fundamentally shifted the landscape of cross-platform UI development, offering developers a declarative framework to simultaneously build intuitive and powerful user interfaces with Kotlin for multiple platforms. A pivotal element within this framework is the Compose Multiplatform Modifier, empowering developers to adjust and extend Multiplatform Composables in a clean and reusable manner. This talk seeks to explore the advanced and innovative uses of Compose Multiplatform Modifiers, providing insights into how they can be leveraged to optimize, streamline, and enhance cross-platform UI development in Kotlin.\",\"speakerIds\":[\"ec2ce46d-95a8-413e-8793-45db17d966d7\"],\"location\":\"Auditorium 15\",\"startsAt\":\"2024-05-24T14:00:00\",\"endsAt\":\"2024-05-24T14:45:00\",\"tags\":[\"Regular Session\",\"Intermediate\",\"Mobile\"]},{\"id\":\"587887\",\"title\":\"Free the world from wasteful scheduling with Timefold AI\",\"description\":\"Timefold Solver is an open source library to optimize planning and scheduling problems. It's the continuation of OptaPlanner.\\r\\n\\r\\nThe world is full of planning problems, such as vehicle routing, employee rostering, maintenance scheduling, job shop scheduling and school timetabling. They are “NP-hard”. That’s math speak for “challenging to solve optimally”. In the session, we’ll show you how to solve them easily with Timefold, an Apache Licensed AI solver for Kotlin.\\r\\n\\r\\nIn this session, I'll explain the challenges, discuss the algorithms and live code some of the constraints.\",\"speakerIds\":[\"b8eee37b-3033-496f-9dcf-3c892ed1ff31\"],\"location\":\"Auditorium 12\",\"startsAt\":\"2024-05-24T14:00:00\",\"endsAt\":\"2024-05-24T14:45:00\",\"tags\":[\"Regular Session\",\"Intermediate\",\"Libraries\"]},{\"id\":\"578348\",\"title\":\"Crossing the barrier from Kotlin to Rust (and back)!\",\"description\":\"Come learn why Mozilla invested in Rust for Android and how we've built open-source libraries to make it easier for others to do so as well. You'll learn how you can call Rust from Kotlin, and also call Kotlin from Rust.\\r\\n\\r\\nAt Mozilla, we've been shipping production Rust code in Firefox Android for years. Rust provides value because it's cross-platform, memory-safe and fast! Interfacing with Native libraries from Kotlin is difficult, but we've made it better! \",\"speakerIds\":[\"ce5f643d-771a-4b14-b504-329c50924cc3\"],\"location\":\"Auditorium 11\",\"startsAt\":\"2024-05-24T14:00:00\",\"endsAt\":\"2024-05-24T14:45:00\",\"tags\":[\"Regular Session\",\"Advanced\",\"Libraries\"]},{\"id\":\"585411\",\"title\":\"Using Vertx with Kotlin\",\"description\":\"This talk will cover Vertx from a Kotlin perspective. Vertx is a framework that allows non-blocking and asynchronous network communication and can be used as a server and a client to many external systems including messaging systems and databases. It is built around the concept of event loops which avoid the traditional multi-threading overheads and allow high throughput systems to be developed easily. The talk will introduce Vertx, it will describe why and how to use it in a Kotlin application.\",\"speakerIds\":[\"48310f7e-7f48-45f5-a2e6-91550fe78c0c\"],\"location\":\"Auditorium 10 (Lightning talks)\",\"startsAt\":\"2024-05-24T14:00:00\",\"endsAt\":\"2024-05-24T14:15:00\",\"tags\":[\"Lightning talk\",\"Intermediate\",\"Server-Side\"]},{\"id\":\"657081\",\"title\":\"Multiplatform Compose + SwiftUI = The Native App Future\",\"description\":\"KMP’s killer feature: Interop. It avoids 3 big traps of other “cross-platform” tools. KMP:\\r\\n\\r\\n1. Plays well with the native platform\\r\\n2. Blends well with native code\\r\\n3. Is optional. Can be as “native” as you need.\\r\\n\\r\\nWith KMP Compose, that flexibility moves to the screen.\\r\\n\\r\\nCompose and SwiftUI can work together. Render “native” UI or shared Compose UI, with the same underlying logic. Make more UI “native”, or build more features with shared UI, and make those decisions incrementally.\\r\\n\\r\\nUltimate Flexibility = Maximum Efficiency + Maximum Quality.\\r\\n\\r\\nIn this lab, we will:\\r\\n\\r\\n- Create screens with KMP Compose\\r\\n- Replace UI with SwiftUI, using the same KMP logic\\r\\n- Discuss the current state-of-the-art, and what’s coming soon…\\r\\n\\r\\nRequired reading and prerequisites are posted here: https://touchlab.co/codelabs.\",\"speakerIds\":[\"1bdf0b7f-2a71-4d40-a3e1-cb481f328361\",\"16e157d4-9d83-452f-a1f3-7feeb7e32d1f\",\"4b037d11-9426-4b3a-a24c-ee0da8d41100\"],\"location\":\"CodeLab\",\"startsAt\":\"2024-05-24T14:00:00\",\"endsAt\":\"2024-05-24T14:45:00\",\"tags\":[\"Intermediate\"]},{\"id\":\"583516\",\"title\":\"Using FModel to structure architecture from route to event store\",\"description\":\"Controllers have been the centerpiece of our application for a long time. We connect them to routes, validate the request and call our domain logic in the model.\\r\\n\\r\\nBut more software starts making events and commands the core of their domain. This is still interoperable with MVC, but it doesn't fit is as nicely. \\r\\n\\r\\nThis talk explores an alternative. Looking at the full server request lifecycle and making events and commands first class citizens using Kotlin FModel at it's core\\r\\n\\r\\nhttps://github.com/fraktalio/fmodel-demos\",\"speakerIds\":[\"161fd433-2422-4a4d-8320-9e34aee8df1e\"],\"location\":\"Auditorium 10 (Lightning talks)\",\"startsAt\":\"2024-05-24T14:25:00\",\"endsAt\":\"2024-05-24T14:40:00\",\"tags\":[\"Lightning talk\",\"Advanced\",\"Server-Side\"]},{\"id\":\"585329\",\"title\":\"KMP in Action: A Production Case Study\",\"description\":\"Over the past several years, numerous companies have undergone transformations. From relying on REST APIs to fully embracing GraphQL. From traditional iOS and Android development to the latest cross-platform technology, Kotlin Multiplatform. Despite the many benefits, it hasn't been without its challenges.\\r\\n\\r\\nIn this talk, I'll cover the benefits of using Kotlin Multiplatform in production, such as how it can streamline app development and improve data retrieval. I'll also discuss common challenges that arise when implementing new technologies in established products. Finally, I'll share best practices for addressing said challenges.\\r\\n\\r\\nSpecifically, I'll touch on:\\r\\n* adopting KMP as an engineering organization\\r\\n* architectural design considerations\\r\\n* libraries that enhance development speed\\r\\n\\r\\nLook forward to gaining valuable insights and practical advice for implementing Kotlin Multiplatform in production!\",\"speakerIds\":[\"7696a516-13da-40d7-bf15-70dda1317955\"],\"location\":\"Hall A\",\"startsAt\":\"2024-05-24T15:15:00\",\"endsAt\":\"2024-05-24T16:00:00\",\"tags\":[\"Regular Session\",\"Introductory and overview\",\"Multiplatform\"]},{\"id\":\"587400\",\"title\":\"Managing Complexity With Ktor\",\"description\":\"Many teams use Ktor solely to create and consume RESTful services over HTTP. They build modestly sized microservices and clients that perform a limited set of tasks well. Whilst these are completely valid use cases, they only scratch the surface of what is possible with Ktor.\\r\\n\\r\\nKtor includes support for Server Sent Events, WebSockets and kotlinx-io. These technologies allow you to incrementally stream data from client to server, such as when reading tokens from an LLM. You can also implement bidirectional conversations, recover from errors, and implement your own buffering strategies. At a higher level, in the design of your applications, you can use Dependency Injection frameworks like Koin, Kodein and Hilt to create and inject the correct networking client, repository, cache etc… for the current environment.\\r\\n\\r\\nThis talk will demonstrate how to configure Ktor Server and Client for a range of non-trivial tasks. You will see how to make best use of both existing, external libraries and upcoming enhancements to the framework itself.\",\"speakerIds\":[\"877c0f18-0545-40a7-b670-1f8593fa6f50\"],\"location\":\"Auditorium 15\",\"startsAt\":\"2024-05-24T15:15:00\",\"endsAt\":\"2024-05-24T16:00:00\",\"tags\":[\"Regular Session\",\"Intermediate\",\"Server-Side\"]},{\"id\":\"547002\",\"title\":\"Mastering Concurrency: End-to-End Stress Testing with Kotlin Multiplatform\",\"description\":\"Distributed systems may expose races, lockups, and other intermittent faults in production. A simple chat app may fail to show an incoming message, but only after running correctly for hours with 1500 active clients. Is it the frontend’s UI failing to update, a missing WebSocket transmission, the backend not synchronizing a session, or something else?\\r\\n\\r\\nWe want to find, analyze and fix such errors efficiently, before a roll-out. To observe real-world behavior, we need do end-to-end testing, with all sub-systems interacting like they do in production, fully multi-threaded, and across client-server boundaries.\\r\\n\\r\\nBut how can we analyze intermittent faults in a distributed system driven by massive parallelism? Even modern telemetry with its distributed logging and tracing will rarely provide the exact information we need. Logs frequently overwhelm us. Running thousands of parallel debugging sessions is impractical.\\r\\n\\r\\nLet’s dive into a world of efficient, real-world end-to-end testing with Kotlin Multiplatform! Explore how to integrate a JVM backend and multiplatform frontends on a single JVM for testing, using Kotest, a Ktor server test engine and thousands of headless Compose Multiplatform clients. Learn how minimal-overhead instrumentation can shorten testing times and answer the question “what got us here” when errors materialize. Access the entire distributed system via a single debugger, set a breakpoint on the intermittent fault condition, go for lunch, then use your debugger’s superpowers to analyze.\\r\\n\\r\\nTake away techniques and ready-to-use code examples which make end-to-end testing more efficient and work independently of frameworks used.\\r\\n\\r\\nTopics covered include:\\r\\n • System design considerations.\\r\\n • Lightweight, focused in-memory tracing.\\r\\n • Making critical sections of client and server code meet at the right time.\\r\\n • Provoking collisions and hitting capacity limits in a focused manner.\\r\\n • Using Kotest’s non-deterministic matchers, and clues (context information) in high-concurrency scenarios.\\r\\n • Avoiding common pitfalls when orchestrating parallelism and inspecting mutable state across thread boundaries.\",\"speakerIds\":[\"c00571fe-610a-42d5-9eb5-2db19f330650\"],\"location\":\"Auditorium 12\",\"startsAt\":\"2024-05-24T15:15:00\",\"endsAt\":\"2024-05-24T16:00:00\",\"tags\":[\"Regular Session\",\"Advanced\",\"Multiplatform\"]},{\"id\":\"551172\",\"title\":\"From Code to Streams: A Kotlin Odyssey with Apache Flink\",\"description\":\"Embark on an adventurous journey that takes you deep into the heart of real-time data processing with Kotlin and Apache Flink. In this session, we will explore the uncharted territories where these two technologies converge and tackle the real-world challenges that arise when harnessing their combined power.\\r\\n\\r\\nJoin us as we navigate through the complexities of:\\r\\n\\r\\nConcurrency Quagmires: Discover how Kotlin's elegant syntax can sometimes clash with Apache Flink's concurrent processing requirements and explore strategies to harmonize them.\\r\\n\\r\\nState Management Trials: Dive into the challenges of managing state in real-time applications, and learn how Kotlin's unique features can be leveraged to build fault-tolerant and efficient systems.\\r\\n\\r\\nPerformance Puzzles: Uncover the performance bottlenecks that can emerge when Kotlin and Apache Flink join forces, and master techniques to optimize your applications.\\r\\n\\r\\nThroughout our journey, we will share battle-tested solutions, practical insights, and real-world experiences. By the end of this session, you'll be well-prepared to overcome the challenges of using Kotlin with Apache Flink and embark on your own successful real-time data processing endeavors.\\r\\n\\r\\nJoin us for an expedition where we confront the challenges, seize the opportunities, and emerge victorious in the realm of Kotlin and Apache Flink.\",\"speakerIds\":[\"222381fc-4c18-4996-90f0-19cc72243c88\"],\"location\":\"Auditorium 11\",\"startsAt\":\"2024-05-24T15:15:00\",\"endsAt\":\"2024-05-24T16:00:00\",\"tags\":[\"Regular Session\",\"Intermediate\",\"Server-Side\"]},{\"id\":\"586999\",\"title\":\"Building libraries for the next 25 years\",\"description\":\"Libraries are a vital part of a language ecosystem. If you're building a client or server app, you're using dozens of them, maybe hundreds or more! And yet, library development can sometimes appear niche or difficult.\\r\\n\\r\\nIn this talk, I'll take library development to the front and center. How are libraries different from your usual client or server apps? What is easier but also what makes them more complex? How do apps and libraries interact and work together?\\r\\n\\r\\nI'll share lessons learned from working on Apollo Kotlin, from the early Java days up until KMP and wasm. \\r\\n\\r\\nIf you're a library author, you'll learn how to publish your library without the hassle, handle compatibility, evolution, versioning and more. \\r\\nIf you are not a library author, I hope this talk will encourage you to become one.\\r\\n\\r\\nTogether, let's build a vibrant Kotlin ecosystem for the next 25 years!\\r\\n\",\"speakerIds\":[\"56fda597-4927-4d25-9a80-4795d15ef080\"],\"location\":\"Hall A\",\"startsAt\":\"2024-05-24T16:15:00\",\"endsAt\":\"2024-05-24T17:00:00\",\"tags\":[\"Regular Session\",\"Intermediate\",\"Libraries\"]},{\"id\":\"568147\",\"title\":\"Tap it! Shake it! Fling it! Sheep it! - The Gesture Animations Dance!\",\"description\":\"Let's have fun with animations, gestures and sensors!\\r\\n\\r\\nUsing Compose Multiplatform, we'll go over how to create animations using gestures and sensor events for Android & iOS. We'll cover some basics like how to get the device motion and position information, how to track gestures in the screen, and how you can combine them with animations to have fun! \\r\\n\\r\\nAfter this talk, you'll have a better understanding on how to use the sensor frameworks, how to make your own gesture effects, and how to create interesting animations in an easy way.\\r\\n\\r\\nKeep it fun, keep it animated!\",\"speakerIds\":[\"94ba4fa4-aed7-482e-8096-f61090d5bb4d\"],\"location\":\"Auditorium 15\",\"startsAt\":\"2024-05-24T16:15:00\",\"endsAt\":\"2024-05-24T17:00:00\",\"tags\":[\"Regular Session\",\"Introductory and overview\",\"Mobile\"]},{\"id\":\"586859\",\"title\":\"Creative Coding with OPENRNDR\",\"description\":\"OPENRNDR is an opensource library that transforms Kotlin into an accelerator for creative coding. OPENRNDR was initially developed to support production work for a creative practice but is now used by a small community of designers and artists. The library has also found its way into education and is used as a tool to teach programming to creatives.\\r\\n\\r\\nCreative coding is programming software while using computation as a medium for expression. This software is often of a real-time, interactive and audiovisual nature. OPENRNDR offers many tools that help to manage the complexities of such software.\\r\\n\\r\\nBy using Kotlin's scripting engine OPENRNDR can be used as a live coding environment in which the write-compile-see cycle is eliminated. Live coding is a valuable tool for teaching, sketching and prototyping software.\",\"speakerIds\":[\"9b75fb2f-d87d-4470-ba35-edade14ea645\"],\"location\":\"Auditorium 12\",\"startsAt\":\"2024-05-24T16:15:00\",\"endsAt\":\"2024-05-24T17:00:00\",\"tags\":[\"Regular Session\",\"Introductory and overview\",\"Libraries\"]},{\"id\":\"586687\",\"title\":\"Dynamic Exploration of Static Analysis with Compose\",\"description\":\"Static analysis is so much more than just finding lint errors. With custom static analyzers, you can collect data you are interested in to better understand your codebase at scale.\\r\\n\\r\\nI personally found the idea of collecting custom analysis to be unapproachable and I didn’t know where to start. After making it through, and finding so much value, I want to break down that barrier for you through a series of examples. These examples are based on real use cases where you will learn how to write your own static analysis collectors for Kotlin, how to visualize the analysis results with Compose, and find hidden insights into your team’s project.\\r\\n\\r\\nWe’ll start by learning how to create a custom static analyzer of your project via Kotlin's Program Structure Interface (PSI) to collect the data. In this case we’ll collect Anvil and Dagger Dependency Injection contributions and usage.\\r\\n\\r\\nWe’ll then continue on to use the collected analysis data to render a Compose report allowing us to see these dependency relationships that are unavailable to the IDE (because it is unaware of our dependency injection frameworks).\\r\\n\\r\\nThis talk gives you the foundation you need to write custom static analysis collectors, how you can explore that data, and solve problems for your team at scale.\",\"speakerIds\":[\"dd32d92b-40e8-4dcf-a29c-a66ec2473b6f\"],\"location\":\"Auditorium 11\",\"startsAt\":\"2024-05-24T16:15:00\",\"endsAt\":\"2024-05-24T17:00:00\",\"tags\":[\"Regular Session\",\"Intermediate\",\"Other\"]},{\"id\":\"657231\",\"title\":\"Mature KMP Adoption Models for Native Mobile Teams\",\"description\":\"Touchlab’s new maturity model and approach to introducing and scaling KMP, using new tools for integration and deployment.\\r\\n\\r\\nKMP tech for native mobile is mature. Best-practice for teams is not. This lab is for native mobile teams adopting KMP for their non-UI logic and architecture.\\r\\n\\r\\nYou’ll get hands-on experience with Touchlab’s latest professional approach to KMP.\\r\\n\\r\\nWe’ll focus on 3 phases:\\r\\n\\r\\n1. Piloting - low-friction KMP introduction\\r\\n2. Production - monitoring and tuning to ensure success\\r\\n3. Perfecting - scale KMP adoption in a realistic scenario with the “deadline simulator”\\r\\n\\r\\nThere’s a lot to cover. Required reading and prerequisites are posted here: https://touchlab.co/codelabs.\\r\\n\\r\\nQ&A session will follow, time permitting.\",\"speakerIds\":[\"1bdf0b7f-2a71-4d40-a3e1-cb481f328361\",\"b0dd9228-8897-4fa2-b858-f8a3edbb511a\"],\"location\":\"CodeLab\",\"startsAt\":\"2024-05-24T16:15:00\",\"endsAt\":\"2024-05-24T17:00:00\",\"tags\":[\"Intermediate\"]},{\"id\":\"616756\",\"title\":\"Closing Panel\",\"description\":\"Like every KotlinConf, we'll end the event with a Closing Panel made up of different folks in the Kotlin community that are there to answer all the questions you've always wanted to ask. Make sure you don't make it easy for them!\",\"speakerIds\":[\"2d146e58-439f-40ec-9d5b-1dbefdeb707a\"],\"location\":\"Hall A\",\"startsAt\":\"2024-05-24T17:15:00\",\"endsAt\":\"2024-05-24T18:00:00\",\"tags\":[\"Regular Session\",\"Introductory and overview\",\"Other\"]}],\"speakers\":[{\"id\":\"9057aae9-da68-4346-87e2-220d354997bd\",\"name\":\"Aaron Todd\",\"position\":\"Senior Software Engineer at AWS\",\"description\":\"Aaron is a senior software engineer at AWS. He has over 13 years of experience spanning hard real time mission critical systems to leading backend development of latency sensitive web services. Currently he works on the AWS SDK for Kotlin.\",\"photoUrl\":\"https://sessionize.com/image/872a-400o400o1-WnCTtr4wTireMTNgrLaSCA.jpg\"},{\"id\":\"6194c065-3bcc-42b5-b1d1-9a25af6b86be\",\"name\":\"Alejandro Serrano Mena\",\"position\":\"Researcher @ Kotlin Language Evolution, JetBrains\",\"description\":\"Alejandro has devoted most of its career to understanding, teaching, and improving programming languages, especially in the realm of functional programming. He currently works on the evolution of the Kotlin language at JetBrains and helps co-maintaining the Arrow library after spending a few years in the consultancy and training world. Before that, he was a PhD and lecturer at Utrecht University, working on compilers for functional languages. He has written \\\"Functional Programming Ideas for the Curious Kotliner\\\" and three other books about Haskell, and it's active in promoting functional programming patterns and formal methods.\",\"photoUrl\":\"https://sessionize.com/image/0f08-400o400o1-PuyESVktZSL4EnoajX5s3S.png\"},{\"id\":\"8451e1e0-951a-4058-8a22-bb68d2c8f52e\",\"name\":\"Aleksei Zinovev\",\"position\":\"JetBrains, TeamLead in Kotlin for Data Science\",\"description\":\"Tempered in the crucible of Apache Hadoop and Apache Spark, the last few years, Alex is working on Machine Learning frameworks for JVM programming languages (Java, Scala, and Kotlin). \\r\\n\\r\\nIn 2017–2020 he worked on an ML module for a distributed in-memory database, Apache Ignite\\r\\n\\r\\n2020 was the year when Alexey created and released the new Deep Learning framework in Kotlin (Kotlin DL https://github.com/JetBrains/KotlinDL) \\r\\n\\r\\nSince 2023, Alexey has been leading the development and research in the development of data analysis tools in Kotlin.\",\"photoUrl\":\"https://sessionize.com/image/a2ed-400o400o1-4DiA61Ze98FVixrVfRcyHU.jpg\"},{\"id\":\"155ea7e0-6dc1-45c7-94c8-055475838101\",\"name\":\"Alexander Sysoev\",\"position\":\"Software developer at JetBrains\",\"description\":\"Alex is a Software Developer at JetBrains, who is working on creating new RPC library for Kotlin and improving existing functionality in the Ktor framework.\\r\\nAlready in University, Alex became a Kotlin enthusiast, who is passionate about inventing new ways how to use the language in different projects.\",\"photoUrl\":\"https://sessionize.com/image/ec75-400o400o1-3gyYmSniDaEXg7STmz7edD.png\"},{\"id\":\"7a141668-a505-4cee-bbb4-ea3bd3d4f403\",\"name\":\"Anastasiia Nekrasova\",\"position\":\"Software Developer in Kotlin Language Evolution, JetBrains\",\"description\":\"Anastasiia Nekrasova has worked at JetBrains since 2020 and is now a part of the Language Kotlin Evolution team. Anastasiia is currently focused on language design and shepherding features throughout all of the Kotlin ecosystem (KEEP, compiler FE, all BEs, libraries, QA, Dokka, documentation, style guide etc). She enjoys meeting users’ needs by design language features.\\r\\nShe previously worked in business application development related to highload and reliable web-systems.\\r\\nAnastasiia loves riding her motorcycle and traveling around the world.\",\"photoUrl\":\"https://sessionize.com/image/49fe-400o400o1-Eg17AjRzNVVJ3emS5BkXQF.jpg\"},{\"id\":\"1e19e15d-18c9-4cd9-82b2-280120a8c8a6\",\"name\":\"Andrei Shikov\",\"position\":\"Compose @ Google\",\"description\":\"Some people call me an engineer from time to time. Kotlin full-timer since before traits became interfaces.\",\"photoUrl\":\"https://sessionize.com/image/0af8-400o400o1-5d-18c9-4cd9-82b2-280120a8c8a6.6f94432f-c80a-4dfc-b910-0e9e51864072.jpg\"},{\"id\":\"9f10694b-6552-4023-bc47-41a8daed6896\",\"name\":\"Andrew O'Hara\",\"position\":\"Backend Tech Lead\",\"description\":\"Andrew leads Camcloud’s Platform Team, where he launched their evolution to backend Kotlin. He writes about testable service architectures, and is a major contributor to the Http4k project.\",\"photoUrl\":\"https://sessionize.com/image/5685-400o400o1-4Hp2g5KX1X85fJiTd9HHtU.jpg\"},{\"id\":\"7696a516-13da-40d7-bf15-70dda1317955\",\"name\":\"Annyce Davis\",\"position\":\"Google Developer Expert, Online Video Instructor\",\"description\":\"Annyce is an Android and Kotlin Google Developer Expert. She has spent the past 9+ years developing applications for the Android ecosystem across multiple form factors. She is also an international conference speaker and author, sharing her knowledge of Android and Kotlin development with others!\",\"photoUrl\":\"https://sessionize.com/image/46f4-400o400o1-nznxhp7iPXQoBr4syMhVvq.jpeg\"},{\"id\":\"f58eda10-92dc-41a0-ac4a-b1a9f2bd7e97\",\"name\":\"Anton Arhipov\",\"position\":\"Developer Advocate, JetBrains\",\"description\":\"Anton is a Developer Advocate in the Kotlin team at JetBrains. With a professional background in server-side development, Anton has been building tools for developers for more than 10 years. Recognized as a Java Champion since 2014, he often presents as a speaker at large software conferences and contributes to the Kotlin YouTube channel.\",\"photoUrl\":\"https://sessionize.com/image/d673-400o400o1-LVU364AmNvMvNAzyi11RBY.jpg\"},{\"id\":\"6cf514a7-0d9a-4e66-944b-672e39700c63\",\"name\":\"Anton Yalyshev\",\"position\":\"Product Manager at Kotlin, JetBrains\",\"description\":\"Since 2011, my expertise has been in dev. tooling development, beginning with quality engineering for Delphi and C++Builder IDEs. In 2015, JetBrains became my professional home, overseeing the quality of IntelliJ Scala plugin, later transitioning to product management for the Kotlin plugin. \\r\\nCurrently I lead the K2-based plugin to Stable release and enhance the decision-making process within the Kotlin language team.\",\"photoUrl\":\"https://sessionize.com/image/7d5d-400o400o1-nLHArppxX8xZznykc3KWoA.jpg\"},{\"id\":\"66fbb80a-cd18-4ba1-931d-d070d060ab95\",\"name\":\"Arnaud Giuliani\",\"position\":\"Cofounder of Kotzilla - Koin Project Lead\",\"description\":\"Software developer for more than 15 years. Works mainly as a Senior Android developer and keeps hands in backend gears, for big companies as well as startups. Speaker since 2016 for topics such Kotlin, Android Architecture & Koin. Google Developer Expert for Kotlin since 2020.\\r\\n\\r\\nIn 2017, Arnaud launched Koin (https://insert-koin.io), a lightweight dependency injection framework for Kotlin.\",\"photoUrl\":\"https://sessionize.com/image/3b0c-400o400o1-0a-cd18-4ba1-931d-d070d060ab95.277e5b69-b91f-444c-acd0-cd915945822e.jpg\"},{\"id\":\"63733e27-0704-401e-a342-8173a51b83c9\",\"name\":\"Brian Norman\",\"position\":\"Kotlin Compiler Core at JetBrains\",\"description\":\"Brian Norman has been writing Kotlin in many different areas across the Kotlin ecosystem for years, but may be most known for his work on Kotlin compiler plugins. In 2023, he joined the Kotlin Compiler Core team at JetBrains, working on the new K2 compiler frontend.\",\"photoUrl\":\"https://sessionize.com/image/32d6-400o400o1-XJZg1C6zzWxMBPiU5xTkM5.jpeg\"},{\"id\":\"aa4f4219-1d5a-4d23-bcb3-42284ff37fb0\",\"name\":\"Chantal Loncle\",\"position\":\"Software Developer, JetBrains\",\"description\":\"As a Software Developer in the Exposed team at JetBrains, Chantal has been working on maintaining and enhancing the database access library since early 2023.\",\"photoUrl\":\"https://sessionize.com/image/9c97-400o400o1-7PKMTr7u7ajoZJGzoUa44J.jpg\"},{\"id\":\"feb160de-17c4-4b74-9919-bae886909898\",\"name\":\"Christian Fredriksson\",\"position\":\"Volvo Car Cloud Chief Opinion Officer\",\"description\":\"Building the connected car cloud for Volvo Cars since 2015\",\"photoUrl\":\"https://sessionize.com/image/dcb4-400o400o1-39EaY5oueU3dQtzZdjqqoZ.jpg\"},{\"id\":\"4aff37ce-2304-496a-af9e-965f47fc3e78\",\"name\":\"Daniel Santiago\",\"position\":\"Software Engineer @ Google\",\"description\":\"Daniel is a Puerto Rican software developer working at Google in the Jetpack team and is passionate about meta programming, databases, video games and cats.\",\"photoUrl\":\"https://sessionize.com/image/0c9e-400o400o1-H3hG1fSmKCcmDfGYbnjcpd.jpg\"},{\"id\":\"d06cbb07-240c-4dd9-9c3d-4fd585e084fd\",\"name\":\"Daniel Terhorst-North\",\"position\":\"Consultant, coder, coach, originator of Behaviour-Driven Development, midwife of DevOps\",\"description\":\"Daniel Terhorst-North uses his deep technical and organisational knowledge to help CIOs, business and software teams to deliver quickly and successfully. He puts people first and finds simple, pragmatic solutions to business and technical problems, often using lean and agile techniques.\\r\\n\\r\\nWith thirty years of experience in IT, Daniel is a frequent speaker at technology and business conferences worldwide. The originator of Behaviour-Driven Development (BDD) and Deliberate Discovery, Daniel has published feature articles in numerous software and business publications, and contributed to The RSpec Book: Behaviour Driven Development with RSpec, Cucumber, and Friends and 97 Things Every Programmer Should Know: Collective Wisdom from the Experts.\\r\\n\\r\\nHe occasionally blogs at https://dannorth.net/blog.\",\"photoUrl\":\"https://sessionize.com/image/80d9-400o400o1-07-240c-4dd9-9c3d-4fd585e084fd.d1c70a7c-abcb-4864-b566-52bc31908665.jpg\"},{\"id\":\"b3f34b70-b68f-4325-8ffe-b599217e1f4c\",\"name\":\"David Denton\",\"position\":\"Engineering Lead // Founder // Trainer // Speaker // Kotlin GDE // Co-creator of http4k\",\"description\":\"Highly experienced Engineering Lead specialising in TDD, software craft, debt-resolving, mentoring and straight talking. \\r\\n\\r\\nParticularly specialised with ContinuousDeployment solutions: JVM, JS & a quick study in others. Everything-as-code automation. Build-craft. Refactoring wizard. Legacy-code cleaner.\\r\\n\\r\\nInternational speaker. Mentor, Co-founder of Monopolis (https://monopolis.cloud). Co-creator of the popular http4k platform (http://http4k.org) and recognised Kotlin Google Developer Expert.\",\"photoUrl\":\"https://sessionize.com/image/af84-400o400o1-Qsvhu3WqYBUtxgfQPgKxFP.jpg\"},{\"id\":\"9aa1160b-ce4f-4992-a1ad-b6da7d62c033\",\"name\":\"Dmitry Kandalov\",\"position\":\"Software Developer\",\"description\":\"Dmitry has been programming since DOS times. He spent the last 20 years or so in Java lands, most recently working with server-side Kotlin.\\r\\n\",\"photoUrl\":\"https://sessionize.com/image/fc09-400o400o1-DGR5B38QUBwQDNgjdaFb3P.jpg\"},{\"id\":\"c471c1b0-53d7-45cf-a12c-340714972d83\",\"name\":\"Duncan McGregor\",\"position\":\"Still coding after all these years\",\"description\":\"Duncan has been a professional software developer for over 30 years now. He was lucky enough to be an early adopter of Object Oriented programming, which was the gateway drug to patterns and Extreme Programming, and more recently functional programming in Kotlin. These days he still writes code for a living, coauthored Java to Kotlin: A Refactoring Guidebook, is a Google Developer Expert, and publishes a weekly YouTube video on Kotlin.\\r\\n\\r\\nHe will try almost anything in his quest for better software, including, but not limited to, actually talking to people. \",\"photoUrl\":\"https://sessionize.com/image/55fe-400o400o1-PvFTW6mcgFnwG9vhdZpbgc.jpeg\"},{\"id\":\"9b75fb2f-d87d-4470-ba35-edade14ea645\",\"name\":\"Edwin Jakobs\",\"position\":\"Principal developer of OPENRNDR\",\"description\":\"Edwin Jakobs is a developer and a designer with a strong interest in computational and generative methods. He is one of the founding partners of RNDR, a studio for interactive design based in The Hague. Edwin is the lead developer of OPENRNDR an open source framework for creative coding.\",\"photoUrl\":\"https://sessionize.com/image/f18e-400o400o1-2f-d87d-4470-ba35-edade14ea645.ebdd9d69-0cd2-4e79-a5d2-857e9d88b5f5.png\"},{\"id\":\"fd9a742d-2e4a-4c87-86ee-b8e03a0984a0\",\"name\":\"Egor Tolstoy\",\"position\":\"Kotlin Project Lead @ JetBrains\",\"description\":\"Egor joined the Kotlin team as a Product Manager in 2019, with a focus on enhancing the developer experience. He now serves as the Project Lead for Kotlin, guiding the project's strategic direction and leading the team.\",\"photoUrl\":\"https://sessionize.com/image/65ef-400o400o1-PhtwXjcJFuKcnmyazDGWWo.jpg\"},{\"id\":\"8707cb07-3a1b-4806-8787-6f5e56f1bd60\",\"name\":\"Ehsan Mehranvari\",\"position\":\"Staff engineer at Volvo Cars\",\"description\":\"My name is Ehsan, and I am a dedicated professional employed as a staff engineer at Volvo Cars. With a deep passion for technology and innovation, I have been working on projects that involve creating user-friendly mobile apps.\\r\\nI'm enthusiastic about technology and believe it can change our lives. Besides my work, I like exploring new tech, participating in hackathons, and sharing my knowledge with other engineers. My aim is to keep innovating in mobile app development and contribute to the automotive industry's future.\",\"photoUrl\":\"https://sessionize.com/image/102d-400o400o1-EZPyvZXwyZCHpZLPTHXXK9.jpeg\"},{\"id\":\"5b2f8184-971a-400c-982d-c33683fd5d61\",\"name\":\"Ekaterina Petrova\",\"position\":\"Product Marketing Manager @ JetBrains\",\"description\":\"I started my career in IT as an iOS developer back in the days of the iPhone 3GS. I tried different roles and worked as an engineering manager and even a CTO in a small startup. Three years ago, I joined JetBrains as a developer advocate for Kotlin. Now I have become a product marketing manager for Kotlin Multiplatform, as I love mobile development and strongly believe in a crossplatform approach, with Kotlin Multiplatform, of course. 😁  I’m also a co-host of a famous IT podcast for the Russian-speaking audience.\\r\\n\",\"photoUrl\":\"https://sessionize.com/image/a48c-400o400o1-Tc1za6zFuGoGS58BKXPWBB.png\"},{\"id\":\"1224bcba-11e0-4f5a-a1b2-c7d533bc42f4\",\"name\":\"Elif Bilgin\",\"position\":\"Software Engineer @ Google\",\"description\":\"Software Engineer at Google on the Android Toolkit & Jetpack Team. \",\"photoUrl\":\"https://sessionize.com/image/31a4-400o400o1-su6XWB9QanYo8dWtHZpMg4.jpg\"},{\"id\":\"e2bc74a2-0838-4c15-921c-25f3439e3683\",\"name\":\"Elijah Semyonov\",\"position\":\"JetBrains, Compose Multiplatform, iOS integration engineer\",\"description\":\"Doing iOS since 2011, AR, astronomy and CG enthusiast. \",\"photoUrl\":\"https://sessionize.com/image/7979-400o400o1-UJb4jQVTGQhX62Hmc3kxdw.jpg\"},{\"id\":\"8bcbaefb-2d28-49a7-9797-56754de90160\",\"name\":\"Erik Meijer\",\"position\":\"Think like a fundamentalist, code like a hacker.\",\"description\":\"https://en.wikipedia.org/wiki/Erik_Meijer_(computer_scientist)\",\"photoUrl\":\"https://sessionize.com/image/4d70-400o400o1-WdYEjyoPPCcbyWJas4uV8q.jpg\"},{\"id\":\"e0d9f3b5-55c9-48ae-aef4-84786b04e329\",\"name\":\"Erik Westenius\",\"position\":\"Senior Android Engineer at Bontouch\",\"description\":\"Senior Android engineer at Bontouch with over 10 years of professional Android Experience. In love with Jetpack Compose since early alpha! Currently working as Android Lead in the SJ (Swedish Railways) App Team. \",\"photoUrl\":\"https://sessionize.com/image/5c1c-400o400o1-UEsrji8ZqUndsfYc5548FU.jpg\"},{\"id\":\"c53e7302-d53c-4c56-ae42-693a74de8ba6\",\"name\":\"Eve Matthaey\",\"position\":\"Software Engineer @ Meta\",\"description\":\"Eve is an Android engineer at Meta.\",\"photoUrl\":\"https://sessionize.com/image/df80-400o400o1-EjwFvZeUDGhuE2ACuzyic8.jpg\"},{\"id\":\"d2ddc9e3-35b6-44a9-8daa-144d89cabaff\",\"name\":\"Evgeny Mandrikov\",\"position\":\"Software Gardener, Language Team Technical Leader @SonarSource\",\"description\":\"Evgeny is a contributor to various open source projects, including OpenJDK, and a speaker at international conferences and JUGs. He is also one of the project leads of widely adopted code coverage library for Java and Kotlin - JaCoCo, and the award-winning EclEmma project at the Eclipse Foundation that integrates JaCoCo into Eclipse. In his day job at Sonar he develops SonarQube’s static source code analysis for languages such as Java, Kotlin, C, and C++.\",\"photoUrl\":\"https://sessionize.com/image/6f13-400o400o1-fWhP66qq2SDdw33AoPHXsD.jpg\"},{\"id\":\"b2bfc2d3-c516-4479-9b56-85634606fb99\",\"name\":\"Filip Dolník\",\"position\":\"Senior Kotlin Developer at Touchlab\",\"description\":\"Filip is a Senior Kotlin Developer at Touchlab, specializing in the Kotlin compiler and Gradle. His work revolves around improving the Kotlin Multiplatform developer experience. He is best known as a co-author of SKIE, a compiler plugin that generates a Swift-friendly API for Kotlin Native. With a deep passion for compilers, programming languages, and technology in general, Filip is dedicated to pushing the boundaries of what's possible in the Kotlin ecosystem.\",\"photoUrl\":\"https://sessionize.com/image/cf6b-400o400o1-pEAq5VtokxQxr24tpQrLHf.jpg\"},{\"id\":\"eb6d6054-e6f7-40ff-b5d1-a1863c70d841\",\"name\":\"Francesco Guardiani\",\"position\":\"Software Engineer @ Restate\",\"description\":\"I’m a Software Engineer and OSS enthusiast based in Berlin working at Restate. I love to shape developer experiences and solve complex problems. My main tech stacks are Rust, JVM and Golang. Previously, I worked on Eclipse Vert.x, Apache Flink and Knative\",\"photoUrl\":\"https://sessionize.com/image/8412-400o400o1-puhuz4a6RV2aCVdihmRbsz.jpg\"},{\"id\":\"3c5ac1d8-444e-48ee-89ff-d092279e950b\",\"name\":\"Francisco Diaz Rodriguez\",\"position\":\"Solutions Director at Xebia\",\"description\":\"I work as a Solutions Director at Xebia, diving deep into the IT industry. My journey has been filled with software engineering, team leadership, and a love for functional programming, data engineering, and microservices architecture. I'm all about teamwork and sharing knowledge because I believe that's where the real magic happens.\",\"photoUrl\":\"https://sessionize.com/image/faa1-400o400o1-UpBj3sfYoR9p2BtUdCrYcR.jpg\"},{\"id\":\"4b037d11-9426-4b3a-a24c-ee0da8d41100\",\"name\":\"Gabriel Souza\",\"position\":\"KMP Developer at Touchlab\",\"description\":\"I started out by modding Minecraft servers with Java, then discovered Kotlin and never looked back, integrating it where possible. Since 2018, I have been working as an Android developer and maintaining open-source libraries, such as Voyager and Compose Icons.\",\"photoUrl\":\"https://sessionize.com/image/a06b-400o400o1-MPf2xHeoKzGCS73C5EHQFe.jpg\"},{\"id\":\"877c0f18-0545-40a7-b670-1f8593fa6f50\",\"name\":\"Garth Gilmour\",\"position\":\"Garth Gilmour - Developer Advocate at JetBrains\",\"description\":\"Garth Gilmour was a full time developer for 5 years and then an educator / mentor for 20. Currently he's a Developer Advocate at JetBrains. He's taught well over 1000 courses and workshops - using everything from CORBA to Kotlin. Garth is a prolific speaker, writer and co-organiser of several conferences and meetups. When not at the whiteboard he coaches Krav Maga, lifts heavy weights and fights nerf wars with his kids. \\r\\n\",\"photoUrl\":\"https://sessionize.com/image/f106-400o400o1-18-0545-40a7-b670-1f8593fa6f50.a02d66df-f682-4f91-a4de-ef525921e101.png\"},{\"id\":\"b8eee37b-3033-496f-9dcf-3c892ed1ff31\",\"name\":\"Geoffrey De Smet\",\"position\":\"Timefold CTO\",\"description\":\"Geoffrey De Smet is the creator and lead of Timefold, the open source AI constraint solver for Kotlin or Java.\\r\\nAround the globe, Timefold automatically optimizes vehicle routing, maintenance scheduling, job shop scheduling, employee scheduling and other planning problems.\\r\\nGeoffrey is also an international speaker on planning optimization.\",\"photoUrl\":\"https://sessionize.com/image/7ace-400o400o1-nPwDqEVukkuL7mJV3SDv8R.jpg\"},{\"id\":\"0f25b6f3-dbd3-4c7e-ad54-a13414f9b5c2\",\"name\":\"Giancarlo Buenaflor\",\"position\":\"Software Engineer @ sentry.io, GSoC 2023 Contributor\",\"description\":\"Hi! I am a SDK Software Engineer at Sentry and started my journey as an intern working on the Kotlin Multiplatform SDK for Sentry. I have gained a great deal of passion for Kotlin through this and hopefully will be able to improve and gain more insights as I go.\\r\\n\\r\\nI have also participated in GSoC 2023 working alongside Google and Jetbrains on the KMP project KFlogger. Additionally I also participated in episode 8 of Jetbrains ATOM Podcast talking about our Sentry KMP SDK.\",\"photoUrl\":\"https://sessionize.com/image/8004-400o400o1-JhX8GMxMN56WEyGS3APbAf.jpeg\"},{\"id\":\"29714cd6-635b-4d48-b373-e7b27689b965\",\"name\":\"Giselle van Dongen\",\"position\":\"Developer advocate @ Restate\",\"description\":\"Giselle is a Developer Advocate at Restate, where she helps its early users with understanding how Restate simplifies the development of resilient and scalable distributed apps. Before that, she worked in the field of big data analytics and distributed stream processing, and obtained a PhD on this topic at Ghent University.\",\"photoUrl\":\"https://sessionize.com/image/ad8f-400o400o1-N7ucUi58oVxRuAbBRazprf.jpg\"},{\"id\":\"16e157d4-9d83-452f-a1f3-7feeb7e32d1f\",\"name\":\"Gustavo Fão Valvassori\",\"position\":\"KMP Developer at Touchlab\",\"description\":\"I started learning Mobile App Development in 2012, dreaming of the possibility of using Mobile for everything. With that goal, I've already tested and used many different mobile frameworks and platforms. Since 2018, I've been focused on Kotlin Development. \",\"photoUrl\":\"https://sessionize.com/image/8fcd-400o400o1-DzqfFETRwiLxUHMpUnRe5T.png\"},{\"id\":\"2d146e58-439f-40ec-9d5b-1dbefdeb707a\",\"name\":\"Hadi Hariri\",\"position\":\"Never believed in elevator pitches\",\"description\":\"Developer and creator of many things OSS, his passions includes Web Development and Software Architecture. Has authored a couple of books, a few courses and has been speaking at industry events for nearly 20 years. Currently at JetBrains leading the Developer Advocacy team. Spends as much time as he can writing code.\",\"photoUrl\":\"https://sessionize.com/image/ce8a-400o400o1-58-439f-40ec-9d5b-1dbefdeb707a.40874e9d-b2c9-4434-9efe-c2759e8b1947.png\"},{\"id\":\"9f2b5627-1d42-423f-a6e9-f5e5e356edee\",\"name\":\"Ian Botsford\",\"position\":\"Sr. Software Development Engineer at Amazon\",\"description\":\"Ian Botsford is a senior engineer at AWS. He's a fan of big data, microservices, and functional programming. He's been a Kotlin developer for 2 years and still keeps discovering new things to love about it!\",\"photoUrl\":\"https://sessionize.com/image/6654-400o400o1-RtRufXWVag4M4yqPBtWJdi.jpg\"},{\"id\":\"1db23323-e852-4faa-87e3-94d5f05d0b96\",\"name\":\"Igor Wojda\",\"position\":\"Principial Android Developer\",\"description\":\"Igor Wojda is a software engineer with 20 years of experience in the field. His proficiency is centered around the Kotlin programming language and application architecture design. Igor has established himself as a conference speaker, open-source contributor, and technical reviewer for several books devoted to the Kotlin programming language. In addition, he is the author of \\\"Android Development with Kotlin\\\" and a Founding Developer behind the Konsist project. Igor enjoys sharing his passion for coding with other developers.\",\"photoUrl\":\"https://sessionize.com/image/d368-400o400o1-c13514c2-d29b-426c-8f81-cbd5053bd063.jpg\"},{\"id\":\"1767e159-e7cf-4102-9765-cf5c99486183\",\"name\":\"István Juhos\",\"position\":\"Staff Android Engineer @ Circuit\",\"description\":\"Staff Android Engineer @ Circuit; Co-organizer of Android Budapest\",\"photoUrl\":\"https://sessionize.com/image/843d-400o400o1-CZsnM75u2hJEfDQ7sRoVp.jpg\"},{\"id\":\"3eabdd46-6cb5-4083-9eb8-1ad9a3b7a5eb\",\"name\":\"Jake Wharton\",\"position\":\"Android at Cash App\",\"description\":\"Android engineer at Cash App working on Kotlin, Compose, open source, and more\",\"photoUrl\":\"https://sessionize.com/image/f0c0-400o400o1-5b966c61-164b-4292-945e-e5e435d350d2.jpg\"},{\"id\":\"5c84d73d-1b13-4383-a7ec-e7ce3151794e\",\"name\":\"James Ward\",\"position\":\"Developer Advocate @ AWS\",\"description\":\"Professional software developer since 1997, with much of that time spent helping developers build software that doesn't suck. A Typed Pure Functional Programming zealot who often compromises on his ideals to just get stuff done. Currently a Developer Advocate for AWS.\",\"photoUrl\":\"https://sessionize.com/image/ded2-400o400o1-3d-1b13-4383-a7ec-e7ce3151794e.dc841fd0-dfb3-44cb-8c0b-542fb0968a02.jpg\"},{\"id\":\"d08e5fe8-0a12-4913-80cb-456badc5585e\",\"name\":\"Jan Holesovsky\",\"position\":\"Crossoid - Develop for Android, release on iOS.\",\"description\":\"Jan is a co-founder of Crossoid (https://crossoid.com), a project and company focusing on implementing an Android-alike API for Kotlin/Native, primarily targeting iOS. With Crossoid, it is possible to take unmodified sources of an Android application (including XML resources, activities, etc.) and compile the iOS app from that. Or, as we say: Develop for Android, release on iOS.\",\"photoUrl\":\"https://sessionize.com/image/b189-400o400o1-fkC3ex5gHjksKwwju2XZwj.jpg\"},{\"id\":\"4f541219-75cb-4e12-a1e9-4d9382652d0d\",\"name\":\"Jason Parachoniak\",\"position\":\"Google, Software Engineer\",\"description\":\"I've worked on, Frontend Code, Backend Code, Firmware development and Web Apps. The last several years I've worked in compilier development in various forums.\",\"photoUrl\":\"https://sessionize.com/image/84cf-400o400o1-JTcG9uabkn7ZUkhE9uxugo.jpg\"},{\"id\":\"9ff98d8b-f176-49b9-a871-339cf8fad50b\",\"name\":\"Jeffrey van Gogh\",\"position\":\"Language Geek @ Google\",\"description\":\"Jeffrey is a Director of Engineering at Google, he's in charge of Programming Language support for Android. He has over 20 year of industry experience building developer tools with a focus on compilers and static analysis. Jeffrey is a Board Member of the Kotlin Foundation and Google's representative on the Kotlin Language Committee, ensuring the language ages well. Jeffrey studied Computer Science at the University of Utrecht in the Netherlands.\",\"photoUrl\":\"https://sessionize.com/image/78fd-400o400o1-8b-f176-49b9-a871-339cf8fad50b.429f0a3a-f907-4147-af88-919baf36796d.jpg\"},{\"id\":\"a9cd5609-7f60-4d7c-bea3-052c42118f16\",\"name\":\"Jeroen Rosenberg\",\"position\":\"Dev of the Ops - Continuous Deliverer - Software Engineering Consultant @Xebia\",\"description\":\"Jeroen Rosenberg is an Amsterdam based pragmatic software engineer and consultant focused on building resilient software at Xebia. With a strong background in Java & Scala development and Fast Data Architectures he helps teams deliver great products by using practices, techniques and tools from Lean, Agile, DevOps and Continuous Delivery.\\r\\n\\r\\nBesides his daily work, he founded the Amsterdam.scala meetup group, still co-hosts and conducts training courses. When not coding or writing you can find him eating nachos at the beach with the love of his life. He’s a proud father of three kids and uses them as an excuse to be able to play with Lego again.\\r\\n\",\"photoUrl\":\"https://sessionize.com/image/eb8a-400o400o1-8ffccfd9-15a9-4e7a-8843-1a3fd01c9827.jpg\"},{\"id\":\"9369d066-526c-434b-9dea-d5925d03940f\",\"name\":\"Johannes Svensson\",\"position\":\"Lead Android Developer @ Instabee\",\"description\":\"Android developer since 2009, brewmaster since 2019, father since 2021, Japanese resident since 2023.\",\"photoUrl\":\"https://sessionize.com/image/b3a0-400o400o1-aszja7TP8ZDAvrX9SCfLfh.jpg\"},{\"id\":\"0392772c-28d4-47f6-bd39-47d743fb4a81\",\"name\":\"John O'Reilly\",\"position\":\"Android Software Engineer @ Neat\",\"description\":\"John is a Kotlin GDE that has been developing Android apps since 2010. He worked on server side Java applications in the 2000s and desktop clients in the 1990s. He's also been exploring and advocating for all things Kotlin Multiplatform since 2018.\",\"photoUrl\":\"https://sessionize.com/image/2245-400o400o1-HkquSQhsfczBGkrABwVTBc.jpg\"},{\"id\":\"b94daf79-b12a-4257-8556-38d500bb414b\",\"name\":\"John Pampuch\",\"position\":\"Production Programming Languages at Google\",\"description\":\"Today, John leads Google’s Internal Production Programming Languages team (CDSF Languages). Before that, John led the Java and Kotlin Team since 2018, with a focus on driving adoption of Kotlin across internal server deployments\\r\\nJohn has held various engineering and management roles at Sun, Oracle, Adobe, Azul Systems and others, including, at Sun and Oracle, John led the JVM (Hotspot) group.\\r\\nJohn is primarily a Java developer, but has also written his fair share of bugs in C, C++ and other languages.\\r\\nIn a past life, John invested a small fortune into Legos but today those mostly sit on a shelf in the garage.\\r\\n\",\"photoUrl\":\"https://sessionize.com/image/dd14-400o400o1-hud3asRmhNz6MYSuFjyC2X.jpeg\"},{\"id\":\"cdc62a79-11fb-4c29-b021-81935c453521\",\"name\":\"Julie Gunderson\",\"position\":\"Sr. Developer Advocate - AWS\",\"description\":\"Julie Gunderson is a Sr. Developer Advocate at AWS, who advocates best practices around DevOps, reducing silos, reliability, and the psychology of teams. Along with advocacy, in her past role Julie was responsible for building partnerships with the major clouds. Julie loves working with people, advocating best practices and all building relationships. Julie is a founding member of DevOpsDays Boise, which recently celebrated its 5th year. When Julie isn’t working she is most likely making jewelry out of circuit boards, or traipsing around the mountains in Idaho.\",\"photoUrl\":\"https://sessionize.com/image/ca87-400o400o1-ncZ7uqT75vASXad23TPMPg.jpg\"},{\"id\":\"b0dd9228-8897-4fa2-b858-f8a3edbb511a\",\"name\":\"Justin Mancinelli\",\"position\":\"Director of Project Strategy\",\"description\":\"Justin helps dev and product teams navigate the waters of mobile app development and is an expert at integrating them into larger technical, customer, and business ecosystems. He has been building software and managing agile software teams since 2011.\\r\\n\\r\\nJustin loves New York (especially the MTA) but has lived all over the world, including Australia and Japan.\",\"photoUrl\":\"https://sessionize.com/image/77e2-400o400o1-28-8897-4fa2-b858-f8a3edbb511a.09135175-df47-4c92-be7d-699246655f72.jpg\"},{\"id\":\"2945cb69-3e28-4cae-9fd8-c01ce9f10869\",\"name\":\"Kevin Bierhoff\",\"position\":\"Bringing Kotlin to Google\",\"description\":\"Kevin leads the Kotlin at Google team that helps Googlers use Kotlin in their daily work, including on Android and JVMs.\",\"photoUrl\":\"https://sessionize.com/image/9820-400o400o1-9G8AvKUJDD5cRGEZcZubvx.jpeg\"},{\"id\":\"1bdf0b7f-2a71-4d40-a3e1-cb481f328361\",\"name\":\"Kevin Galligan\",\"position\":\"Partner at Touchlab\",\"description\":\"Kevin Galligan is a Partner at Touchlab. He has 20 years of professional software development experience, and has been working on Android since the first public platform release. Kevin is currently focused on developing and evangelizing Kotlin multiplatform native tools for the next generation of mobile development.\",\"photoUrl\":\"https://sessionize.com/image/7518-400o400o1-7f-2a71-4d40-a3e1-cb481f328361.91f83573-a3b9-471e-8815-e1de2f897e6e.jpg\"},{\"id\":\"0fd04388-0a57-4c8e-9505-89d7962c2dba\",\"name\":\"Konstantin Tskhovrebov\",\"position\":\"Compose Multiplatform @ JetBrains\",\"description\":\"10 years Android developer\\r\\n4+ Kotlin developer\",\"photoUrl\":\"https://sessionize.com/image/db62-400o400o1-KXePCUL4piZiGwU6pLw2CK.jpg\"},{\"id\":\"35f8da6a-8cfc-4e0d-9660-f616ca218e93\",\"name\":\"Leonid Stashevskii\",\"position\":\"JetBrains. Ktor & Exposed Lead\",\"description\":\"Kotlin libraries team. Ktor developer.\",\"photoUrl\":\"https://sessionize.com/image/b042-400o400o1-S2K5vT6V5wvC8SR4NuTv3W.jpg\"},{\"id\":\"7c1cede6-5f59-46bb-ad1e-22b63758dae7\",\"name\":\"Louis CAD\",\"position\":\"Amande - Founder\",\"description\":\"I love reliable, efficient, and fun things.\\r\\nKotlin is my go-to tool to achieve that in software projects since 2016.\\r\\n\\r\\nI maintain a few successful open source projects like refreshVersions and Splitties, while seeking new problems to solve with new libraries.\\r\\n\\r\\nAlways trying to innovate, I am interested in a lot of technical subjects of all scales, and how they are linked, directly or not.\\r\\n\\r\\nI also specifically love commuting by recumbent bike, velomobiles, and lego technic.\",\"photoUrl\":\"https://sessionize.com/image/513f-400o400o1-8uv1o8mW8uWPvgF1vEKUh.jpg\"},{\"id\":\"2313d8eb-7d6e-444d-8e8d-4d223f896ce8\",\"name\":\"Maia Grotepass\",\"position\":\"Staff Engineer: Android competency lead at Luno\",\"description\":\"Mobile dev since Cupcake. Android GDE. Kotlin enthusiast. Dogs make me happy.\",\"photoUrl\":\"https://sessionize.com/image/b7fb-400o400o1-PQ22Fj6woXrZCjkLnpk1ak.jpeg\"},{\"id\":\"aeddc24f-0e47-4934-ad76-2de7a9dc9fac\",\"name\":\"Marco Gomiero\",\"position\":\"Senior Android Developer @ Airalo - Kotlin GDE\",\"description\":\"Marco is an Android engineer, currently working at Airalo. He is a Google Developer Expert for Kotlin, he loves Kotlin and he has experience with native Android and native iOS development, as well as cross-platform development with Flutter and Kotlin Multiplatform.\\r\\n\\r\\nIn his spare time, he writes and maintains open-source code, he shares his dev experience by writing on his blog, speaking at confs and organizing events with the Google Developer Group Venezia and he plays basketball.\",\"photoUrl\":\"https://sessionize.com/image/0159-400o400o1-JVg7XKCfJ2g8Pi1LyNPMPA.jpg\"},{\"id\":\"eeb25beb-5d37-4fb7-acac-170357a1d89b\",\"name\":\"Marharyta Nedzelska\",\"position\":\"Software Engineer @ Sonar\",\"description\":\"Margarita is a big Kotlin fan and Kotlin GDE. Knows both conference sides: speaking and organizing. Organized a KUG in her native city Kyiv because she believes in Knowledge Sharing and Collective Intelligence. For her everyday job, she's building Static Code Analysis tools for Java/Kotlin/Scala and other languages.\",\"photoUrl\":\"https://sessionize.com/image/0b1a-400o400o1-e2ba4bc2-bed9-4217-ab0b-2a5b2eb895b1.jpg\"},{\"id\":\"56fda597-4927-4d25-9a80-4795d15ef080\",\"name\":\"Martin Bonnin\",\"position\":\"Mobile Engineer at ApolloGraphQL\",\"description\":\"Martin is a maintainer of Apollo Kotlin. He has been writing Android applications since Cupcake and fell in love with Kotlin in 2017. Martin loves naming things and the sound of his laptop fan compiling all these type-safe programs. When not busy rewriting all his bash scripts in Kotlin, Martin loves to hike the Pyrénées or play a good game of Hearthstone.\",\"photoUrl\":\"https://sessionize.com/image/00e1-400o400o1-UiWeCMZDxPejrFsozKmLYr.jpeg\"},{\"id\":\"5307510b-c3fa-4f9c-a340-36d198198ef5\",\"name\":\"Márton Braun\",\"position\":\"Developer Advocate @ JetBrains\",\"description\":\"Márton is a Kotlin Developer Advocate at JetBrains, working on making Kotlin Multiplatform awesome. Passionate about education, he's a guest lecturer at the Budapest University of Technology and Economics.\\r\\n\\r\\nHe’s been contributing to the community through writing, speaking, and open source libraries since his university days. He is a Google Developer Expert for Android and Kotlin, and a co-organizer of Android Budapest and Android Worldwide.\",\"photoUrl\":\"https://sessionize.com/image/13e0-400o400o1-RRyuxJHmysRieKokiLVzmj.jpg\"},{\"id\":\"ec2ce46d-95a8-413e-8793-45db17d966d7\",\"name\":\"Meike Felicia Hammer\",\"position\":\"Android Lead @ adesso mobile solutions\",\"description\":\"Meike Felicia Hammer is a Senior Software Engineer at adesso mobile solutions GmbH and is responsible for the Android department. She has been working on mobile app development since 2009 and is regularly pleased with the implementation of related backend-for-frontend systems. Meike Felicia has been a fan of JetBrains, including Kotlin, for a long time. She is also known as the organizer of the Kotlin User Group Karlsruhe and as a speaker at MobileTechCon, Python Summit and KKON.\",\"photoUrl\":\"https://sessionize.com/image/bcb3-400o400o1-RPVqQNFnBRbbNESJTCrzpk.jpeg\"},{\"id\":\"08416a0a-bb37-4e33-b1e5-2d1f2e2102eb\",\"name\":\"Michail Zarečenskij\",\"position\":\"Lead Language Designer @ JetBrains\",\"description\":\".\",\"photoUrl\":\"https://sessionize.com/image/0901-400o400o1-QosQ37yUhyXdFn4kFVYbYp.png\"},{\"id\":\"a79f3682-df5c-40e4-8aa8-1b6eaa7bdeec\",\"name\":\"Mohit Sarveiya\",\"position\":\"Google Developers Expert Kotlin & Android\",\"description\":\"Mohit Sarveiya is a Google Developer Expert in Kotlin and Android. Prior to building Android apps, he was a Backend Engineer. He was an early adopter of Kotlin and absolutely loves the language. He has given many talks and workshops on Kotlin.\",\"photoUrl\":\"https://sessionize.com/image/27b5-400o400o1-KVK4kvFitPjesss8TcUTR3.png\"},{\"id\":\"30cc8bd5-49a1-4609-bf70-ff5e6b12b3c2\",\"name\":\"Nat Pryce\",\"position\":\"Consulting developer\",\"description\":\"Nat has been programming for *coughty-cough* years, in various languages, platforms, application domains and industries.\",\"photoUrl\":\"https://sessionize.com/image/aba9-400o400o1-WJ59qQwhfQkmbbXDSjBZna.jpg\"},{\"id\":\"1b6696dd-e240-49c2-a383-26d3e8f656d3\",\"name\":\"Natalia Peterwas\",\"position\":\"Kotlin developer\",\"description\":\"Natalia is a passionate Kotlin developer. Her journey with Kotlin has allowed her to pioneer innovative solutions to enhance codebase integrity and enforce coding standards across Kotlin projects. She has been crucial in the development of the Konsist library from the start. Natalia's passion for sleek and effective coding drives her to explore new frontiers in programming.\",\"photoUrl\":\"https://sessionize.com/image/b2d0-400o400o1-GDb13v59sqFAmJafeZTuFR.png\"},{\"id\":\"94ba4fa4-aed7-482e-8096-f61090d5bb4d\",\"name\":\"Nicole Terc\",\"position\":\"Android Tech Lead @ HubSpot\",\"description\":\"Android GDE, Boardgame lover, videogame addict and origami enthusiast, Nicole self taught herself to code and has been fooling around with the Android ecosystem for more than 10 years. She has participated in a diverse variety of projects for several clients around the world, including video streaming, news, social media and public transport applications. Regardless of what the current adventures have taken her, she loves finding time to play with new things and share her experience :)\",\"photoUrl\":\"https://sessionize.com/image/ac6b-400o400o1-G9xcJMvyiQXy5uEyUthvFx.jpg\"},{\"id\":\"ffcac92c-d9e9-48e9-8de0-4e4e684c58e2\",\"name\":\"Nikita Koval\",\"position\":\"Researcher at JetBrains\",\"description\":\"Nikita is a researcher in the Kotlin team at JetBrains and works on a PhD in the field of concurrency at the same time. His primary research interests are concurrent data structures and algorithms, their verification, and practically applicable code analysis. Here you can find all the recent information about me and my projects.\\r\\n\\r\\nhttps://nikitakoval.org\",\"photoUrl\":\"https://sessionize.com/image/7605-400o400o1-f4wHmg583xtyv1DzdsewJf.jpg\"},{\"id\":\"1d007157-b8e7-439b-9c88-6db97e0505d3\",\"name\":\"Nikita Nazarov\",\"position\":\"Google LLC\",\"description\":\"Hi! \\r\\nMy name is Nikita Nazarov! \\r\\n\\r\\nLinkedIn: https://www.linkedin.com/in/nikita-nazarov-694762234/\\r\\n\\r\\nGitHub: https://github.com/nikita-nazarov\\r\\n\\r\\nI used to work at JetBrains in the Kotlin plugin team for a couple of years fixing issues and bringing new features to the Kotlin debugger. There I interacted with the coroutine debugger a lot and put in many effort to making it faster and more useful. These days I work at the Kotlin compiler team at Google, where we are working on improving the compiler and various Kotlin tooling including the coroutine debugger as well. I'm also the author of the Coroutine Stacks (https://github.com/nikita-nazarov/coroutine-stacks) Intellij plugin that allows rendering coroutine traces in a similar way to how it is done in the Parallel Stacks feature of the JetBrains rider IDE. \",\"photoUrl\":\"https://sessionize.com/image/d6c9-400o400o1-fKjGBatwVJuaZ5DB9xKrH6.jpeg\"},{\"id\":\"c00571fe-610a-42d5-9eb5-2db19f330650\",\"name\":\"Oliver Okrongli\",\"position\":\"Multiplatform Software at infix\",\"description\":\"Oliver is an experienced developer and has been shaping and creating software from backend to frontends. He loves the productivity of working with Kotlin Multiplatform and has contributed to several libraries of the Kotlin ecosystem as well as the Kotlin compiler. Can be found on GitHub (OliverO2) and the kotlinlang Slack (Oliver O).\\r\\n\\r\\nWhen not developing, he is most probably in deep talks, dancing, snowboarding or F18 catamaran sailing whenever he gets a chance.\",\"photoUrl\":\"https://sessionize.com/image/cc60-400o400o1-Dr86YBCXZYiyqiazR9KLRq.jpg\"},{\"id\":\"62216efe-dd8b-4d8b-9800-1d51b57c4001\",\"name\":\"Pamela Hill\",\"position\":\"Developer Advocate at JetBrains\",\"description\":\"Pamela is a Developer Advocate for Kotlin Multiplatform at JetBrains and has more than 20 years of experience writing desktop, web and mobile apps. \",\"photoUrl\":\"https://sessionize.com/image/2102-400o400o1-Dbh3jNbrkDNdSH1q1zAJmr.png\"},{\"id\":\"4029e453-72f6-473f-bb08-e3ad5da66f84\",\"name\":\"Parthasarathy Muruganandam\",\"position\":\"Mobile Developer, Instabee\",\"description\":\"Android Enthusiast, enjoying AOSP and open source, 5+ years of experience as Android Developer.\",\"photoUrl\":\"https://sessionize.com/image/aa4a-400o400o1-Sx6G5s3We7F7feJrqfcDJL.jpg\"},{\"id\":\"ebc612d5-a764-46b6-8524-0adb9638dd5c\",\"name\":\"Paul Merlin\",\"position\":\"Gradle Build Tool Principal Software Engineer\",\"description\":\"Paul is an experienced, self-made, software engineer with a wide knowledge ranging from computers, network security and architectures to high-level programming langages, domain modeling and cryptography. 45 years old, hobbyist at 7 already, Paul professionally started to build softwares in 2000.\\r\\n\\r\\nHe joined the Gradle team height years ago, on time for 2.14, participated to the big performance efforts that went into the 3.x and 4.x versions, lead the Gradle Kotlin DSL and Configuration Cache teams since then and is now working on making Gradle more declarative.\",\"photoUrl\":\"https://sessionize.com/image/197d-400o400o1-d9150054-6421-47e5-882c-9670e41d611c.jpg\"},{\"id\":\"d3841a2b-b09c-41f7-afa6-26734c05a277\",\"name\":\"Paulina Sadowska\",\"position\":\"Engineering Manager | Senior Mobile Software Engineer @ Allegro\",\"description\":\"I'm the Engineering Manager at Allegro, Poland's biggest online marketplace. My team creates an in-house Server-Side UI platform (MBox) which aims to make mobile development fast and scalable. \\r\\nI share my insights on Android development on my YouTube channel (@PaulinaTalksAndroid) and blog (medium.com/@PaulinaSadowska).\",\"photoUrl\":\"https://sessionize.com/image/f642-400o400o1-VVmAq39BYZX4chCP42iPxH.png\"},{\"id\":\"161fd433-2422-4a4d-8320-9e34aee8df1e\",\"name\":\"Pim van Gurp\",\"position\":\"Kotlin Software Engineer\",\"description\":\"Fan of idiomatic Kotlin, quality software architecture and finding entrepreneurial opportunities that can be highly automated.\",\"photoUrl\":\"https://sessionize.com/image/e8de-400o400o1-RbGzx1oAGWy4dKVfpNq6BH.jpg\"},{\"id\":\"222381fc-4c18-4996-90f0-19cc72243c88\",\"name\":\"Rafael Roman\",\"position\":\"Principal Engineer at Personio\",\"description\":\"Principal Engineer with over 15 years of experience leading teams and delivering presentations on technical topics. Skilled in developing and implementing innovative solutions, as well as driving team collaboration and productivity. Strong communication skills and experience presenting to both technical and non-technical audiences. Committed to staying up-to-date on industry trends and best practices.\",\"photoUrl\":\"https://sessionize.com/image/a6e0-400o400o1-49bnT1tVpfQKyiCF6YCk7b.jpg\"},{\"id\":\"9caa9624-350a-4e69-8ac4-88db14bdb5bf\",\"name\":\"Rahul Ravikumar\",\"position\":\"Software Engineer at Google\",\"description\":\"Software Engineer on the Android Toolkit team. \",\"photoUrl\":\"https://sessionize.com/image/ef9a-400o400o1-019901dd-fc75-4fef-a9b7-cece6452c414.jpg\"},{\"id\":\"b1a17a8e-db4d-4046-b2e6-34a3608a33f1\",\"name\":\"Roman Belov\",\"position\":\"Kotlin for Data Science, JetBrains\",\"description\":\"Present:\\r\\nSoftware Developer @ Kotlin for Data Science\\r\\nPreviously:\\r\\nMarketing Manager @ Kotlin\\r\\nSoftware Developer @ dotMemory\\r\\n\\r\\n\",\"photoUrl\":\"https://sessionize.com/image/08c7-400o400o1-8e-db4d-4046-b2e6-34a3608a33f1.7bcf1fbc-7d4f-49c0-820d-0dfd86e50885.png\"},{\"id\":\"7b42f61c-5e49-45ac-96a7-5d6fb0391ebd\",\"name\":\"Ross Tate\",\"position\":\"Programming-Languages Researcher and Consultant\",\"description\":\"I am an independent researcher and consultant on programming-language design and implementation, currently working with the Kotlin language team. Before going independent, I was a professor at Cornell University, and I worked with the Kotlin team in its early days to integrate my research on mixed-site variance and gradual types into what became platform types. Beyond Kotlin, I have contributed to the designs of Java, Scala, Ceylon, Julia, and WebAssembly.\",\"photoUrl\":\"https://sessionize.com/image/04b2-400o400o1-LrwU8Xjrw5ENqKcZVRn1yF.jpg\"},{\"id\":\"24586433-c018-4271-bf89-43bae78dfa77\",\"name\":\"Salomon Brys\",\"position\":\"Kodein Koders\",\"description\":\"Salomon is the creator and maintainer of the KODEIN multiplatform open source initiative as well as the founder of KODEIN Koders.\\r\\nDeeply rooted in the Open-Source philosophy, he is dedicated to making tools and libraries to make programming easier, safer, and more exciting.\\r\\nHe is a Kotlin GDE, Kotlin certified trainer, Kotlin meetup Paris co-organiser, and conference speaker (you guessed it... about Kotlin!).\\r\\nHe also loves dancing Rock, playing boardgames, and flying small planes.\",\"photoUrl\":\"https://sessionize.com/image/3920-400o400o1-naVWkegcMUGyAxHht3ncYC.JPG\"},{\"id\":\"dd32d92b-40e8-4dcf-a29c-a66ec2473b6f\",\"name\":\"Sam Edwards\",\"position\":\"Android Foundation @ Square\",\"description\":\"Sam has been sharing his knowledge on software development through talks, post, open source and screencasts and is recognized as a Google Developer Expert (GDE) for Android and Kotlin. He has a passion for creating high quality software, learning from the community and sharing back his experiences. He's been working with Android for 13 years and and has 19 years of professional experience with software development. Check out https://handstandsam.com where he shares tips and tricks about Android and Kotlin development.\",\"photoUrl\":\"https://sessionize.com/image/a7b3-400o400o1-haYJLaj7j8kgFiRuBSVQzC.png\"},{\"id\":\"a82c6942-6e2b-4d80-9883-0b84b932d6ef\",\"name\":\"Sebastian Aigner\",\"position\":\"Developer Advocate at JetBrains\",\"description\":\"As a Kotlin and Compose Multiplatform Developer Advocate at JetBrains, Sebastian spends a lot of time thinking about how technology can advance and inspire people. When he first tried Kotlin, it was love at first sight. He is one of the hosts of the Talking Kotlin podcast, and creates videos for the official Kotlin YouTube channel. Sebastian loves to develop networked applications, uses Kotlin on a variety of platforms, and passionately tinkers on his programs until late into the night.\",\"photoUrl\":\"https://sessionize.com/image/2ef9-400o400o1-XGxKBoqZvxxQxosrZHQHTT.png\"},{\"id\":\"48310f7e-7f48-45f5-a2e6-91550fe78c0c\",\"name\":\"Simon Billingsley\",\"position\":\"Lead Developer at Kody\",\"description\":\"I am a seasoned server-side Java developer who has been working with Kotlin in the financial services industry for the past 3 years.\",\"photoUrl\":\"https://sessionize.com/image/010f-400o400o1-sciZnZpWf6B8CKZD969XEB.jpg\"},{\"id\":\"e2f202a0-595e-42d4-921c-f94433fa68e5\",\"name\":\"Simon Ogorodnik\",\"position\":\"DevLead @ Kotlin Compiler, JetBrains\",\"description\":\"Simon Ogorodnik is a member of the Kotlin team at JetBrains. He started his journey in the Kotlin IDE team when he was just 18 years old and has since advanced to the position of Development Lead for the Kotlin Compiler. Previously, he led the K2 project as its TechLead. In his early days with the IDE team, he initiated the new J2K (Java2Kotlin converter), maintained Dokka, and made several performance optimization efforts.\",\"photoUrl\":\"https://sessionize.com/image/a259-400o400o1-GPbq7REKVyXxCf8pBbzMS2.jpg\"},{\"id\":\"ea32e9a2-b68e-44c5-b4b7-6d2aa0dc3141\",\"name\":\"Simon Vergauwen\",\"position\":\"Principal Engineer at Xebia & Arrow (OSS) Maintainer\",\"description\":\"Software engineer from Antwerp, Belgium. Interested in everything functional, and Kotlin. Loves OSS, snowboarding and Fallout.\",\"photoUrl\":\"https://sessionize.com/image/6718-400o400o1-fjw7kgxgtgQxuPy5N8d4np.png\"},{\"id\":\"7ad82c43-738a-4d09-9032-2fafb26f6858\",\"name\":\"Stanislav Erokhin\",\"position\":\"Kotlin Compiler Lead @ JetBrains\",\"description\":\"Stanislav has been part of the Kotlin team at JetBrains for over ten years and now leads the compiler development. His notable achievements include playing a crucial role in advancing Kotlin Multiplatform (KMP) from Beta to Stable. Early in his Kotlin career, he worked on developing the resolution and inference algorithm in the Kotlin front-end.\",\"photoUrl\":\"https://sessionize.com/image/017d-400o400o1-fd6EFEJNJn32RTMi8UqnNv.png\"},{\"id\":\"f296664b-274f-4e11-90a4-b632afab99cc\",\"name\":\"Sterling Greene\",\"position\":\"Senior Lead Software Engineer\",\"description\":\"Sterling Greene is a Senior Lead Software Engineer for Gradle. He has helped lead transformative change in large organizations to improve software quality, delivery speed and development costs. Recently, he has been focused on making Gradle easier to use. When he’s not working on Gradle, he spends time making pizzas for his family.\",\"photoUrl\":\"https://sessionize.com/image/e27a-400o400o1-GF1Cjoc77ynUQqLPkEZpj.jpeg\"},{\"id\":\"265b1a56-e32c-459d-8580-6d0d4ed5fc63\",\"name\":\"Sumayyah Ahmed\",\"position\":\"Android Tech Lead at Square\",\"description\":\"Sumayyah has been building Android apps since 2013, and still loves it! She likes digging deep into how Android works, and how to keep production codebases flexible, scalable, and clean. In fact, she spends a lot of time building talks around those exact topics. She currently works at Square, leading engineering teams and thinking about architecture. \",\"photoUrl\":\"https://sessionize.com/image/e736-400o400o1-0949bc8a-30dd-421d-8781-40cc5f77346f.jpg\"},{\"id\":\"0f769b19-d5f2-49fb-aa78-a086aa046b7e\",\"name\":\"Svetlana Isakova\",\"position\":\"Developer Advocate, JetBrains\",\"description\":\"Svetlana Isakova has worked on the Kotlin language at JetBrains. She’s co-authored the book Kotlin in Action and now is a Developer Advocate, where she spends her time teaching Kotlin and speaking at conferences worldwide. \",\"photoUrl\":\"https://sessionize.com/image/5daa-400o400o1-9juRv43WFGQcGhJ31eGWsE.jpg\"},{\"id\":\"969813cd-0231-4310-9c61-745967bd94c5\",\"name\":\"Tadeas Kriz\",\"position\":\"Senior Kotlin Developer at Touchlab\",\"description\":\"Tadeas is a Senior Kotlin Developer at Touchlab, experimenting with Kotlin's compiler plugins. Began as a PHP developer, moving to .NET desktop apps later on. Finally landing in mobile development with Android first and then falling in love with iOS. Fortunately, Kotlin Multiplatform happened, opening the path to doing both mobile platforms. Do NOT feed after midnight!\",\"photoUrl\":\"https://sessionize.com/image/8dd1-400o400o1-RW6sTdV194VWGAsCKa7PYE.jpg\"},{\"id\":\"ce5f643d-771a-4b14-b504-329c50924cc3\",\"name\":\"Tarik Eshaq\",\"position\":\"Senior Software Engineer - Mozilla\",\"description\":\"I've worked at Mozilla for over 2 years. At Mozilla, I write software that powers Firefox Sync and Firefox Accounts in Firefox for Android, Firefox for iOS and Firefox Desktop.\\r\\n\\r\\nI've spent a long time writing cross-platform Rust that ships to the client on the user's devices but I have also worked on the backend systems that enable authentication and authorization to a user's data. \",\"photoUrl\":\"https://sessionize.com/image/1b76-400o400o1-N33BF6nqfj3T2zazDrJtu5.jpg\"},{\"id\":\"b18a2e1f-3904-48e8-b0bb-45b3942ebc69\",\"name\":\"Thomas Künneth\",\"position\":\"Senior Android Developer @snappmobile_io\",\"description\":\"Thomas fell in love with Android in 2009. He has been constantly contributing to the community since then. Thomas loves writing books (four titles, 15 editions) and articles. He enjoys speaking at conferences and meetups. Thomas' first encounter with programming was in the era of home computers during the early 1980s. Later came C, Perl and a few more. During the 90s he wrote a bunch of programs for the Atari ST series. The first decade of Thomas' professional career centered around Java Enterprise. Today it’s all things Android and Kotlin.\",\"photoUrl\":\"https://sessionize.com/image/6833-400o400o1-XnzKp9ZD3bUWUGVhTAUdti.png\"},{\"id\":\"d4d861f4-0319-49d3-8ca1-7778cd2fb6dc\",\"name\":\"Tor Norbye\",\"position\":\"Android Studio Engineering Director\",\"description\":\"Tor Norbye is the engineering director for Android Studio at Google, and has worked on many of the features in the IDE (and is also the initial author of Android Lint.)\",\"photoUrl\":\"https://sessionize.com/image/1d68-400o400o1-wVMTxzmVferaYKgJq52J6k.jpg\"},{\"id\":\"6a3de662-ef86-4c62-bb68-2f7ebe607f76\",\"name\":\"Ty Smith\",\"position\":\"Principal Engineer at Uber, Mobile Platform\",\"description\":\"Ty is a Principal Engineer at Uber where he leads the Mobile Platform group and is the chairman of Uber's Open-Source program. He has a passion for tools, frameworks, and open-source to help developers make great mobile apps. He is a Google Developer Expert for Android and Kotlin, engaging regularly with the community through conferences, open-source, and writing, as well as an organizer for conferences and meetups. He is an angel investor and tech advisor, as well as a member in multiple venture capital advisory syndicates. Ty has been at Uber for 6 years and prior to that he worked at Twitter on the Fabric developer tools, Evernote, and a variety of smaller startups and consulting firms\",\"photoUrl\":\"https://sessionize.com/image/b693-400o400o1-YapSn4nbXFLtK5vNm8KKrA.jpg\"},{\"id\":\"7df2c791-134f-4279-bb68-23f8899bb1ac\",\"name\":\"Urs Peter\",\"position\":\"Urs Peter Senior Software Engineer and JetBrains certified Kotlin Trainer \",\"description\":\"Urs is a seasoned software engineer, solution architect, conference speaker, and trainer with over 20 years of experience in building resilient, scalable, and mission-critical systems, mostly involving Kotlin and Scala. Besides his job as a consultant, he is also a passionate trainer and author of a great variety of courses ranging from language courses for Kotlin and Scala to architectural trainings such as Microservices and Event-Driven Architectures. As a people person by nature, he loves to share knowledge and inspire and get inspired by peers on meetups and conferences. Urs is a JetBrains certified Kotlin trainer.\",\"photoUrl\":\"https://sessionize.com/image/a3f7-400o400o1-QYUavRYyARnAVJLCpM1m8M.png\"},{\"id\":\"cb316e0e-8407-472b-bdb6-bfa4291cc3dd\",\"name\":\"Vitaly Bragilevsky\",\"position\":\"Developer Advocate at JetBrains\",\"description\":\"I'm a developer advocate at JetBrains. I taught more than a dozen programming languages and other Computer Science topics at universities for more than 20 years. I authored \\\"Haskell in Depth\\\", published by Manning Publications in 2021.\",\"photoUrl\":\"https://sessionize.com/image/f5cf-400o400o1-0e-8407-472b-bdb6-bfa4291cc3dd.716516cd-51c0-47ff-b208-e8ddd9cd2285.jpg\"},{\"id\":\"7bbb257c-a5db-4e6f-8769-03dd0a7fe522\",\"name\":\"Vladislav Tankov\",\"position\":\"JetBrains, Software Developer\",\"description\":\"Lead of JetBrains AI.\\r\\n\\r\\nAt JetBrains, has created JetBrains AI, Grazie and Kotless (Kotlin serverless framework).\\r\\n\\r\\nA big enthusiast of Kotlin and has created numerous libraries for it.\\r\\n\",\"photoUrl\":\"https://sessionize.com/image/3e00-400o400o1-WRdFavXWFRXjDwtgAgkPhV.jpg\"},{\"id\":\"b2a19517-6d18-4ec1-9c40-7e29f4d862b1\",\"name\":\"Vsevolod Tolstopyatov\",\"position\":\"Kotlin Core Ecosystem Lead @ JetBrains\",\"description\":\"Having fun in Kotlin team, poking APIs, libraries, languages, and tools. Passionate and curious about API design, concurrency, low-level programming, and performance.\",\"photoUrl\":\"https://sessionize.com/image/b108-400o400o1-wPAB1xRYf8Sc7XcfrdjnHa.png\"},{\"id\":\"2b198f3a-5df1-4c1f-ba0c-2f3f4f25f1bd\",\"name\":\"Yiğit Boyar\",\"position\":\"Android/ Google\",\"description\":\"Yigit leads the Architecture Components for Android, focusing on the developer experience and dreams of making app development easy. Prior to Google, he was the Android engineering manager at Path.com. He received his B.S. in Computer Engineering from Middle East Technical University / Turkey.\\r\\n\\r\\nHe is most proud of being the first person to use Kotlin in the Android codebase in 2014!\\r\\n\",\"photoUrl\":\"https://sessionize.com/image/a866-400o400o1-3a-5df1-4c1f-ba0c-2f3f4f25f1bd.1269928d-52fc-4815-bff5-3e56bbb8901b.jpg\"},{\"id\":\"12a549cb-145e-4d13-8bb3-ccfe162200a3\",\"name\":\"Zalim Bashorov\",\"position\":\"Leading Kotlin/Wasm to the Moon at JetBrains\",\"description\":\"I’ve been writing Kotlin in Kotlin at JetBrains for more than 10 years. Now I'm leading the Kotlin/Wasm team. Interested in compilers, interpreters, and VMs.\",\"photoUrl\":\"https://sessionize.com/image/a9f8-400o400o1-W2szZhZ3hV6RAkqAK2oC4W.png\"}]}","favorites":"[\"616761\"]","notificationsAllowed":"false"}} \ No newline at end of file diff --git a/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/Filters.kt b/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/Filters.kt index cfc1abd4..1748d5e8 100644 --- a/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/Filters.kt +++ b/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/Filters.kt @@ -46,17 +46,19 @@ import org.jetbrains.compose.ui.tooling.preview.Preview import org.jetbrains.kotlinconf.ui.theme.KotlinConfTheme import org.jetbrains.kotlinconf.ui.theme.PreviewHelper +enum class FilterItemType { + Category, Level, Format, +} + data class FilterItem( - val id: Int, + val type: FilterItemType, val value: String, val isSelected: Boolean, ) @Composable fun Filters( - categories: List, - levels: List, - sessionFormats: List, + tags: List, toggleItem: (FilterItem, Boolean) -> Unit, modifier: Modifier = Modifier, ) { @@ -105,11 +107,7 @@ fun Filters( .clip(CircleShape) .background(KotlinConfTheme.colors.primaryBackground) ) { - val count = remember(categories, levels, sessionFormats) { - categories.count { it.isSelected } + - levels.count { it.isSelected } + - sessionFormats.count { it.isSelected } - } + val count = remember(tags) { tags.count { it.isSelected } } StyledText( text = count.toString(), color = KotlinConfTheme.colors.primaryTextInverted, @@ -129,9 +127,25 @@ fun Filters( verticalArrangement = Arrangement.spacedBy(8.dp), modifier = Modifier.padding(12.dp), ) { - FilterItemGroup(stringResource(Res.string.filter_label_category), categories, toggleItem) - FilterItemGroup(stringResource(Res.string.filter_label_level), levels, toggleItem) - FilterItemGroup(stringResource(Res.string.filter_label_session_format), sessionFormats, toggleItem) + val categories = tags.filter { it.type == FilterItemType.Category } + val levels = tags.filter { it.type == FilterItemType.Level } + val formats = tags.filter { it.type == FilterItemType.Format } + + FilterItemGroup( + stringResource(Res.string.filter_label_category), + categories, + toggleItem, + ) + FilterItemGroup( + stringResource(Res.string.filter_label_level), + levels, + toggleItem, + ) + FilterItemGroup( + stringResource(Res.string.filter_label_session_format), + formats, + toggleItem, + ) } } } @@ -173,40 +187,28 @@ private fun FilterItemGroup( @Composable internal fun FiltersPreview() { PreviewHelper { - val categories = remember { - mutableStateListOf( - FilterItem(1, "Server-side", false), - FilterItem(2, "Multiplatform", false), - FilterItem(3, "Android", false), - FilterItem(4, "Extensibility/Tooling", false), - FilterItem(5, "Languages and Best Practices", false), - FilterItem(6, "Other", false), - ) - } - val levels = remember { - mutableStateListOf( - FilterItem(11, "Introductory and overview", false), - FilterItem(12, "Intermediate", false), - FilterItem(13, "Advanced", false), - ) - } - val sessionFormats = remember { + val tags = remember { mutableStateListOf( - FilterItem(21, "Workshop", false), - FilterItem(22, "Regular session", false), - FilterItem(23, "Lightning session", false), + FilterItem(FilterItemType.Category, "Server-side", false), + FilterItem(FilterItemType.Category, "Multiplatform", false), + FilterItem(FilterItemType.Category, "Android", false), + FilterItem(FilterItemType.Category, "Extensibility/Tooling", false), + FilterItem(FilterItemType.Category, "Languages and Best Practices", false), + FilterItem(FilterItemType.Category, "Other", false), + FilterItem(FilterItemType.Level, "Introductory and overview", false), + FilterItem(FilterItemType.Level, "Intermediate", false), + FilterItem(FilterItemType.Level, "Advanced", false), + FilterItem(FilterItemType.Format, "Workshop", false), + FilterItem(FilterItemType.Format, "Regular session", false), + FilterItem(FilterItemType.Format, "Lightning session", false), ) } Filters( - categories = categories, - levels = levels, - sessionFormats = sessionFormats, + tags = tags, toggleItem = { item, value -> val newItem = item.copy(isSelected = value) - categories.replace(item, newItem) - levels.replace(item, newItem) - sessionFormats.replace(item, newItem) + tags.replace(item, newItem) } ) } diff --git a/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/Switcher.kt b/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/Switcher.kt index fec9b23a..452a1351 100644 --- a/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/Switcher.kt +++ b/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/Switcher.kt @@ -4,7 +4,6 @@ import androidx.compose.animation.animateColorAsState import androidx.compose.foundation.background import androidx.compose.foundation.border import androidx.compose.foundation.clickable -import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Row @@ -50,7 +49,7 @@ private fun SwitcherItem( Box( modifier = modifier - .heightIn(max = 40.dp) + .heightIn(min = 40.dp) .clip(SwitcherItemShape) .border( width = 2.dp, diff --git a/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/TalkCard.kt b/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/TalkCard.kt index 0f42c547..6109ce2e 100644 --- a/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/TalkCard.kt +++ b/ui-components/src/commonMain/kotlin/org/jetbrains/kotlinconf/ui/components/TalkCard.kt @@ -10,6 +10,8 @@ import androidx.compose.animation.fadeOut import androidx.compose.animation.togetherWith import androidx.compose.foundation.background import androidx.compose.foundation.border +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ExperimentalLayoutApi @@ -32,6 +34,7 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.graphics.Color @@ -90,7 +93,7 @@ fun TalkCard( bookmarked: Boolean, onBookmark: (Boolean) -> Unit, tags: List, - selectedTags: List, + tagHighlights: List, speakers: String, speakerHighlights: List, location: String, @@ -100,6 +103,7 @@ fun TalkCard( status: TalkStatus, onSubmitFeedback: (Emotion?) -> Unit, onSubmitFeedbackWithComment: (Emotion, String) -> Unit, + onClick: () -> Unit, modifier: Modifier = Modifier, ) { val backgroundColor by animateColorAsState( @@ -118,7 +122,13 @@ fun TalkCard( color = KotlinConfTheme.colors.strokePale, shape = CardTalkShape, ) - .background(backgroundColor, CardTalkShape) + .clip(CardTalkShape) + .clickable( + onClick = onClick, + indication = null, + interactionSource = remember { MutableInteractionSource() }, + ) + .background(backgroundColor) ) { TopBlock( title = title, @@ -127,7 +137,7 @@ fun TalkCard( bookmarked = bookmarked, onBookmark = onBookmark, tags = tags, - selectedTags = selectedTags, + selectedTags = tagHighlights, speakers = speakers, speakerHighlights = speakerHighlights, ) @@ -297,7 +307,7 @@ private fun FeedbackBlock( targetState = selectedEmotion != null, transitionSpec = { fadeIn(tween(FeedbackAnimationDuration)) togetherWith - fadeOut(tween(FeedbackAnimationDuration)) + fadeOut(tween(FeedbackAnimationDuration)) }, modifier = Modifier.fillMaxHeight(), contentAlignment = Alignment.CenterStart, @@ -373,7 +383,7 @@ internal fun TalkCardPreview() { "Workshop", "Kotlin", "Coroutines", "Multiplatform", "Label", "Label", "Label", "Label", "Label", ), - selectedTags = listOf( + tagHighlights = listOf( "Kotlin", "Multiplatform", ), speakers = "Sebastian Aigner, Vsevolod Tolstopyatov", @@ -385,6 +395,7 @@ internal fun TalkCardPreview() { status = TalkStatus.Now, onSubmitFeedbackWithComment = { e, s -> println("Feedback, emotion + comment: $e, $s") }, onSubmitFeedback = { e -> println("Feedback, emotion only: $e") }, + onClick = { "Clicked session" }, modifier = Modifier.weight(1f), ) Spacer(Modifier.width(16.dp)) @@ -397,7 +408,7 @@ internal fun TalkCardPreview() { "Workshop", "Kotlin", "Coroutines", "Multiplatform", "Label", "Label", "Label", "Label", "Label", ), - selectedTags = listOf(), + tagHighlights = listOf(), speakers = "Sebastian Aigner, Vsevolod Tolstopyatov", speakerHighlights = emptyList(), location = "Auditorium 14", @@ -407,6 +418,7 @@ internal fun TalkCardPreview() { status = TalkStatus.Upcoming, onSubmitFeedbackWithComment = { e, s -> println("Feedback, emotion + comment: $e, $s") }, onSubmitFeedback = { e -> println("Feedback, emotion only: $e") }, + onClick = { "Clicked session" }, modifier = Modifier.weight(1f), ) }