0
0

Kotlin MultipatformとFirestoreでWebページ

Last updated at Posted at 2024-06-27

概要(日記)

Kotlin Multiplatform (Kotlin/js)とfirebase-kotlin-SDKでプラウザアプリの骨組みを作る。

前提

  • Ubuntu 22.04 on Windwos 11 wsl2
  • Firebaseプロジェクト・Firestoreが有効であること
  • 認証無し。実験用

Step 1: 空のアプリ作成

参照

build.gradle.kts
plugins {
    kotlin("multiplatform") version "2.0.0"
}

repositories {
    mavenCentral()
}

kotlin {
    js {
        browser{}
        binaries.executable()
    }
}
src/jsMain/kotlin/Main.kt
fun main() {
    println("Hello, World!")
}
src/jsMain/index.html
<script src="KtFirestore.js"></script>

src="KtFirestore.js"はProject名(デフォルトでプロジェクトフォルダ名)に置き換え

実行
sh gradlew jsRun

ブラウザが起動し空のページが表示される。開発者ツールでConsole上にHello, World!が表示されていることを確認。

Step 2: Firebase Kotlin SDK 組み込み

参照

Firestore SDKは大きく2通り

  • Admin SDK: サーバ上で動作するFirestoreアプリ用。サーバ上でAPIを提供する場合
  • モバイル/Web SDK: デバイス/ブラウザから直接(APIを介さず)DBにアクセスする場合

プラウザアプリならWeb SDKを使用するのだが、今回せっかくなのでmultiplatformに対応するfirebase-kotlin-SDKを試してみた。
Webページはkotlinx.htmlを使ってHTMLを手書き。

build.gradle.kts
//...
kotlin {
    js {
        browser {}
        binaries.executable()
    }
    sourceSets {
        jsMain.dependencies {
            implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1") // https://mvnrepository.com/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-core
            implementation("dev.gitlive:firebase-firestore:1.13.0") // https://mvnrepository.com/artifact/dev.gitlive/firebase-firestore
            implementation("org.jetbrains.kotlinx:kotlinx-html:0.11.0") // https://mvnrepository.com/artifact/org.jetbrains.kotlinx/kotlinx-html
        }
    }
}
src/jsMain/resources/index.html
<body></body>
<script src="プロジェクト名.js"></script>
src/jsMain/kotlin/Main.kt
val options = FirebaseOptions(
    apiKey = "xxxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxxx",
    projectId = "xxxxxx",
    databaseUrl = "https://xxxxxxxxxxxxx.firebaseio.com",
    applicationId = "1:xxxxxxxxxxx:web:xxxxxxxxxxxxxxxxxxxx",
)

@OptIn(DelicateCoroutinesApi::class)
suspend fun main() {
    val app = Firebase.initialize(Unit, options)
    val db = Firebase.firestore(app)
    db.settings = firestoreSettings(db.settings) { cacheSettings = persistentCacheSettings { } }

    fun addItem(item: String) = GlobalScope.launch { db.collection("tmp").add(mapOf("action" to item)) }
    fun delItem(id: String) = GlobalScope.launch { db.collection("tmp").document(id).delete() }

    val action = document.create.input(name = "name")
    val book = document.create.table()
    val body = document.body ?: error("body is null")
    body.append(book)
    db.collection("tmp").snapshots.collect { qs ->
        book.innerHTML = ""
        book.tHead = document.create.thead { tr { td {};td { +"To do List" } } }
        book.insertRow().apply {
            insertCell().append { button { +"Add" }.onclick = { addItem(action.value) } }
            insertCell().append(action)
        }
        qs.documents.forEach { ds ->
            book.insertRow().apply {
                insertCell().append { button { +"Del" }.onclick = { delItem(ds.id) } }
                insertCell().apply { textContent = ds.get<String?>("action") ?: "[No Action]" }
            }
        }
    }
}

apiKeyなどの接続情報は Firebaseポータル→プロジェクトの設定 を参照。
※実際のコードではapiKeyをコミットしてしまわないよう注意。

ソースコード

資料

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0