From b3022237a345c6b944c8aae08485207789bf268e Mon Sep 17 00:00:00 2001 From: Raihan Ariq <202310715297@mhs.ubharajaya.ac.id> Date: Wed, 12 Nov 2025 21:10:17 +0700 Subject: [PATCH] Room Database Setup --- .idea/appInsightsSettings.xml | 26 ++++++++++ app/build.gradle.kts | 14 +++++ .../java/com/example/notebook/MainActivity.kt | 1 + .../com/example/notebook/data/AppDatabase.kt | 44 ++++++++++++++++ .../com/example/notebook/data/DatabaseTest.kt | 31 +++++++++++ .../com/example/notebook/data/NotebookDao.kt | 51 +++++++++++++++++++ .../example/notebook/data/NotebookEntity.kt | 48 +++++++++++++++++ build.gradle.kts | 1 + gradle/libs.versions.toml | 2 +- 9 files changed, 217 insertions(+), 1 deletion(-) create mode 100644 .idea/appInsightsSettings.xml create mode 100644 app/src/main/java/com/example/notebook/data/AppDatabase.kt create mode 100644 app/src/main/java/com/example/notebook/data/DatabaseTest.kt create mode 100644 app/src/main/java/com/example/notebook/data/NotebookDao.kt create mode 100644 app/src/main/java/com/example/notebook/data/NotebookEntity.kt diff --git a/.idea/appInsightsSettings.xml b/.idea/appInsightsSettings.xml new file mode 100644 index 0000000..371f2e2 --- /dev/null +++ b/.idea/appInsightsSettings.xml @@ -0,0 +1,26 @@ + + + + + + \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 8b2c35e..ec57099 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,6 +1,7 @@ plugins { alias(libs.plugins.android.application) alias(libs.plugins.jetbrains.kotlin.android) + id("com.google.devtools.ksp") version "1.9.22-1.0.16" } android { @@ -66,4 +67,17 @@ dependencies { androidTestImplementation(libs.ui.test.junit4) debugImplementation(libs.ui.tooling) debugImplementation(libs.ui.test.manifest) + + // Room Database - TAMBAHKAN INI SEMUA + val roomVersion = "2.6.1" + implementation("androidx.room:room-runtime:$roomVersion") + implementation("androidx.room:room-ktx:$roomVersion") + ksp("androidx.room:room-compiler:$roomVersion") + + // Coroutines + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.0") + + // ViewModel & Lifecycle + implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.7.0") + implementation("androidx.lifecycle:lifecycle-runtime-compose:2.7.0") } \ No newline at end of file diff --git a/app/src/main/java/com/example/notebook/MainActivity.kt b/app/src/main/java/com/example/notebook/MainActivity.kt index 41a997b..2d8bde0 100644 --- a/app/src/main/java/com/example/notebook/MainActivity.kt +++ b/app/src/main/java/com/example/notebook/MainActivity.kt @@ -33,6 +33,7 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.DialogProperties +import com.example.notebook.data.DatabaseTest import com.example.notebook.ui.theme.NotebookTheme class MainActivity : ComponentActivity() { diff --git a/app/src/main/java/com/example/notebook/data/AppDatabase.kt b/app/src/main/java/com/example/notebook/data/AppDatabase.kt new file mode 100644 index 0000000..9464132 --- /dev/null +++ b/app/src/main/java/com/example/notebook/data/AppDatabase.kt @@ -0,0 +1,44 @@ +package com.example.notebook.data + +import android.content.Context +import androidx.room.Database +import androidx.room.Room +import androidx.room.RoomDatabase + +/** + * Database utama aplikasi + * Version 1 = versi pertama database kamu + */ +@Database( + entities = [ + NotebookEntity::class, + SourceEntity::class, + ChatMessageEntity::class + ], + version = 1, + exportSchema = false +) +abstract class AppDatabase : RoomDatabase() { + + abstract fun notebookDao(): NotebookDao + + companion object { + @Volatile + private var INSTANCE: AppDatabase? = null + + /** + * Singleton pattern - hanya ada 1 instance database + */ + fun getDatabase(context: Context): AppDatabase { + return INSTANCE ?: synchronized(this) { + val instance = Room.databaseBuilder( + context.applicationContext, + AppDatabase::class.java, + "notebook_database" + ).build() + INSTANCE = instance + instance + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/notebook/data/DatabaseTest.kt b/app/src/main/java/com/example/notebook/data/DatabaseTest.kt new file mode 100644 index 0000000..903d9a6 --- /dev/null +++ b/app/src/main/java/com/example/notebook/data/DatabaseTest.kt @@ -0,0 +1,31 @@ +package com.example.notebook.data + +import android.content.Context +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch + +/** + * Helper untuk test database + * Panggil fungsi ini dari MainActivity untuk test + */ +class DatabaseTest(private val context: Context) { + + private val database = AppDatabase.getDatabase(context) + private val dao = database.notebookDao() + + fun testInsertNotebook() { + CoroutineScope(Dispatchers.IO).launch { + val testNotebook = NotebookEntity( + title = "Notebook Test", + description = "Ini adalah test database", + createdAt = System.currentTimeMillis(), + updatedAt = System.currentTimeMillis(), + sourceCount = 0 + ) + + val id = dao.insertNotebook(testNotebook) + println("✅ Database Test: Notebook berhasil disimpan dengan ID: $id") + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/notebook/data/NotebookDao.kt b/app/src/main/java/com/example/notebook/data/NotebookDao.kt new file mode 100644 index 0000000..1e64801 --- /dev/null +++ b/app/src/main/java/com/example/notebook/data/NotebookDao.kt @@ -0,0 +1,51 @@ +package com.example.notebook.data + +import androidx.room.* +import kotlinx.coroutines.flow.Flow + +/** + * DAO (Data Access Object) untuk mengakses database + * Semua fungsi ini otomatis dihandle Room + */ +@Dao +interface NotebookDao { + + // === NOTEBOOK OPERATIONS === + + @Insert + suspend fun insertNotebook(notebook: NotebookEntity): Long + + @Update + suspend fun updateNotebook(notebook: NotebookEntity) + + @Delete + suspend fun deleteNotebook(notebook: NotebookEntity) + + @Query("SELECT * FROM notebooks ORDER BY updatedAt DESC") + fun getAllNotebooks(): Flow> + + @Query("SELECT * FROM notebooks WHERE id = :notebookId") + fun getNotebookById(notebookId: Int): Flow + + // === SOURCE OPERATIONS === + + @Insert + suspend fun insertSource(source: SourceEntity) + + @Query("SELECT * FROM sources WHERE notebookId = :notebookId") + fun getSourcesByNotebook(notebookId: Int): Flow> + + @Delete + suspend fun deleteSource(source: SourceEntity) + + // === CHAT OPERATIONS === + + @Insert + suspend fun insertChatMessage(message: ChatMessageEntity) + + @Query("SELECT * FROM chat_messages WHERE notebookId = :notebookId ORDER BY timestamp ASC") + fun getChatHistory(notebookId: Int): Flow> + + @Query("DELETE FROM chat_messages WHERE notebookId = :notebookId") + suspend fun clearChatHistory(notebookId: Int) +} \ No newline at end of file diff --git a/app/src/main/java/com/example/notebook/data/NotebookEntity.kt b/app/src/main/java/com/example/notebook/data/NotebookEntity.kt new file mode 100644 index 0000000..3eeac80 --- /dev/null +++ b/app/src/main/java/com/example/notebook/data/NotebookEntity.kt @@ -0,0 +1,48 @@ +package com.example.notebook.data + +import androidx.room.Entity +import androidx.room.PrimaryKey + +/** + * Entity untuk menyimpan data Notebook di database + */ +@Entity(tableName = "notebooks") +data class NotebookEntity( + @PrimaryKey(autoGenerate = true) + val id: Int = 0, + + val title: String, // Judul notebook + val description: String, // Deskripsi singkat + val createdAt: Long, // Timestamp pembuatan + val updatedAt: Long, // Timestamp update terakhir + val sourceCount: Int = 0 // Jumlah sumber yang diupload +) + +/** + * Entity untuk menyimpan sumber/dokumen yang diupload + */ +@Entity(tableName = "sources") +data class SourceEntity( + @PrimaryKey(autoGenerate = true) + val id: Int = 0, + + val notebookId: Int, // Foreign key ke notebook + val fileName: String, // Nama file + val fileType: String, // Tipe: PDF, Image, Text, dll + val filePath: String, // Path file di storage + val uploadedAt: Long // Timestamp upload +) + +/** + * Entity untuk menyimpan chat history dengan AI + */ +@Entity(tableName = "chat_messages") +data class ChatMessageEntity( + @PrimaryKey(autoGenerate = true) + val id: Int = 0, + + val notebookId: Int, // Foreign key ke notebook + val message: String, // Isi pesan + val isUserMessage: Boolean, // true = user, false = AI + val timestamp: Long // Kapan pesan dikirim +) \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index c1e23bc..15498bd 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -2,4 +2,5 @@ plugins { alias(libs.plugins.android.application) apply false alias(libs.plugins.jetbrains.kotlin.android) apply false + id("com.google.devtools.ksp") version "1.9.22-1.0.16" apply false } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b0b9771..23f3239 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -agp = "8.2.2" +agp = "8.13.1" kotlin = "1.9.22" coreKtx = "1.12.0" junit = "4.13.2"