Merge branch 'backend/db-projects' into 'main'

feat: projects local database and repository made

Closes #9

See merge request EmmaVandewalle/writand!24
This commit is contained in:
Robin Meersman 2024-07-22 19:08:25 +00:00
commit 8def0b92a8
14 changed files with 259 additions and 18 deletions

View file

@ -1,16 +1,20 @@
plugins { plugins {
id 'com.android.application' id 'com.android.application'
id 'org.jetbrains.kotlin.android' id 'org.jetbrains.kotlin.android'
id "com.google.dagger.hilt.android"
id 'kotlinx-serialization'
id "kotlin-kapt"
id 'com.google.protobuf' version '0.9.4'
} }
android { android {
namespace 'be.re.writand' namespace 'be.re.writand'
compileSdk 33 compileSdk 34
defaultConfig { defaultConfig {
applicationId "be.re.writand" applicationId "be.re.writand"
minSdk 24 minSdk 26
targetSdk 33 targetSdk 34
versionCode 1 versionCode 1
versionName "1.0" versionName "1.0"
@ -27,37 +31,92 @@ android {
} }
} }
compileOptions { compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8 sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_17
} }
kotlinOptions { kotlinOptions {
jvmTarget = '1.8' jvmTarget = '17'
} }
buildFeatures { buildFeatures {
compose true compose true
} }
composeOptions { composeOptions {
kotlinCompilerExtensionVersion '1.2.0' kotlinCompilerExtensionVersion '1.5.0'
} }
packagingOptions { packagingOptions {
resources { resources {
excludes += '/META-INF/{AL2.0,LGPL2.1}' excludes += '/META-INF/{AL2.0,LGPL2.1}'
} }
} }
testOptions {
unitTests.all {
useJUnitPlatform()
}
unitTests.returnDefaultValues = true
}
} }
dependencies { dependencies {
implementation 'androidx.core:core-ktx:1.13.1'
implementation 'androidx.core:core-ktx:1.7.0' implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.8.3'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1' implementation 'androidx.activity:activity-compose:1.9.0'
implementation 'androidx.activity:activity-compose:1.3.1'
implementation "androidx.compose.ui:ui:$compose_ui_version" implementation "androidx.compose.ui:ui:$compose_ui_version"
implementation "androidx.compose.ui:ui-tooling-preview:$compose_ui_version" implementation "androidx.compose.ui:ui-tooling-preview:$compose_ui_version"
implementation 'androidx.compose.material:material:1.2.0' implementation 'androidx.compose.material:material:1.6.8'
testImplementation 'junit:junit:4.13.2' testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5' androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
// Testing
androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_ui_version" androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_ui_version"
testImplementation "org.junit.jupiter:junit-jupiter-api:5.8.1"
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:5.8.1"
// Mockito testing
testImplementation "org.mockito.kotlin:mockito-kotlin:3.2.0"
testImplementation "org.robolectric:robolectric:3.4.2"
testImplementation 'org.powermock:powermock-api-mockito:1.4.12'
testImplementation 'org.powermock:powermock-module-junit4:1.6.2'
testImplementation "org.mockito:mockito-core:4.2.0"
testImplementation "org.mockito:mockito-inline:4.1.0"
testImplementation "org.mockito:mockito-android:4.1.0"
// Hilt
implementation "com.google.dagger:hilt-android:2.48"
kapt "com.google.dagger:hilt-compiler:2.48"
// Room
implementation 'androidx.room:room-runtime:2.6.1'
annotationProcessor 'androidx.room:room-compiler:2.6.1'
implementation 'androidx.room:room-ktx:2.6.1'
// Proto DataStore
implementation 'androidx.datastore:datastore:1.1.1'
implementation 'com.google.protobuf:protobuf-javalite:3.21.7'
debugImplementation "androidx.compose.ui:ui-tooling:$compose_ui_version" debugImplementation "androidx.compose.ui:ui-tooling:$compose_ui_version"
debugImplementation "androidx.compose.ui:ui-test-manifest:$compose_ui_version" debugImplementation "androidx.compose.ui:ui-test-manifest:$compose_ui_version"
} }
kapt {
correctErrorTypes true
}
protobuf {
protoc {
artifact = "com.google.protobuf:protoc:3.21.7"
}
// Generates the java Protobuf-lite code for the Protobufs in this project.
// see https://github.com/google/protobuf-gradle-plugin#customizing-protobuf-compilation
// for more information.
generateProtoTasks {
all().each { task ->
task.builtins {
java {
option 'lite'
}
}
}
}
}

View file

@ -0,0 +1,19 @@
package be.re.writand.data.local.db
import androidx.room.Entity
import androidx.room.PrimaryKey
import be.re.writand.data.local.models.OpenFilePath
/**
* Entity for recent projects to keep in memory, used in the ProjectsDAO.
* @param[id] the unique id of a project.
* @param[path] the absolute path to the directory/file.
* A file in case of a project consisting of 1 file only.
* @param[openedFiles] a list of objects to specify more about each last opened file.
*/
@Entity(tableName = "projects")
data class ProjectEntity (
@PrimaryKey val id: Int,
val path: String,
val openedFiles: List<OpenFilePath>
)

View file

@ -0,0 +1,37 @@
package be.re.writand.data.local.db
import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Query
import be.re.writand.data.local.models.Project
import kotlinx.coroutines.flow.Flow
/**
* A DAO to handle recent opened projects when the Project Picker is presented.
*/
@Dao
interface ProjectsDao {
/**
* Get all the recent files that were opened.
*/
@Query("SELECT * FROM projects")
fun getAllProjects(): Flow<List<Project>>
/**
* Insert a project into the database that was just opened.
* @param[project] the project to add in the database.
*/
@Insert(entity = ProjectEntity::class)
suspend fun insertProject(project: Project)
/**
* Delete a project from the recent opened projects.
* Should be called when the limit of saving projects is reached.
* @param[project] the project to be deleted from the database.
*/
@Delete(entity = ProjectEntity::class)
suspend fun deleteProject(project: Project)
}

View file

@ -0,0 +1,25 @@
package be.re.writand.data.local.db
import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
/**
* Database for all the recent projects.
*/
@Database(entities = [ProjectEntity::class], version = 1)
abstract class ProjectsDatabase: RoomDatabase() {
abstract fun projectsDao(): ProjectsDao
companion object {
@Volatile private var instance: ProjectsDatabase? = null
fun getInstance(context: Context) = instance ?: synchronized(this) {
return Room.databaseBuilder(
context.applicationContext, ProjectsDatabase::class.java, "projects-db"
).build().also { instance = it }
}
}
}

View file

@ -0,0 +1,16 @@
package be.re.writand.data.local.models
/**
* Data class used in the ProjectsDAO to store information about a recent project.
* @param[id] a unique id for the project.
* @param[path] the absolute path to the directory/file location of the project.
*/
data class Project(val id: Int, val path: String)
/**
* Data class used in ProjectEntity to store information about a recent file of a project.
* @param[projectId] the id of the project the file belongs to.
* @param[path] the relative path to the file starting from the root fo the project.
* @param[isSaved] info whether the file was saved before closing the app (for expansion of unsaved files).
*/
data class OpenFilePath(val projectId: Int, val path: String, var isSaved: Boolean)

View file

@ -0,0 +1,29 @@
package be.re.writand.data.repos
import be.re.writand.data.local.models.Project
import kotlinx.coroutines.flow.Flow
/**
* Repository that handles everything for the local ProjectsDatabase.
* @param[dao] the dao provides get/add/delete functionality of the recent projects.
*/
interface IProjectsRepository {
/**
* Gets all the projects from the local storage.
*/
fun getAllProjects(): Flow<List<Project>>
/**
* Adds a project to the local storage of recent projects.
* @param[project] the project to be added to the database.
*/
suspend fun addProject(project: Project)
/**
* Deletes a project from the local storage of recent projects.
* @param[project] the project to be deleted from the database.
*/
suspend fun deleteProject(project: Project)
}

View file

@ -0,0 +1,23 @@
package be.re.writand.data.repos
import be.re.writand.data.local.db.ProjectsDao
import be.re.writand.data.local.models.Project
import kotlinx.coroutines.flow.Flow
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class ProjectsRepository @Inject constructor(private val dao: ProjectsDao): IProjectsRepository {
override fun getAllProjects(): Flow<List<Project>> {
return dao.getAllProjects()
}
override suspend fun addProject(project: Project) {
dao.insertProject(project)
}
override suspend fun deleteProject(project: Project) {
dao.deleteProject(project)
}
}

View file

@ -0,0 +1,29 @@
package be.re.writand.di
import android.content.Context
import be.re.writand.data.local.db.ProjectsDao
import be.re.writand.data.local.db.ProjectsDatabase
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton
/**
* Module necessary to enable dependency injection for databases and DAO's.
*/
@InstallIn(SingletonComponent::class)
@Module
class DatabaseModule {
@Singleton
@Provides
fun provideProjectsDatabase(@ApplicationContext context: Context): ProjectsDatabase {
return ProjectsDatabase.getInstance(context)
}
@Provides
fun provideQuotesDao(projectsDatabase: ProjectsDatabase): ProjectsDao {
return projectsDatabase.projectsDao()
}
}

View file

@ -1,10 +1,13 @@
buildscript { buildscript {
ext { ext {
compose_ui_version = '1.2.0' kotlin_version = '1.9.0'
compose_ui_version = '1.6.8'
} }
}// Top-level build file where you can add configuration options common to all sub-projects/modules. }// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins { plugins {
id 'com.android.application' version '7.4.2' apply false id 'com.android.application' version '8.5.1' apply false
id 'com.android.library' version '7.4.2' apply false id 'com.android.library' version '8.5.1' apply false
id 'org.jetbrains.kotlin.android' version '1.7.0' apply false id 'org.jetbrains.kotlin.android' version '1.9.0' apply false
id 'com.google.dagger.hilt.android' version '2.44' apply false
id 'org.jetbrains.kotlin.plugin.serialization' version '1.6.21'
} }

View file

@ -21,3 +21,4 @@ kotlin.code.style=official
# resources declared in the library itself and none from the library's dependencies, # resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library # thereby reducing the size of the R class for that library
android.nonTransitiveRClass=true android.nonTransitiveRClass=true
android.nonFinalResIds=false

View file

@ -1,6 +1,6 @@
#Tue Jul 16 09:37:51 CEST 2024 #Tue Jul 16 09:37:51 CEST 2024
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME