Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Compose Multiplatform で Bluesky のクライアント作ってみた / ...
Search
Yuki Anzai
April 30, 2023
Technology
0
700
Compose Multiplatform で Bluesky のクライアント作ってみた / Bluesky client with Compose Multiplatform
Bluesky/ATProtocol 勉強会#1
https://428lab.connpass.com/event/280610/
Yuki Anzai
April 30, 2023
Tweet
Share
More Decks by Yuki Anzai
See All by Yuki Anzai
AI ツールを活用したコードリーディング - Android の公式サンプル Now in Android のソースコードを読んでみよう - / Code reading with AI tools
yanzm
1
58
EncryptedSharedPreferences が deprecated になっちゃった!どうしよう! / Oh no! EncryptedSharedPreferences has been deprecated! What should I do?
yanzm
0
1.2k
Devinを使ったモバイルアプリ開発 / Mobile app development with Devin
yanzm
0
240
Android Studio の 新しいAI機能を試してみよう / Try out the new AI features in Android Studio
yanzm
0
340
What’s new in Android development tools
yanzm
0
880
Google I/O 2025 Keynote & Developer Keynote Overview
yanzm
0
160
Coding Agent を使って Android アプリを作ってみる / Let's try using coding agent for Android app development
yanzm
0
180
MediaPipe と ML Kit ってどう ちがうの? / What is the difference between MediaPipe and ML Kit?
yanzm
0
1.3k
アプリをリリースできる状態に保ったまま 段階的にリファクタリングするための 戦略と戦術 / Strategies and tactics for incremental refactoring
yanzm
8
5.6k
Other Decks in Technology
See All in Technology
関係性が駆動するアジャイル──GPTに人格を与えたら、対話を通してふりかえりを習慣化できた話
mhlyc
0
130
いまさら聞けない ABテスト入門
skmr2348
1
200
生成AIを活用したZennの取り組み事例
ryosukeigarashi
0
200
Optuna DashboardにおけるPLaMo2連携機能の紹介 / PFN LLM セミナー
pfn
PRO
1
880
o11yで育てる、強い内製開発組織
_awache
3
120
extension 現場で使えるXcodeショートカット一覧
ktombow
0
210
20250929_QaaS_vol20
mura_shin
0
110
ZOZOのAI活用実践〜社内基盤からサービス応用まで〜
zozotech
PRO
0
170
Modern_Data_Stack最新動向クイズ_買収_AI_激動の2025年_.pdf
sagara
0
200
AIが書いたコードをAIが検証する!自律的なモバイルアプリ開発の実現
henteko
1
340
AWSにおけるTrend Vision Oneの効果について
shimak
0
130
GA technologiesでのAI-Readyの取り組み@DataOps Night
yuto16
0
270
Featured
See All Featured
Building Applications with DynamoDB
mza
96
6.6k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
16k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
32
2.2k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
140
34k
The Pragmatic Product Professional
lauravandoore
36
6.9k
Fireside Chat
paigeccino
40
3.7k
jQuery: Nuts, Bolts and Bling
dougneiner
64
7.9k
Typedesign – Prime Four
hannesfritz
42
2.8k
Code Reviewing Like a Champion
maltzj
525
40k
Why Our Code Smells
bkeepers
PRO
339
57k
Building Better People: How to give real-time feedback that sticks.
wjessup
368
20k
The Invisible Side of Design
smashingmag
301
51k
Transcript
$PNQPTF.VMUJQMBUGPSNͰ #MVFTLZͷΫϥΠΞϯτ࡞ͬͯΈͨ yanzm
ZBO[NʢΜ͟Ήʣ w !ZBO[NCTLZTPDJBM w ݹʢ͍ʹ͑͠ʣͷ"OESPJEFS w ݄ʹ,PKJSB͞ΜʹটίʔυΒͬͯCMVFTLZ͡Ί·ͨ͠ɻ৽ถͰ ͢ɻ
,PUMJO w ʢͱͱʣ+7.ݴޠ w CFUUFS+BWBతͳ w ͔Β"OESPJEͷެࣜαϙʔτݴޠͷҰͭ
,PUMJO.VMUJQMBUGPSN ,.1 w ,PUMJOͷίʔυΛXFC +T ͱ͔OBUJWF EFTLUPQ ͱ͔ͷόΠφϦʹϏϧυ w ಉ͡,PUMJOͷίʔυͰෳͷ1MBUGPSNʹରԠ
w J04ରԠ w ͨͩ͠ɺ6*ͦΕͧΕͷ1MBUGPSN/BUJWFͳ෦Ͱ࣮
+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") } }
$PNQPTFGPS%FTLUPQ w ݄ w +FUQBDL$PNQPTFͰ,PUMJO.VMUJQMBUGPSNͷEFTLUPQͷ6*͕࡞ΕΔ
$PNQPTF.VUMJQMBUGPSN6*'SBNFXPSL w IUUQTXXXKFUCSBJOTDPNMQDPNQPTFNVMUJQMBUGPSN w ݄ͷ,PUMJO$POGͰൃද w EFTLUPQ͚ͩ͡Όͳ͘J04 "MQIB ,PUMJO/BUJWF 8FC
&YQFSJNFOUBM ,PUMJO8BTN αϙʔτ
#MVFTLZͷΫϥΠΞϯτΞϓϦΛ $PNQPTF.VMUJQMBUGPSNͰ࡞Δ https://github.com/yanzm/Rayleigh
4UFQϕʔεͷϓϩδΣΫτΛ࡞Δ w +FU#SBJOTͷHJUIVCʹDPNQPTFNVMUJQMBUGPSNͷςϯϓϨʔτ͕͋Δ w IUUQTHJUIVCDPN+FU#SBJOTDPNQPTFNVMUJQMBUGPSNJPTBOESPJE UFNQMBUF
4UFQ௨৴Ͱ͖ΔΑ͏ʹ͢Δ w 4FJVO͞Μ3FUSP fi UΛ͍͚ͬͯͨͲ,.1Ͱ͑ͳ͍ w ,UPS w IUUQTLUPSJP w
,PUMJO$POG`ͷηογϣϯͰग़͖ͯͨ$PNQPTF.VMUJQMBUGPSNͰνϟο τ͢ΔΞϓϦ͕ࢀߟʹͳͬͨ w IUUQTHJUIVCDPNTWUL,$$IBU"QQ w ,UPS ,PUMJOY4FSJBMJ[BUJPOͱ͔
4UFQϩάΠϯը໘ͷ6*Λ࡞Δ
4UFQϩάΠϯը໘ͷ6*Λ࡞Δ w SEQBSUZDMJFOU"QQ1BTTXPSEͰϩάΠϯ͢ΔΑ͏ʹͳ͔ͬͨΒɺΞΧ ϯτͷ࡞ϩάΠϯ"QQ1BTTXPSEͷ࡞ϒϥβΛ։͍ͯIUUQT TUBHJOHCTLZBQQΛද͍ࣔͨ͠ w "OESPJE J04ͦΕͧΕͷQMBUGPSNͷॲཧ͕ඞཁ
@Composable fun App( onOpenBrowser: (String) -> Unit = {} )
{ RayleighTheme { … LoginScreen( viewModel = viewModel, onOpenBrowser = onOpenBrowser, ) } } shared/commonMain
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
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
4UFQϩάΠϯ͢Δ w "1*Λୟ͍ͯฦ͖ͬͯͨUPLFOΛอଘ͠ͳ͍ͱ͍͚ͳ͍ w NVMUJQMBUGPSNTFUUJOHTΛ͏͜ͱʹ͢Δ w IUUQTHJUIVCDPNSVTTIXPMGNVMUJQMBUGPSNTFUUJOHT w ϓϥοτϑΥʔϜ͝ͱʹ4FUUJOHTͷੜΠϯελϯε͕ҟͳΔ w
%*͕ͳ͍ͱͭΒ͍
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
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) } … } }
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
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
4UFQλΠϜϥΠϯΛऔಘ͢Δ w ϩάΠϯ࣌ʹऔಘͨ͠5PLFOΛCFBSFSBVUIFOUJDBUJPOʹηοτ͢Δ w ,UPSͷ"VUIQMVHJO͏͚ͩ w IUUQTLUPSJPEPDTCFBSFSDMJFOUIUNM w UZQFͰΦϒδΣΫτ͕มΘΔ3FDPSEͱ͔$MBTTEJTDSJNJOBUPSGPS QPMZNPSQIJTN͏
w IUUQTHJUIVCDPN,PUMJOLPUMJOYTFSJBMJ[BUJPOCMPCNBTUFSEPDT KTPONEDMBTTEJTDSJNJOBUPSGPSQPMZNPSQIJTN
None
·ͱΊࠓޙ w /BWJHBUJPOͲ͏ͨ͠Β͍͍ͷͩʜ w %FDPNQPTF IUUQTHJUIVCDPNBSLJWBOPW%FDPNQPTF w %*͕ͭΒ͍ʜ
w LPJODPNQPTF͕ରԠͨ͠ΒָʹͳΔ͔ʁ w 5FYU'JFMEͷڍಈ͕J044JNVMBUPSͰ͓͔͍͠ʜ w $PNQPTFͰී௨ʹJ04ͷ6*͕Ͱ͖͍ͯ͢͝ͷͰɺ͍Ζ͍ΖΓ͍ͨ