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

Compose Multiplatform で Bluesky のクライアント作ってみた / Bluesky client with Compose Multiplatform

Compose Multiplatform で Bluesky のクライアント作ってみた / Bluesky client with Compose Multiplatform

Yuki Anzai

April 30, 2023
Tweet

More Decks by Yuki Anzai

Other Decks in Technology

Transcript

  1. $PNQPTF.VMUJQMBUGPSNͰ
    #MVFTLZͷΫϥΠΞϯτ࡞ͬͯΈͨ
    yanzm

    View full-size slide

  2. ZBO[Nʢ΍Μ͟Ήʣ
    w !ZBO[NCTLZTPDJBM
    w ݹʢ͍ʹ͑͠ʣͷ"OESPJEFS
    w ݄೔ʹ,PKJSB͞Μʹট଴ίʔυ΋ΒͬͯCMVFTLZ͸͡Ί·ͨ͠ɻ৽ถͰ
    ͢ɻ

    View full-size slide

  3. ,PUMJO
    w ʢ΋ͱ΋ͱ͸ʣ+7.ݴޠ
    w CFUUFS+BWBతͳ
    w ೥͔Β"OESPJEͷެࣜαϙʔτݴޠͷҰͭ

    View full-size slide

  4. ,PUMJO.VMUJQMBUGPSN ,.1

    w ,PUMJOͷίʔυΛXFC +T
    ͱ͔OBUJWF EFTLUPQ
    ͱ͔ͷόΠφϦʹϏϧυ
    w ಉ͡,PUMJOͷίʔυͰෳ਺ͷ1MBUGPSNʹରԠ
    w J04΋ରԠ
    w ͨͩ͠ɺ6*͸ͦΕͧΕͷ1MBUGPSN/BUJWFͳ෦෼Ͱ࣮૷

    View full-size slide

  5. +FUQBDL$PNQPTF
    w "OESPJEͷωΠςΟϒ6*Λߏங͢ΔͨΊͷ࠷৽ͷπʔϧΩοτ
    w એݴత6*
    Row {
    Icon(
    imageVector = Icons.Default.Star,
    contentDescription = null
    )
    Column {
    Text(
    text = "username"
    )
    Text(
    text = "description"
    )
    }
    Button(
    onClick = onClickFollow
    ) {
    Text("follow")
    }
    }

    View full-size slide

  6. $PNQPTFGPS%FTLUPQ
    w ೥݄
    w +FUQBDL$PNQPTFͰ,PUMJO.VMUJQMBUGPSNͷEFTLUPQͷ6*͕࡞ΕΔ

    View full-size slide

  7. $PNQPTF.VUMJQMBUGPSN6*'SBNFXPSL
    w IUUQTXXXKFUCSBJOTDPNMQDPNQPTFNVMUJQMBUGPSN
    w ೥݄೔ͷ,PUMJO$POGͰൃද
    w EFTLUPQ͚ͩ͡Όͳ͘J04 "MQIB ,PUMJO/BUJWF
    ΍8FC &YQFSJNFOUBM
    ,PUMJO8BTN
    ΋αϙʔτ

    View full-size slide

  8. #MVFTLZͷΫϥΠΞϯτΞϓϦΛ
    $PNQPTF.VMUJQMBUGPSNͰ࡞Δ
    https://github.com/yanzm/Rayleigh

    View full-size slide

  9. 4UFQϕʔεͷϓϩδΣΫτΛ࡞Δ
    w +FU#SBJOTͷHJUIVCʹDPNQPTFNVMUJQMBUGPSNͷςϯϓϨʔτ͕͋Δ
    w IUUQTHJUIVCDPN+FU#SBJOTDPNQPTFNVMUJQMBUGPSNJPTBOESPJE
    UFNQMBUF

    View full-size slide

  10. 4UFQ௨৴Ͱ͖ΔΑ͏ʹ͢Δ
    w 4FJVO͞Μ͸3FUSP
    fi
    UΛ࢖͍͚ͬͯͨͲ,.1Ͱ͸࢖͑ͳ͍
    w ,UPS
    w IUUQTLUPSJP
    w ,PUMJO$POG`ͷηογϣϯͰग़͖ͯͨ$PNQPTF.VMUJQMBUGPSNͰνϟο
    τ͢ΔΞϓϦ͕ࢀߟʹͳͬͨ
    w IUUQTHJUIVCDPNTWUL,$$IBU"QQ
    w ,UPS,PUMJOY4FSJBMJ[BUJPOͱ͔

    View full-size slide

  11. 4UFQϩάΠϯը໘ͷ6*Λ࡞Δ

    View full-size slide

  12. 4UFQϩάΠϯը໘ͷ6*Λ࡞Δ
    w SEQBSUZDMJFOU͸"QQ1BTTXPSEͰϩάΠϯ͢ΔΑ͏ʹͳ͔ͬͨΒɺΞΧ
    ΢ϯτͷ࡞੒ϩάΠϯ΍"QQ1BTTXPSEͷ࡞੒͸ϒϥ΢βΛ։͍ͯIUUQT
    TUBHJOHCTLZBQQΛද͍ࣔͨ͠
    w "OESPJE J04ͦΕͧΕͷQMBUGPSNͷॲཧ͕ඞཁ

    View full-size slide

  13. @Composable
    fun App(
    onOpenBrowser: (String) -> Unit = {}
    ) {
    RayleighTheme {

    LoginScreen(
    viewModel = viewModel,
    onOpenBrowser = onOpenBrowser,
    )
    }
    }
    shared/commonMain

    View full-size slide

  14. class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContent {
    MainView(
    onOpenBrowser = {
    startActivity(
    Intent(Intent.ACTION_VIEW, Uri.parse(it))
    )
    }
    )
    }
    }
    @Composable
    fun MainView(
    onOpenBrowser: (String) -> Unit
    ) {
    App(
    onOpenBrowser = onOpenBrowser
    )
    }
    androidApp/
    shared/androidMain Android

    View full-size slide

  15. struct ComposeView: UIViewControllerRepresentable {
    func makeUIViewController(context: Context) -> UIViewController {
    Main_iosKt.MainViewController(
    onOpenBrowser: {
    let url = URL(string:$0)!
    UIApplication.shared.open(url, options: [:], completionHandler: nil)
    }
    )
    }
    func updateUIViewController(_ uiViewController: UIViewController, context: Context) {}
    }
    fun MainViewController(
    onOpenBrowser: (String) -> Unit
    ) = ComposeUIViewController {
    App(
    onOpenBrowser = onOpenBrowser
    )
    }
    iosApp/iosApp/ContentView.swift
    shared/iosMain iOS

    View full-size slide

  16. 4UFQϩάΠϯ͢Δ
    w "1*Λୟ͍ͯฦ͖ͬͯͨUPLFOΛอଘ͠ͳ͍ͱ͍͚ͳ͍
    w NVMUJQMBUGPSNTFUUJOHTΛ࢖͏͜ͱʹ͢Δ
    w IUUQTHJUIVCDPNSVTTIXPMGNVMUJQMBUGPSNTFUUJOHT
    w ϓϥοτϑΥʔϜ͝ͱʹ4FUUJOHTͷੜ੒Πϯελϯε͕ҟͳΔ
    w %*͕ͳ͍ͱͭΒ͍

    View full-size slide

  17. 4UFQ%FQFOEFODZ*OKFDUJPO
    w "OESPJEͰ͸EBHHFSIJMU͕σϑΝΫτ͕ͩ,.1Ͱ͸࢖͑ͳ͍
    w ,PJO
    w LPJODPSF͸,.1ʹରԠ͍ͯ͠Δ͕
    w LPJODPNQPTF͸$PNQPTF.VMUJQMBUGPSNʹ·ͩରԠ͍ͯ͠ͳ͍
    w l$PVMEOPU
    fi
    OEJPJOTFSULPJOLPJODPNQPTFJPTBSNzͱౖΒΕ
    Δ
    w IUUQTJOTFSULPJOJPEPDTSFGFSFODFLPJODPNQPTFNVMUJQMBUGPSN͸
    8*1

    View full-size slide

  18. class AppComponent : KoinComponent {
    val authRepository: AuthRepository by inject()
    }
    shared/commonMain
    @Composable
    fun App(
    appComponent: AppComponent,
    onOpenBrowser: (String) -> Unit = {}
    ) {
    RayleighTheme {
    val appViewModel = remember { AppViewModel(appComponent.authRepository) }

    }
    }

    View full-size slide

  19. class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContent {
    MainView(
    appComponent = AppComponent(),
    onOpenBrowser = {
    startActivity(
    Intent(Intent.ACTION_VIEW, Uri.parse(it))
    )
    @Composable
    fun MainView(
    appComponent: AppComponent,
    onOpenBrowser: (String) -> Unit
    ) {
    App(
    appComponent = appComponent,
    onOpenBrowser = onOpenBrowser
    )
    }
    androidApp/
    shared/androidMain Android

    View full-size slide

  20. struct ComposeView: UIViewControllerRepresentable {
    let appComponent = AppComponent()
    func makeUIViewController(context: Context) -> UIViewController {
    Main_iosKt.MainViewController(
    appComponent: appComponent,
    onOpenBrowser: {
    let url = URL(string:$0)!
    UIApplication.shared.open(url, options: [:], completionHandler: nil)
    }
    )
    }
    fun MainViewController(
    appComponent: AppComponent,
    onOpenBrowser: (String) -> Unit
    ) = ComposeUIViewController {
    App(
    appComponent = appComponent,
    onOpenBrowser = onOpenBrowser
    )
    }
    iosApp/iosApp/ContentView.swift
    shared/iosMain iOS

    View full-size slide

  21. 4UFQλΠϜϥΠϯΛऔಘ͢Δ
    w ϩάΠϯ࣌ʹऔಘͨ͠5PLFOΛCFBSFSBVUIFOUJDBUJPOʹηοτ͢Δ
    w ,UPSͷ"VUIQMVHJO࢖͏͚ͩ
    w IUUQTLUPSJPEPDTCFBSFSDMJFOUIUNM
    w UZQFͰΦϒδΣΫτ͕มΘΔ3FDPSEͱ͔͸$MBTTEJTDSJNJOBUPSGPS
    QPMZNPSQIJTN࢖͏
    w IUUQTHJUIVCDPN,PUMJOLPUMJOYTFSJBMJ[BUJPOCMPCNBTUFSEPDT
    KTPONEDMBTTEJTDSJNJOBUPSGPSQPMZNPSQIJTN

    View full-size slide

  22. ·ͱΊࠓޙ
    w /BWJHBUJPOͲ͏ͨ͠Β͍͍ͷͩʜ
    w %FDPNQPTF IUUQTHJUIVCDPNBSLJWBOPW%FDPNQPTF

    w %*͕ͭΒ͍ʜ
    w LPJODPNQPTF͕ରԠͨ͠ΒָʹͳΔ͔΋ʁ
    w 5FYU'JFMEͷڍಈ͕J044JNVMBUPSͰ͓͔͍͠ʜ
    w $PNQPTFͰී௨ʹJ04ͷ6*͕Ͱ͖͍ͯ͢͝ͷͰɺ͍Ζ͍Ζ΍Γ͍ͨ

    View full-size slide