Upgrade to Pro — share decks privately, control downloads, hide ads and more …

An Android, a Desktop, and a Web developer ente...

cmota
October 07, 2021

An Android, a Desktop, and a Web developer enter in a bar

Three different platforms meet at a bar and decided to share (pun intended) a couple of drinks.

This last year has been great for multiplatform development. As Kotlin keeps pushing for new releases and KMP starts to gain more adoption and stable releases, we now have the chance to write the UI for our Android apps with Compose and share it along with the Desktop and the Web.

In this talk, you’re going to see how you can start to decompose your Android app and start sharing all of its content along with a Desktop app and the Web. Drink at your own responsibility.

cmota

October 07, 2021
Tweet

More Decks by cmota

Other Decks in Technology

Transcript

  1. @cafonsomota An Android, A Desktop, and A Web Developer enter

    in a Bar Photo by Alexander Popov on Unsplash
  2. Photo by Alexander Popov on Unsplash An Android, A Desktop,

    and A Web Developer enter in a Bar *following all the public health measures @cafonsomota
  3. 👨💻 Android GDE 🗣 Founder @GDGCoimbra and co-founder @Kotlin_Knights ✍

    Author @rwenderlich 🗺 Loves travel, photography and running 🍻 Looking to taste a Zywiec Biale with all of you hello mobiconf! 👋 @cafonsomota
  4. 💬 How we built a Jetpack Compose Chat SDK, by

    Filip Babić 📱 KMP for Mobile Developers, by Enrique López Mañas Mobiconf talks @cafonsomota
  5. 2008 2012 2018 2013 2011 2017 2006 2010 2009 2015

    * Kotlin Multiplatform * @cafonsomota Mobile
  6. 2008 2012 2018 2014 2017 2006 2010 2009 2015 *

    @cafonsomota * Kotlin Multiplatform Web
  7. @cafonsomota Great!! Are you going to do it natively? I’ve

    got a new app idea! droiders 🤖 📱
  8. @cafonsomota Great!! Are you going to do it natively? I’ve

    got a new app idea! droiders 🤖 📱 Natively? You can use Xamarin and instead of android only, you get android and iOS
  9. @cafonsomota Great!! Are you going to do it natively? I’ve

    got a new app idea! droiders 🤖 📱 Natively? You can use Xamarin and instead of android only, you get android and iOS For that, you should use Flutter! It has better performance!
  10. @cafonsomota Great!! Are you going to do it natively? I’ve

    got a new app idea! droiders 🤖 📱 Natively? You can use Xamarin and instead of android only, you get android and iOS For that, you should use Flutter! It has better performance! But it uses Dart! You’re already familiar with Kotlin, you should try Kotlin Multiplatform!
  11. @cafonsomota Great!! Are you going to do it natively? I’ve

    got a new app idea! droiders 🤖 📱 Natively? You can use Xamarin and instead of android only, you get android and iOS For that, you should use Flutter! It has better performance! But it uses Dart! You’re already familiar with Kotlin, you should try Kotlin Multiplatform! I’ve been using react native and it’s great!
  12. @cafonsomota Great!! Are you going to do it natively? I’ve

    got a new app idea! droiders 🤖 📱 Natively? You can use Xamarin and instead of android only, you get android and iOS For that, you should use Flutter! It has better performance! But it uses Dart! You’re already familiar with Kotlin, you should try Kotlin Multiplatform! I’ve been using react native and it’s great! 12 people are typing
  13. How to decide? Team background and size Which language is

    your team familiar with? Do they want to learn new things? Can you have developers focused on each platform you’re targeting? Project type Are you developing an MVP? 1yr long project? 5yr? Never ending project? Constraints Time: It hasn’t started yet, and you’re already behind schedule? Budget: Can you hire/allocate more people? @cafonsomota
  14. Framework dependent OS updates require the fw to be updated

    and launch a new app Missing features OS/device features depend on the fw support, you might need to write them Slower performance Commitment to one framework Common disadvantages @cafonsomota
  15. It’s Kotlin ❤ Take advantage of all the language features

    (that you’re already familiar with) Low risk Decide what’s worth to share across platforms Consistency across platforms One tech-stack Strong community support KOtlin Multiplatform @cafonsomota
  16. presentation model parser view network presentation model parser view network

    presentation model parser view network presentation model parser view network desktop web iOS android @cafonsomota
  17. business logic business logic business logic model parser network presentation

    model parser network presentation model parser network presentation model parser network presentation business logic view view view view desktop web iOS android @cafonsomota
  18. android iOS desktop model parser network presentation common view view

    view view java/kotlin objective-c/ swift (kotlin) JS supported in jvm web @cafonsomota
  19. src/commonMain/sample/Platform.kt :shared @cafonsomota expect object Platform { val name: String

    } You need to de fi ne actual per target actual for Android actual for Desktop actual for JS Kotlin Multiplatform: Platform Specific Code
  20. src/commonMain/sample/Platform.kt :shared @cafonsomota expect object Platform { val name: String

    } src/androidMain/sample/Platform.kt actual object Platform { actual val name: String = "android" } Kotlin Multiplatform: Platform Specific Code
  21. src/commonMain/sample/Platform.kt :shared @cafonsomota expect object Platform { val name: String

    } src/androidMain/sample/Platform.kt actual object Platform { actual val name: String = “android” } Kotlin Multiplatform: Platform Specific Code
  22. src/commonMain/sample/Platform.kt :shared @cafonsomota expect object Platform { val name: String

    } src/androidMain/sample/Platform.kt src/desktopMain/sample/Platform.kt src/webMain/sample/Platform.kt actual object Platform { actual val name: String = “android” } actual object Platform { actual val name: String = “desktop” } actual object Platform { actual val name: String = “web” } Kotlin Multiplatform: Platform Specific Code
  23. *.kt common expect JVM actual *.kt, *.java, *.jar Native *.kt,

    *C, Swift, Framework JS *.kt, *.js, NPM actual actual
  24. Jetpack Compose compose.animation compose.material compose.foundation compose.ui compose.runtime compose.compiler Compose Compiler

    Compose Runtime Compose UI Toolkit (Android) Compose Animation Compose UI Compose Foundation Compose Material
  25. Jetpack Compose compose.animation compose.material compose.foundation compose.ui compose.runtime compose.compiler Compose Compiler

    Compose Runtime Compose UI Toolkit (Android) Compose Animation Compose UI Compose Foundation Compose Material
  26. Compose Compiler Compose Runtime Compose UI Toolkit (Android) Compose Animation

    Compose UI Compose Foundation Compose Material Compose compiler android.googlesource.com/platform/frameworks/support/+/HEAD/compose/compiler Written in Kotlin Transforms @Composable into UI Doesn’t use the Annotation Processor The plugin works at system/code generation level Doesn’t impact build times Open source Available in the AOSP
  27. Compose Runtime Platform agnostic Doesn’t know what Android or UI

    are Tree management solution Compose Compiler Compose Runtime Compose UI Toolkit (Android) Compose Animation Compose UI Compose Foundation Compose Material
  28. Compose UI Toolkit Compose Compiler Compose Runtime Compose UI Toolkit

    (Android) Compose Animation Compose UI Compose Foundation Compose Material compose.ui Handles input management, Drawing, Layouts, etc. compose.foundation Contains Basic building: Column, Text, Image, etc. compose.material Material design system to use on components compose.animation Animations to use easily and out side of the box
  29. Compose UI Raspberry pi Compose Compiler Compose Runtime Compose UI

    Android Compose UI Desktop Compose UI Web Compose UI Console Compose
  30. Now that we’ve got the android app ready, How quickly

    can we have desktop and web apps? - all the dreamers out there
  31. @cafonsomota SELECT YOUR LEVEL I just want to see the

    story. I want a lighter experience. Give me the full challenge!
  32. @cafonsomota SELECT YOUR LEVEL I just want to see the

    story. I want a lighter experience. Give me the full challenge! 👉
  33. @cafonsomota SELECT YOUR LEVEL I just want to see the

    story. I want a lighter experience. Give me the full challenge! 👉
  34. @cafonsomota SELECT YOUR LEVEL I just want to see the

    story. I want a lighter experience. Give me the full challenge! 👉
  35. KOtlin Multiplatform: Targets @cafonsomota jvm JS android android 
 NDK

    iOS watchOS tvOS macOS Linux Windows Web Assembly
  36. KOtlin Multiplatform: Libraries @cafonsomota Kotlinx.x Coroutines, serialization, datetime, atomicfu, etc.

    Network Ktor: github.com/ktorio/ktor Storage Database: github.com/cashapp/sqldelight Others Curated list: github.com/AAkira/Kotlin-Multiplatform-Libraries
  37. @cafonsomota KOtlin Multiplatform: Creating a new KMM project 1. Install

    the KMM plugin on Android Studio 2. Create a new KMM Application ⚠ There’s a version that supports Mac M1 :shared
  38. androidApp/ desktopApp/ webApp/ shared/ @cafonsomota KOtlin Multiplatform: Project Structure your

    common code (logic) androidMain/ commonMain/ desktopMain/ jsMain/ :shared
  39. androidApp/ desktopApp/ webApp/ shared/ @cafonsomota KOtlin Multiplatform: Project Structure your

    platform speci fi c code (engine, drivers, etc.) :shared androidMain/ commonMain/ desktopMain/ jsMain/
  40. shared/build.gradle.kts KOtlin Multiplatform: Refactoring to KMP kotlin { ... sourceSets

    { val commonMain by getting dependencies implementation(“io.ktor:ktor-client-core:1.6.4") val androidMain by getting dependencies implementation("io.ktor:ktor-client-android:1.6.4") val desktopMain by getting val jsMain by getting dependencies implementation("io.ktor:ktor-client-js:1.6.4") } } Network ✅ Migrating to Ktor :shared
  41. shared/build.gradle.kts ✅ Migrating to SQLDelight KOtlin Multiplatform: Refactoring to KMP

    kotlin { ... sourceSets { val commonMain by getting val androidMain by getting dependencies implementation("com.squareup.sqldelight:android-driver:1.5.1") val desktopMain by getting dependencies implementation("com.squareup.sqldelight:native-driver:1.5.1") val jsMain by getting dependencies implementation("com.squareup.sqldelight:sqljs-driver:1.5.1") } } :shared
  42. kotlin { ... sourceSets { val commonMain by getting dependencies

    implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.0") val androidMain by getting val desktopMain by getting val jsMain by getting } } shared/build.gradle.kts ✅ Migrating to kotlinx.serialization KOtlin Multiplatform: Refactoring to KMP :shared
  43. kotlin { ... sourceSets { val commonMain by getting dependencies

    implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.0") val androidMain by getting val desktopMain by getting val jsMain by getting } } shared/build.gradle.kts ✅ Migrating to kotlinx.serialization KOtlin Multiplatform: Refactoring to KMP shared module And of course, Also migratE the API Calls
  44. KOtlin Multiplatform You don’t need to commit your entire codebase

    to KMP The goal is to share your business logic Di ff erent apps share di ff erent parts of their code - what makes sense to them! Space *Adapted from: KotlinConf 2019: Opening Keynote by Andrey Breslav Full KMP Cash App Shares: business logic Yandex Maps Shares: business logic, wrappers for C++ libraries PlanGrid Planboard Workspace Shares: business logic, sync logic, mgmnt o ffl ine data Shares: business logic Shares: business logic, networking, o ffl ine caching lyrs
  45. @cafonsomota KOtlin Multiplatform: ‘Suggestions’ Start small You’re going to develop

    a new feature? There’s part of your app that needs to be refactored? Want to improve your test coverage? why not do it on the shared module?
  46. KOtlin Multiplatform: ‘Challenges’ @cafonsomota 🟡 Not all libraries are available

    on KMP Those who are might not support all targets They might not be compatible with your Kotlin version
  47. KOtlin Multiplatform: ‘Challenges’ @cafonsomota 🟡 Not all libraries are available

    for KMP Those who are might not support all targets They might not be compatible with your Kotlin version 🟠 Project initial setup requires some time Invalidate cache and restart is needed sometimes to recover code auto-complete There are properties that you need to con fi gure: export (iOS), @JsName (JS), etc. Especially when targeting Web, you should enable the IR compiler
  48. KOtlin Multiplatform: ‘Challenges’ @cafonsomota 🟡 Not all libraries are available

    for KMP Those who are might not support all targets They might not be compatible with your Kotlin version 🟠 Project initial setup requires some time Invalidate cache and restart is needed sometimes to recover code auto-complete There are properties that you need to con fi gure: export (iOS), @JsName (JS), etc. Especially when targeting Web, you should enable the IR compiler 🔴 Generated library might need to lose some weight Especially when targeting Web, they can easily gain several MB’s
  49. @cafonsomota Compose: Getting Ready If you’re starting Compose for the

    fi rst time Start by developing fi rst on Android Once done, you can move it to a shared module If you’re already familiar with it Create a shared-ui module that will de fi ne the UI for the di ff erent platforms
  50. @cafonsomota Compose: Getting Ready 1. Create a new module called

    shared-ui 2. You can just copy-paste shared Rename it to shared-ui Remove all of it’s .kt classes
  51. @cafonsomota Compose To share your Compose UI you’ll need to

    do a bit of KMP Di ff erent platforms, mean di ff erent behaviours For instance, you can resize a window on the desktop but not on your phone* You have di ff erent input types, etc. * well, you can have the app in split screen mode, yes 🙂
  52. Compose src/shared-ui/build.gradle.kts :shared-ui plugins { kotlin("multiplatform") id("org.jetbrains.compose") version "1.0.0-alpha3" id("com.android.library")

    kotlin("plugin.serialization") } kotlin { ... sourceSets { val commonMain by getting { dependencies { api(compose.foundation) api(compose.runtime) api(compose.foundation) api(compose.material) api(compose.materialIconsExtended) api(compose.ui) api(compose.uiTooling) } } } }
  53. @cafonsomota Compose You’re using two di ff erent versions of

    Compose androidx.compose org.jetbrains.compose
  54. Compose Compose is interoperable with XML You don’t need to

    rewrite your entire app with Compose You’ll only be able to share the features that are using Compose
  55. Compose: ‘Challenges’ @cafonsomota 🟠 Initial setup is… challenging You’ll need

    to use JetBrains Compose plugin Adding the wrong con fi guration might increase building times in several minutes
  56. Compose: ‘Challenges’ @cafonsomota 🟠 Initial setup is… challenging You’ll need

    to use JetBrains Compose plugin Adding the wrong con fi guration might increase building times in several minutes 🟠 Libraries depend on the Compose version You’ll need to use a compatible one
  57. Compose: ‘Challenges’ @cafonsomota 🟠 Initial setup is… challenging You’ll need

    to use JetBrains Compose plugin Adding the wrong con fi guration might increase building times in several minutes 🟠 Libraries depend on the Compose version You’ll need to use a compatible one 🟠 Not all features are available for Desktop/ Web There’s no direct support for i18n, fonts and other resources LiveData, ViewModels, etc. are only available through third-party libraries
  58. Compose: ‘Challenges’ @cafonsomota 🔴 Web… is in it’s initial stages

    Not all Compose functions are ported to the Web The ones that are, often require that you use DOM elements to manipulate them Adding this abstraction manually will be really time consuming
  59. Compose: ‘Challenges’ @cafonsomota Accompanist A set of libraries that provide

    Compose ready features Examples: Insets, Paging, Permissions, Swipe to refresh, etc. 📐 Insets 🍫 System UI Controller 🎨 AppCompat Theme Adapter 🧭✨Navigation-Animation 📫 Permissions ⏳ Placeholder 🌊 Flow Layouts 🧭🎨 Navigation-Material 🖌 Drawable Painter ⬇ Swipe to Refresh 📖 Pager
  60. Accompanist A set of libraries that provide Compose ready features

    Examples: Insets, Paging, Permissions, Swipe to refresh, etc. Compose: ‘Challenges’
  61. Accompanist A set of libraries that provide Compose ready features

    Examples: Insets, Paging, Permissions, Swipe to refresh, etc. Not all Compose libraries are supported on Desktop and Web… for now! Compose: ‘Challenges’
  62. Compose: ‘Challenges’ Accompanist A set of libraries that provide Compose

    ready features Examples: Insets, Paging, Permissions, Swipe to refresh, etc. Not all Compose libraries are supported on Desktop and Web… for now! Community to the rescue! 🚀
  63. Accompanist (by Syer10) A subset of accompanist libraries ported by

    Syer10 to Desktop Available at: syer10.github.io/accompanist Compose: ‘Challenges’
  64. Accompanist (by Syer10) A subset of accompanist libraries ported by

    Syer10 to Desktop Available at: syer10.github.io/accompanist ⚠ only works on Desktop Compose: ‘Challenges’
  65. Compose: ‘Challenges’ Accompanist (by Syer10) A subset of accompanist libraries

    ported by Syer10 to Desktop Available at: syer10.github.io/accompanist ⚠ only works on Desktop Why? 😭
  66. plugins { kotlin("multiplatform") id("org.jetbrains.compose") version "1.0.0-alpha3" } kotlin { api(compose.material)

    api(compose.ui) } Syer10 Accompanist Syer10/accompanist/build.gradle.kts Compose: ‘Challenges’
  67. plugins { kotlin("multiplatform") id("org.jetbrains.compose") version "1.0.0-alpha3" } kotlin { api(compose.material)

    api(compose.ui) } Syer10 Accompanist Syer10/accompanist/build.gradle.kts Compose: ‘Challenges’ ⚠ Not exported to Android
  68. plugins {1 kotlin("multiplatform") id("org.jetbrains.compose") version “1.0.0-alpha3" id("com.android.library") }2 kotlin {a

    api(compose.material) api(compose.ui) }b Syer10 Accompanist Syer10/accompanist/build.gradle.kts Compose: ‘Challenges’
  69. plugins {1 kotlin("multiplatform") id("org.jetbrains.compose") version “1.0.0-alpha3" id("com.android.library") }2 kotlin {a

    android {b publishLibraryVariants("release", “debug") }c jvm(“desktop") }d Syer10 Accompanist Syer10/accompanist/build.gradle.kts Compose: ‘Challenges’
  70. plugins {1 kotlin("multiplatform") id("org.jetbrains.compose") version “1.0.0-alpha3" id("com.android.library") }2 kotlin {a

    android {b publishLibraryVariants("release", “debug") }c jvm(“desktop”)e sourceSets {f val commonMain by getting {g dependencies {h api(compose.material) api(compose.ui) }i }j val androidMain by getting val desktopMain by getting }d Syer10 Accompanist Syer10/accompanist/build.gradle.kts Compose: ‘Challenges’
  71. plugins {1 kotlin("multiplatform") id("org.jetbrains.compose") version “1.0.0-alpha3" id("com.android.library") }2 kotlin {a

    android {b publishLibraryVariants("release", “debug") }c jvm(“desktop”)e sourceSets {f val commonMain by getting {g dependencies {h api(compose.material) api(compose.ui) }i }j val androidMain by getting val desktopMain by getting }d android { compileSdk = 31 sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml") defaultConfig { minSdk = 21 targetSdk = 31 } compileOptions { sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 } } Syer10 Accompanist Syer10/accompanist/build.gradle.kts Compose: ‘Challenges’
  72. plugins { kotlin("multiplatform") id("org.jetbrains.compose") version “1.0.0-alpha3" id("com.android.library") } kotlin {

    android { publishLibraryVariants("release", “debug") } jvm(“desktop") sourceSets { val commonMain by getting { dependencies { api(compose.material) api(compose.ui) } } val androidMain by getting val desktopMain by getting } android { compileSdk = 31 sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml") defaultConfig { minSdk = 21 targetSdk = 31 } compileOptions { sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 } } Syer10 Accompanist Syer10/accompanist/build.gradle.kts Compose: ‘Challenges’ ✅ Supports Android and Desktop
  73. Compose: Image Loading Coil-Compose Image loading library implemented in Kotlin

    (and using Coroutines) Not all Compose libraries are supported on Desktop and Web… for now?
  74. Not all Compose libraries are supported on Desktop and Web…

    for now? Compose: Image Loading Coil-Compose Image loading library implemented in Kotlin (and using Coroutines) Community to the rescue! 🚀
  75. Compose: Image Loading Kamel Asynchronous media loading library for Android

    and Desktop Uses Ktor in the background Get it from: github.com/alialbaali/Kamel @cafonsomota
  76. Compose: Image Loading val request = ImageRequest.Builder(LocalContext.current) .data(url) .crossfade(true) .build()

    val painter = rememberImagePainter(request) when (val resource = lazyPainterResource(url)) { is ImagePainter.Loading -> { AddImagePreviewLoading(modifier) } is ImagePainter.Success -> { Image( painter = painter, contentScale = ContentScale.Crop, contentDescription = "Image preview", modifier = modifier) } is ImagePainter.Failure -> { AddImagePreviewFailure(modifier) } Coil
  77. Compose: Image Loading when (val resource = lazyPainterResource(url)) { is

    Resource.Loading -> { AddImagePreviewLoading(modifier) } is Resource.Success -> { KamelImage( resource = resource, contentScale = ContentScale.Crop, contentDescription = "Image preview", modifier = modifier, crossfade = true ) } is Resource.Failure -> { AddImagePreviewFailure(modifier) } Kamel
  78. Compose: Image Loading when (val resource = lazyPainterResource(url)) { is

    Resource.Loading -> { AddImagePreviewLoading(modifier) } is Resource.Success -> { KamelImage( resource = resource, contentScale = ContentScale.Crop, contentDescription = "Image preview", modifier = modifier, crossfade = true ) } is Resource.Failure -> { AddImagePreviewFailure(modifier) } Kamel ⚠ Last supported version is 1.0.0-alpha3 (Kamel version 0.2.2)
  79. Compose: Resources Resources Imagine that you want to show an

    image Hello world! Image( painter = painterResource(id = R.drawable.ic_launcher), contentDescription = stringResource(id = R.string.app_name) )
  80. Compose: Resources Resources Imagine that you want to show an

    image Implementation shared-ui/commonMain contains the expect implementation shared-ui/androidMain contains the xml fi les (vectors) and actual implementation shared-ui/desktopMain contains the images (png’s) and actual implementation @cafonsomota
  81. @Composable public expect fun icAbout(): Painter @Composable public expect fun

    icHome(): Painter Resources: Images shared-ui/commonMain/Icons.kt Compose: Resources
  82. @Composable public actual fun icAbout() = painterResource(R.drawable.ic_about) @Composable public actual

    fun icHome() = painterResource(R.drawable.ic_home) Resources: Images shared-ui/androidApp/Icons.kt Compose: Resources
  83. @Composable public actual fun icAbout() = painterResource("images/ic_about.png") @Composable public actual

    fun icHome() = painterResource("images/ic_home.png") Resources: Images shared-ui/desktopApp/Icons.kt Compose: Resources
  84. Compose: Resources Resources Imagine that you want to set a

    custom font Hello world! Hello world!
  85. Compose: Resources Resources Imagine that you want to set a

    custom font Hello world! Text( text = “Hello World!”, style = typography.h4 ) Hello world!
  86. Compose: Resources Resources Imagine that you want to set a

    custom font Hello world! private val HollywoodHillsFontFamily = FontFamily( Font(R.font.sf_hollywood_hills) ) h4 = TextStyle( color = colorAccent, fontFamily = HollywoodHillsFontFamily, fontSize = fontSizeLarge ) Hello world!
  87. Compose: Resources Resources Imagine that you want to set a

    custom font Implementation shared-ui/commonMain/resources contains the font fi les shared-ui/commonMain/platform de fi nes the expect function shared-ui/androidMain/platform de fi nes the actual function shared-ui/desktopMain/platform de fi nes the actual function @cafonsomota
  88. @Composable expect fun Font( name: String, res: String ): Font

    Resources: Font shared-ui/commonMain/platform/PlatformFont.kt Compose: Resources
  89. @Composable actual fun Font( name: String, res: String, ): Font

    { val context = LocalContext.current val id = context.resources.getIdentifier(res, "font", context.packageName) return Font(id) } Resources: Font shared-ui/androidMain/platform/PlatformFont.kt Compose: Resources
  90. @Composable actual fun Font( name: String, res: String ): Font

    { androidx.compose.ui.text.platform.Font("font/$res.ttf") } shared-ui/desktopMain/platform/PlatformFont.kt Resources: Font Compose: Resources
  91. Compose: Lifecycle, ViewModel, LiveData and Navigation PreCompose (by Tlaster) Lifecycle,

    ViewModel, LiveData and Navigation are Android components They now have been ported to Compose desktop Get it from: github.com/Tlaster/PreCompose
  92. Compose: WebApp What about Web? Is in an initial stage

    and the paradigm is di ff erent It’s focused on DOM rendering Only a set of components are available: Box, Button, Column, Row, Slider, Text @cafonsomota
  93. Compose: WebApp @Composable fun Column(content: @Composable () -> Unit) {

    Div({ style { display(DisplayStyle.Flex) alignItems(AlignItems.Center) flexGrow(1.0) } }) { content() } } :webApp webApp/components/Column.kt
  94. Compose: WebApp Sharing logic Works without any issue The generated

    JS fi le might be up to several MBs Sharing UI It’s going to be time consuming to share everything You’re going to need to create several components Most of the libraries don’t support it (yet) Nevertheless… it’s fun to see how long we’ll be able to go in a couple of months! @cafonsomota
  95. Status 🟢 Kotlin Multiplatform Mobile is stable-ish Can be used

    in production although part of it is in alpha/beta 🟢 Compose (Android) is stable Go on! It’s time to dive-in into declarative UI 🟡 Compose (Desktop) is alpha-ish 🔴 Compose (Web) is alpha 🟠 Documentation and samples 🟢 Community and support @cafonsomota
  96. Jetpack Compose samples (Google) github.com/android/compose-samples Jetpack Compose samples (JetBrains) https://github.com/JetBrains/compose-jb/

    Jetpack/JetBrains Compose Playground foso.github.io/Jetpack-Compose-Playground/ Jetpack Compose Internals Kotlin Slack Resources
  97. @cafonsomota SELECT YOUR LEVEL I just want to see the

    story. I want a lighter experience. Give me the full challenge! 👉
  98. @cafonsomota SELECT YOUR LEVEL I just want to see the

    story. I want a lighter experience. Give me the full challenge! 👉
  99. Kotlin Multiplatform and Compose template Alicerce In Portuguese alicerce means

    foundation A Kotlin Multiplatform with Compose template Currently supports: Android, Desktop and Web Contains an initial project con fi guration along with the libraries mentioned here Open to feedback and contributions! Alicerce
  100. Photo by Hans Isaacson on Unsplash @cafonsomota An Android, A

    Desktop, and A Web Developer enter in a Bar