Skip to content

Commit

Permalink
Add GetDayLogList Usecase and it's viewModel Impelementation.
Browse files Browse the repository at this point in the history
This commit includes,

1. Fix some directory hierarchy according to clean architecture.
2. Add GetDayLogList usecase.
3. Implement FakeDataRepository to test usecaes before implementing create dayLog usecase.
4. Link usecase with DayLogListViewModel for front page.

TODO:
  - Need to implement navhost.
  - Need to implement deletion action for listview.

Signed-off-by: Hyukjoong Kim <wangmir@gmail.com>
  • Loading branch information
wangmir committed Jan 31, 2022
1 parent 6a27842 commit 36b2d53
Show file tree
Hide file tree
Showing 26 changed files with 292 additions and 64 deletions.
17 changes: 9 additions & 8 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,13 @@ android {
dependencies {

implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.4.0'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'com.google.android.material:material:1.5.0'
implementation "androidx.compose.ui:ui:$compose_version"
implementation "androidx.compose.material:material:$compose_version"
implementation "androidx.compose.material:material-icons-extended:$compose_version"
implementation "androidx.compose.ui:ui-tooling-preview:$compose_version"
implementation 'androidx.test:core-ktx:1.4.0'
debugImplementation "androidx.compose.ui:ui-tooling:$compose_version"
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.4.0'
implementation 'androidx.activity:activity-compose:1.4.0'
Expand All @@ -71,16 +72,17 @@ dependencies {
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.8.2")
testImplementation("org.junit.jupiter:junit-jupiter-params:5.8.2")
testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.0'
testImplementation("de.mannodermaus.junit5:android-test-core:1.3.0")
testImplementation "com.google.truth:truth:1.1.2"

androidTestImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.0'
androidTestImplementation("androidx.test:runner:1.4.0")
androidTestImplementation("org.junit.jupiter:junit-jupiter-api:5.8.2")
androidTestImplementation("de.mannodermaus.junit5:android-test-core:1.3.0")
androidTestRuntimeOnly("de.mannodermaus.junit5:android-test-runner:1.3.0")
// androidTestImplementation("de.mannodermaus.junit5:android-test-compose:0.1.0-SNAPSHOT")
debugImplementation "com.google.truth:truth:1.1.2"
testImplementation "com.google.truth:truth:1.1.2"
androidTestImplementation "com.google.truth:truth:1.1.2"
androidTestImplementation 'androidx.test:core:1.0.0'
androidTestImplementation 'androidx.test:core:1.4.0'
// to wait flow
androidTestImplementation("app.cash.turbine:turbine:0.6.1")

Expand All @@ -94,16 +96,15 @@ dependencies {
kapt "com.google.dagger:hilt-android-compiler:2.37"
implementation "androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha03"
kapt "androidx.hilt:hilt-compiler:1.0.0"
implementation 'androidx.hilt:hilt-navigation-compose:1.0.0-beta01'
implementation 'androidx.hilt:hilt-navigation-compose:1.0.0'

// Datetime better than util Date
implementation "org.jetbrains.kotlinx:kotlinx-datetime:0.3.1"

// Room
def room_version = "2.4.0-alpha03"
def room_version = "2.4.1"
implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version"

// Kotlin Extensions and Coroutines support for Room
implementation "androidx.room:room-ktx:$room_version"
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ package com.wangmir.calliope
import android.content.Context
import androidx.test.core.app.ApplicationProvider
import com.google.common.truth.Truth.assertThat
import com.wangmir.calliope.model.DataRepository
import com.wangmir.calliope.model.adapters.data.DataRepositoryImpl
import com.wangmir.calliope.model.adapters.data.LocalDatabase
import com.wangmir.calliope.model.entities.Date
import com.wangmir.calliope.model.entities.DayLog
import com.wangmir.calliope.model.entities.EmotionLog
import com.wangmir.calliope.model.entities.TextLog
import com.wangmir.calliope.domain.repositories.DataRepository
import com.wangmir.calliope.adapters.data.DataRepositoryImpl
import com.wangmir.calliope.adapters.data.LocalDatabase
import com.wangmir.calliope.domain.entities.Date
import com.wangmir.calliope.domain.entities.DayLog
import com.wangmir.calliope.domain.entities.EmotionLog
import com.wangmir.calliope.domain.entities.TextLog
import com.wangmir.calliope.testutils.getOrAwaitValue
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
Expand Down
39 changes: 39 additions & 0 deletions app/src/androidTest/java/com/wangmir/calliope/UseCasesTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.wangmir.calliope

import com.google.common.truth.Truth.assertThat
import com.wangmir.calliope.adapters.data.FakeDataRepository
import com.wangmir.calliope.domain.usecases.GetDayLogList
import com.wangmir.calliope.domain.util.DayLogFilter
import com.wangmir.calliope.domain.util.OrderType
import com.wangmir.calliope.testutils.getOrAwaitValue
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.runBlocking
import org.junit.jupiter.api.Test

@ExperimentalCoroutinesApi
class UseCasesTest {

private val getDayLogList get() = GetDayLogList(FakeDataRepository())

@Test
fun testGetDayLogListByYear() = runBlocking {
val uc = getDayLogList
var filter = DayLogFilter.Year(OrderType.Ascending, 2021)
var result = uc(filter).getOrAwaitValue(this, dispatcher = Dispatchers.IO)
assertThat(result).isNotNull()
result.forEach {
assertThat(it.date.year).isEqualTo(2021)
}

assertThat(result[0].date.toInt()).isLessThan(result[1].date.toInt())

filter = DayLogFilter.Year(OrderType.Descending, 2021)
result = uc(filter).getOrAwaitValue(this, dispatcher = Dispatchers.IO)
result.forEach {
assertThat(it.date.year).isEqualTo(2021)
}

assertThat(result[0].date.toInt()).isGreaterThan(result[1].date.toInt())
}
}
2 changes: 2 additions & 0 deletions app/src/main/java/com/wangmir/calliope/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import com.wangmir.calliope.ui.theme.CalliopeTheme
import com.wangmir.calliope.ui.view.Home
import dagger.hilt.android.AndroidEntryPoint

@ExperimentalMaterialApi
@AndroidEntryPoint
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.wangmir.calliope.model.adapters.data
package com.wangmir.calliope.adapters.data

import androidx.room.Delete
import androidx.room.Insert
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package com.wangmir.calliope.model.adapters.data
package com.wangmir.calliope.adapters.data

import com.wangmir.calliope.model.DataRepository
import com.wangmir.calliope.model.entities.DayLog
import com.wangmir.calliope.model.entities.EmotionLog
import com.wangmir.calliope.domain.repositories.DataRepository
import com.wangmir.calliope.domain.entities.DayLog
import com.wangmir.calliope.domain.entities.EmotionLog
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.datetime.LocalDate
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package com.wangmir.calliope.model.adapters.data
package com.wangmir.calliope.adapters.data

import androidx.room.Dao
import androidx.room.Query
import com.wangmir.calliope.model.entities.Date
import com.wangmir.calliope.model.entities.DayLog
import com.wangmir.calliope.model.entities.EmotionLog
import com.wangmir.calliope.domain.entities.Date
import com.wangmir.calliope.domain.entities.DayLog
import com.wangmir.calliope.domain.entities.EmotionLog
import kotlinx.coroutines.flow.Flow
import kotlinx.datetime.LocalDate

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package com.wangmir.calliope.adapters.data

import com.wangmir.calliope.domain.entities.Date
import com.wangmir.calliope.domain.entities.DayLog
import com.wangmir.calliope.domain.entities.EmotionLog
import com.wangmir.calliope.domain.entities.TextLog
import com.wangmir.calliope.domain.repositories.DataRepository
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOf
import kotlinx.datetime.LocalDate

class FakeDataRepository : DataRepository {

companion object {
const val MOCK_KEYWORD = "MOCK_KEYWORD"
}

val list = mutableListOf<DayLog>()
val mockData = DayLog.getMockDayLog()

init {
// year 2021
list.add(mockData.copy(date = Date(2021, 10, 30)))
list.add(mockData.copy(date = Date(2021, 9, 28)))

// year 2022
list.add(mockData.copy(date = Date(2022, 1, 21)))
list.add(mockData.copy(date = Date(2022, 2, 28)))

// keyword has "MOCK_KEYWORD"
list.add(mockData.copy(textLog = TextLog(MOCK_KEYWORD)))
list.add(mockData.copy(textLog = TextLog(MOCK_KEYWORD + "tail misc text")))

// emotion is Fear
list.add(mockData.copy(emotionLog = EmotionLog.Fear))
}

override suspend fun insertDayLog(dayLog: DayLog) {
list.add(dayLog)
}

override suspend fun getDayLog(date: LocalDate): DayLog {
return list.find { it.date == Date(date) }!!
}

override suspend fun deleteDayLog(date: LocalDate) {
list.removeIf { it.date == Date(date) }
}

override fun getDayLogsByYear(year: Int): Flow<List<DayLog>> {
return flowOf(list.filter { it.date.year == year })
}

override fun getDayLogsByKeyword(keyword: String): Flow<List<DayLog>> {
return flowOf(list.filter { it.textLog.text.contains(keyword) })
}

override fun getDayLogsByEmotion(emotionLog: EmotionLog): Flow<List<DayLog>> {
return flowOf(list.filter { it.emotionLog == emotionLog })
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package com.wangmir.calliope.model.adapters.data
package com.wangmir.calliope.adapters.data

import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import com.wangmir.calliope.model.entities.DayLog
import com.wangmir.calliope.domain.entities.DayLog

@Database(
entities = [DayLog::class],
Expand Down
16 changes: 12 additions & 4 deletions app/src/main/java/com/wangmir/calliope/di/AppModule.kt
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package com.wangmir.calliope.di

import android.app.Application
import com.wangmir.calliope.model.DataRepository
import com.wangmir.calliope.model.adapters.data.DataRepositoryImpl
import com.wangmir.calliope.model.adapters.data.LocalDatabase
import com.wangmir.calliope.adapters.data.FakeDataRepository
import com.wangmir.calliope.adapters.data.LocalDatabase
import com.wangmir.calliope.domain.repositories.DataRepository
import com.wangmir.calliope.domain.usecases.GetDayLogList
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
Expand All @@ -20,5 +21,12 @@ object AppModule {

@Provides
@Singleton
fun provideDataRepository(db: LocalDatabase): DataRepository = DataRepositoryImpl(db.dayLogDao)
fun provideDataRepository(db: LocalDatabase): DataRepository = FakeDataRepository()
// TODO: until make create dayLog view, fake repository will be used as list of view.
// fun provideDataRepository(db: LocalDatabase): DataRepository = DataRepositoryImpl(db.dayLogDao)

@Provides
@Singleton
fun provideGetDayLogList(dataRepository: DataRepository): GetDayLogList =
GetDayLogList(dataRepository)
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.wangmir.calliope.model.entities
package com.wangmir.calliope.domain.entities

import androidx.room.Embedded
import androidx.room.Entity
Expand Down Expand Up @@ -44,4 +44,8 @@ data class Date (
override fun toString(): String {
return "$year.$month.$dayOfMonth."
}

fun toInt(): Int {
return "$year$month$dayOfMonth".toInt()
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.wangmir.calliope.model.entities
package com.wangmir.calliope.domain.entities

enum class EmotionLog (val value: String) {
NotSet("none"),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.wangmir.calliope.model.entities
package com.wangmir.calliope.domain.entities

data class SttLog(
val sttText: String
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.wangmir.calliope.model.entities
package com.wangmir.calliope.domain.entities

data class TextLog(
val text: String
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.wangmir.calliope.model.entities
package com.wangmir.calliope.domain.entities

data class VoiceLog(
val audioFilePath: String
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.wangmir.calliope.model
package com.wangmir.calliope.domain.repositories

import com.wangmir.calliope.model.entities.DayLog
import com.wangmir.calliope.model.entities.EmotionLog
import com.wangmir.calliope.domain.entities.DayLog
import com.wangmir.calliope.domain.entities.EmotionLog
import kotlinx.coroutines.flow.Flow
import kotlinx.datetime.LocalDate

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.wangmir.calliope.domain.usecases

import com.wangmir.calliope.domain.entities.DayLog
import com.wangmir.calliope.domain.repositories.DataRepository
import com.wangmir.calliope.domain.util.DayLogFilter
import com.wangmir.calliope.domain.util.OrderType
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map

class GetDayLogList(
private val dataRepository: DataRepository
) {
operator fun invoke(filter: DayLogFilter): Flow<List<DayLog>> {
val logs = when (filter) {
is DayLogFilter.Year -> dataRepository.getDayLogsByYear(filter.year)
is DayLogFilter.Keyword -> dataRepository.getDayLogsByKeyword(filter.keyword)
is DayLogFilter.Emotion -> dataRepository.getDayLogsByEmotion(filter.emotion)
}
return logs.map { dayLogs ->
when (filter.orderType) {
is OrderType.Ascending -> dayLogs.sortedBy { it.date.toInt() }
is OrderType.Descending -> dayLogs.sortedByDescending { it.date.toInt() }
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.wangmir.calliope.domain.util

import com.wangmir.calliope.domain.entities.EmotionLog

sealed class DayLogFilter(val orderType: OrderType) {
class Year(orderType: OrderType, val year: Int): DayLogFilter(orderType)
class Keyword(orderType: OrderType, val keyword: String): DayLogFilter(orderType)
class Emotion(orderType: OrderType, val emotion: EmotionLog): DayLogFilter(orderType)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.wangmir.calliope.domain.util

sealed class OrderType {
object Ascending: OrderType()
object Descending: OrderType()
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.wangmir.calliope.viewmodels
package com.wangmir.calliope.presentation

import androidx.lifecycle.ViewModel
import dagger.hilt.android.lifecycle.HiltViewModel
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.wangmir.calliope.presentation.list

import com.wangmir.calliope.domain.entities.DayLog
import com.wangmir.calliope.domain.util.DayLogFilter

sealed class DayLogListEvent {
data class Filter(val dayLogFilter: DayLogFilter): DayLogListEvent()
data class DeleteNote(val dayLog: DayLog): DayLogListEvent()
object RestoreNote: DayLogListEvent()
object ToggleOrderSection: DayLogListEvent()
}
Loading

0 comments on commit 36b2d53

Please sign in to comment.