From 998e3d7d73c099fc1a5691bf0b373e72b9acdfa9 Mon Sep 17 00:00:00 2001 From: beomjo Date: Tue, 27 Jul 2021 02:46:34 +0900 Subject: [PATCH 001/273] =?UTF-8?q?chore:=20Git=20ignore=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 5 +++++ buildSrc/.gitignore | 4 ++++ 2 files changed, 9 insertions(+) create mode 100644 buildSrc/.gitignore diff --git a/.gitignore b/.gitignore index aa724b7..c1a448e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ *.iml .gradle /local.properties +/.idea +/.idea/ /.idea/caches /.idea/libraries /.idea/modules.xml @@ -13,3 +15,6 @@ .externalNativeBuild .cxx local.properties +.idea/misc.xml +.idea/gradle.xml +.idea/compiler.xml diff --git a/buildSrc/.gitignore b/buildSrc/.gitignore new file mode 100644 index 0000000..92c8f7d --- /dev/null +++ b/buildSrc/.gitignore @@ -0,0 +1,4 @@ +/.gradle +/build +buildSrc.i* +servers/out From 169be711e28f84b0412844faefa0209cb20e4f81 Mon Sep 17 00:00:00 2001 From: beomjo Date: Tue, 27 Jul 2021 02:51:25 +0900 Subject: [PATCH 002/273] =?UTF-8?q?build:=20Kotlin=20DSL=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD,=20buildSrc=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 45 --------- app/build.gradle.kts | 56 +++++++++++ app/proguard-rules.pro | 2 +- .../kakao/search/ExampleInstrumentedTest.kt | 24 ----- .../io/beomjo/kakao/search/MainActivity.kt | 0 build.gradle | 27 ------ build.gradle.kts | 10 ++ buildSrc/build.gradle.kts | 19 ++++ buildSrc/src/main/kotlin/Dependency.kt | 92 +++++++++++++++++++ buildSrc/src/main/kotlin/Project.kt | 35 +++++++ settings.gradle | 2 - settings.gradle.kts | 4 + version.properties | 2 + 13 files changed, 219 insertions(+), 99 deletions(-) delete mode 100644 app/build.gradle create mode 100644 app/build.gradle.kts delete mode 100644 app/src/androidTest/java/io/beomjo/kakao/search/ExampleInstrumentedTest.kt rename app/src/main/{java => kotlin}/io/beomjo/kakao/search/MainActivity.kt (100%) delete mode 100644 build.gradle create mode 100644 build.gradle.kts create mode 100644 buildSrc/build.gradle.kts create mode 100644 buildSrc/src/main/kotlin/Dependency.kt create mode 100644 buildSrc/src/main/kotlin/Project.kt delete mode 100644 settings.gradle create mode 100644 settings.gradle.kts create mode 100644 version.properties diff --git a/app/build.gradle b/app/build.gradle deleted file mode 100644 index 0130579..0000000 --- a/app/build.gradle +++ /dev/null @@ -1,45 +0,0 @@ -plugins { - id 'com.android.application' - id 'kotlin-android' -} - -android { - compileSdkVersion 30 - buildToolsVersion "30.0.3" - - defaultConfig { - applicationId "io.beomjo.kakao.search" - minSdkVersion 16 - targetSdkVersion 30 - versionCode 1 - versionName "1.0" - - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - } - - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - } - } - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - kotlinOptions { - jvmTarget = '1.8' - } -} - -dependencies { - - implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" - implementation 'androidx.core:core-ktx:1.6.0' - implementation 'androidx.appcompat:appcompat:1.3.0' - implementation 'com.google.android.material:material:1.4.0' - implementation 'androidx.constraintlayout:constraintlayout:2.0.4' - testImplementation 'junit:junit:4.+' - androidTestImplementation 'androidx.test.ext:junit:1.1.3' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' -} \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts new file mode 100644 index 0000000..c460bbf --- /dev/null +++ b/app/build.gradle.kts @@ -0,0 +1,56 @@ +plugins { + android + `kotlin-android` +} + +val version = Project.Version.value + +android { + compileSdkVersion(Project.Config.ANDROID_COMPILE) + buildToolsVersion = Project.Config.BUILD_TOOL + + defaultConfig { + applicationId = "io.beomjo.kakao.search" + minSdkVersion(Project.Config.ANDROID_MIN) + targetSdkVersion(Project.Config.ANDROID_TARGET) + vectorDrawables.useSupportLibrary = true + versionCode = version.code + versionName = version.name + + testInstrumentationRunner = Dependency.Test.ANDROID_JUNIT_RUNNER + } + + buildTypes { + getByName("release") { + minifyEnabled(false) + proguardFiles( + getDefaultProguardFile( + "proguard-android-optimize.txt" + ), + "proguard-rules.pro" + ) + } + } + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + + kotlinOptions { + jvmTarget = JavaVersion.VERSION_1_8.toString() + } +} + +dependencies { + implementation(Dependency.Kotlin.SDK) + implementation(Dependency.KTX.CORE) + implementation(Dependency.AndroidX.APP_COMPAT) + implementation(Dependency.AndroidX.MATERIAL) + implementation(Dependency.AndroidX.CONSTRAINT_LAYOUT) + + testImplementation(Dependency.Test.JUNIT) + + androidTestImplementation(Dependency.AndroidTest.TEST_RUNNER) + androidTestImplementation(Dependency.AndroidTest.ESPRESSO_CORE) +} diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 481bb43..ff59496 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -1,6 +1,6 @@ # Add project specific ProGuard rules here. # You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. +# proguardFiles setting in build.gradle.kts. # # For more details, see # http://developer.android.com/guide/developing/tools/proguard.html diff --git a/app/src/androidTest/java/io/beomjo/kakao/search/ExampleInstrumentedTest.kt b/app/src/androidTest/java/io/beomjo/kakao/search/ExampleInstrumentedTest.kt deleted file mode 100644 index 39bf646..0000000 --- a/app/src/androidTest/java/io/beomjo/kakao/search/ExampleInstrumentedTest.kt +++ /dev/null @@ -1,24 +0,0 @@ -package io.beomjo.kakao.search - -import androidx.test.platform.app.InstrumentationRegistry -import androidx.test.ext.junit.runners.AndroidJUnit4 - -import org.junit.Test -import org.junit.runner.RunWith - -import org.junit.Assert.* - -/** - * Instrumented test, which will execute on an Android device. - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -@RunWith(AndroidJUnit4::class) -class ExampleInstrumentedTest { - @Test - fun useAppContext() { - // Context of the app under test. - val appContext = InstrumentationRegistry.getInstrumentation().targetContext - assertEquals("io.beomjo.kakao.search", appContext.packageName) - } -} \ No newline at end of file diff --git a/app/src/main/java/io/beomjo/kakao/search/MainActivity.kt b/app/src/main/kotlin/io/beomjo/kakao/search/MainActivity.kt similarity index 100% rename from app/src/main/java/io/beomjo/kakao/search/MainActivity.kt rename to app/src/main/kotlin/io/beomjo/kakao/search/MainActivity.kt diff --git a/build.gradle b/build.gradle deleted file mode 100644 index e0dc4aa..0000000 --- a/build.gradle +++ /dev/null @@ -1,27 +0,0 @@ -// Top-level build file where you can add configuration options common to all sub-projects/modules. -buildscript { - ext.kotlin_version = "1.5.21" - repositories { - google() - mavenCentral() - } - dependencies { - classpath "com.android.tools.build:gradle:4.2.2" - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - - // NOTE: Do not place your application dependencies here; they belong - // in the individual module build.gradle files - } -} - -allprojects { - repositories { - google() - mavenCentral() - jcenter() // Warning: this repository is going to shut down soon - } -} - -task clean(type: Delete) { - delete rootProject.buildDir -} \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000..693ec32 --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,10 @@ +subprojects { + repositories { + google() + mavenCentral() + } +} + +tasks.register("clean", Delete::class) { + delete(rootProject.buildDir) +} diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts new file mode 100644 index 0000000..09cafd9 --- /dev/null +++ b/buildSrc/build.gradle.kts @@ -0,0 +1,19 @@ +plugins { + `kotlin-dsl` +} + +repositories { + google() + mavenCentral() +} + +object PluginVersion { + const val GRADLE = "4.2.2" + const val KOTLIN = "1.5.21" + +} + +dependencies { + implementation("com.android.tools.build:gradle:${PluginVersion.GRADLE}") + implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:${PluginVersion.KOTLIN}") +} diff --git a/buildSrc/src/main/kotlin/Dependency.kt b/buildSrc/src/main/kotlin/Dependency.kt new file mode 100644 index 0000000..a61afe2 --- /dev/null +++ b/buildSrc/src/main/kotlin/Dependency.kt @@ -0,0 +1,92 @@ +object Dependency { + + object Kotlin { + const val SDK = "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.5.21" + const val COROUTINE_CORE = "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.1" + const val COROUTINE_ANDROID = "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.1" + const val COROUTINE_PLAY_SERVICE = "org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.5.1" + const val REFLECTION = "org.jetbrains.kotlin:kotlin-reflect:1.5.21" + } + + object AndroidX { + const val MATERIAL = "androidx.compose.material:material:1.0.0-rc02" + const val CONSTRAINT_LAYOUT = "androidx.constraintlayout:constraintlayout:2.1.0-rc01" + const val APP_COMPAT = "androidx.appcompat:appcompat:1.3.1" + const val SWIPE_REFRESH_LAYOUT = "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0" + const val MEDIA = "androidx.media:media:1.4.0" + } + + object KTX { + const val CORE = "androidx.core:core-ktx:1.7.0-alpha01" + const val LIFECYCLE_VIEWMODEL = "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + const val LIFECYCLE_LIVEDATA = "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + const val ACTIVITY = "androidx.activity:activity-ktx:1.3.0-rc02" + const val FRAGMENT = "androidx.fragment:fragment-ktx:1.3.6" + } + + object Google { + const val MATERIAL = "com.google.android.material:material:1.3.0" + const val GSON = "com.google.code.gson:gson:2.8.7" + const val OSS_LISENCE = "com.google.android.gms:play-services-oss-licenses:17.0.0" + } + + object Firebase { + const val BOM = "com.google.firebase:firebase-bom:28.3.0" + const val AUTH = "com.google.firebase:firebase-auth-ktx" + const val FIRESTORE = "com.google.firebase:firebase-firestore-ktx" + const val GMS_PLAY_SERVICE_AUTH = "com.google.android.gms:play-services-auth:19.2.0" + const val STORAGE = "com.google.firebase:firebase-storage-ktx" + const val CRASHLYTICS = "com.google.firebase:firebase-crashlytics" + } + + object Rx { + const val RX_JAVA = "io.reactivex.rxjava2:rxjava:2.2.17" + const val RX_ANDROID = "io.reactivex.rxjava2:rxandroid:2.2.1" + const val RX_KOTLIN = "io.reactivex.rxjava2:rxkotlin:2.4.0" + const val RX_BINDING = "com.jakewharton.rxbinding2:rxbinding-kotlin:2.2.0" + + } + + object Test { + const val JUNIT = "junit:junit:4.13.2" + const val ARCH_CORE = "androidx.arch.core:core-testing:2.1.0" + const val ANDROIDX_TEST_CORE = "androidx.test:core:1.4.0-beta02" + const val COROUTINE_TEST = "org.jetbrains.kotlinx:kotlinx-coroutines-test:1.5.1" + const val ANDROID_JUNIT_RUNNER = "AndroidJUnitRunner" + const val MOCKK = "io.mockk:mockk:1.12.0" + } + + object AndroidTest { + const val TEST_RUNNER = "androidx.test:runner:1.4.0" + const val ESPRESSO_CORE = "androidx.test.espresso:espresso-core:3.4.0" + } + + object OkHttp { + const val CORE = "com.squareup.okhttp3:okhttp:5.0.0-alpha.2" + const val LOGGING_INTERCEPTOR = "com.squareup.okhttp3:logging-interceptor:5.0.0-alpha.2" + } + + object Retrofit { + const val CORE = "com.squareup.retrofit2:retrofit:2.9.0" + const val CONVERT_GSON = "com.squareup.retrofit2:converter-gson:2.9.0" + } + + object Glide { + const val CORE = "com.github.bumptech.glide:glide:4.12.0" + const val APT = "com.github.bumptech.glide:compiler:4.12.0" + } + + object Lottie { + const val CORE = "com.airbnb.android:lottie:3.7.2" + } + + object Hilt { + const val CORE = "com.google.dagger:hilt-android:2.37" + const val APT = "com.google.dagger:hilt-android-compiler:2.37" + } + + // Etc + const val SHIMMER = "com.facebook.shimmer:shimmer:0.5.0" + const val BINDABLES = "com.github.skydoves:bindables:1.0.8" + const val GOOGLE_BUTTON ="com.shobhitpuri.custombuttons:google-signin:1.0.0" +} diff --git a/buildSrc/src/main/kotlin/Project.kt b/buildSrc/src/main/kotlin/Project.kt new file mode 100644 index 0000000..06923a6 --- /dev/null +++ b/buildSrc/src/main/kotlin/Project.kt @@ -0,0 +1,35 @@ +import java.io.FileInputStream +import java.util.* + +object Project { + + object Config { + const val ANDROID_COMPILE = 30 + const val ANDROID_TARGET = 30 + const val ANDROID_MIN = 21 + const val BUILD_TOOL = "30.0.3" + } + + object Version { + private const val VERSION_FILE_NAME = "version.properties" + + data class VersionProperty( + val code: Int, + val name: String + ) + + private fun getVersionProperty(): VersionProperty { + val prop = loadVersionVersionPropertyFile() + return VersionProperty( + prop.getProperty("version.code", "1").toInt(), + prop.getProperty("version.name", "1") + ) + } + + private fun loadVersionVersionPropertyFile(): Properties { + FileInputStream(VERSION_FILE_NAME).use { return Properties().apply { load(it) } } + } + + val value = getVersionProperty() + } +} diff --git a/settings.gradle b/settings.gradle deleted file mode 100644 index 161f479..0000000 --- a/settings.gradle +++ /dev/null @@ -1,2 +0,0 @@ -rootProject.name = "kakao-search" -include ':app' diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 0000000..6ab6ca3 --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,4 @@ +rootProject.name = "Kakao Search" +include(":app") + + diff --git a/version.properties b/version.properties new file mode 100644 index 0000000..eef15ee --- /dev/null +++ b/version.properties @@ -0,0 +1,2 @@ +version.code=2021072701 +version.name=1.0.0 From f93e04cc56239507957f119af5ac5dad06d16bea Mon Sep 17 00:00:00 2001 From: beomjo Date: Wed, 28 Jul 2021 00:45:02 +0900 Subject: [PATCH 003/273] build: Gradle 7.1.1 --- gradle/wrapper/gradle-wrapper.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 58fd375..49bd583 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Fri Jul 23 23:35:06 KST 2021 +#Wed Jul 28 00:36:08 KST 2021 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.1.1-bin.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME From 05a22e2dc66de6579d74498da082eb5c834e3d30 Mon Sep 17 00:00:00 2001 From: beomjo Date: Wed, 28 Jul 2021 02:54:51 +0900 Subject: [PATCH 004/273] =?UTF-8?q?build:=20Domain,=20Data=20Module=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle.kts | 3 +++ data/.gitignore | 1 + data/build.gradle.kts | 7 +++++++ data/src/main/kotlin/io/beomjo/kakao/search/.gitkeep | 0 domain/.gitignore | 1 + domain/build.gradle.kts | 7 +++++++ domain/src/main/kotlin/io/beomjo/kakao/search/.gitkeep | 0 settings.gradle.kts | 8 +++++--- 8 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 data/.gitignore create mode 100644 data/build.gradle.kts create mode 100644 data/src/main/kotlin/io/beomjo/kakao/search/.gitkeep create mode 100644 domain/.gitignore create mode 100644 domain/build.gradle.kts create mode 100644 domain/src/main/kotlin/io/beomjo/kakao/search/.gitkeep diff --git a/app/build.gradle.kts b/app/build.gradle.kts index c460bbf..969d5b8 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -43,6 +43,9 @@ android { } dependencies { + implementation(project(":domain")) + implementation(project(":data")) + implementation(Dependency.Kotlin.SDK) implementation(Dependency.KTX.CORE) implementation(Dependency.AndroidX.APP_COMPAT) diff --git a/data/.gitignore b/data/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/data/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/data/build.gradle.kts b/data/build.gradle.kts new file mode 100644 index 0000000..38ac923 --- /dev/null +++ b/data/build.gradle.kts @@ -0,0 +1,7 @@ +plugins { + `android-library` +} + +dependencies { + implementation(project(":domain")) +} diff --git a/data/src/main/kotlin/io/beomjo/kakao/search/.gitkeep b/data/src/main/kotlin/io/beomjo/kakao/search/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/domain/.gitignore b/domain/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/domain/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/domain/build.gradle.kts b/domain/build.gradle.kts new file mode 100644 index 0000000..b3f6c19 --- /dev/null +++ b/domain/build.gradle.kts @@ -0,0 +1,7 @@ +plugins { + kotlin +} + +dependencies { + +} diff --git a/domain/src/main/kotlin/io/beomjo/kakao/search/.gitkeep b/domain/src/main/kotlin/io/beomjo/kakao/search/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/settings.gradle.kts b/settings.gradle.kts index 6ab6ca3..a636130 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,4 +1,6 @@ rootProject.name = "Kakao Search" -include(":app") - - +include( + ":app", + ":domain", + ":data" +) From 59616d2a233e81cd98620a495920f0218e8605cd Mon Sep 17 00:00:00 2001 From: beomjo Date: Wed, 28 Jul 2021 03:00:45 +0900 Subject: [PATCH 005/273] =?UTF-8?q?build:=20detekt=20=EC=84=B8=ED=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle.kts | 1 + buildSrc/build.gradle.kts | 3 ++- .../src/main/kotlin/detekt-setting.gradle.kts | 25 +++++++++++++++++++ data/build.gradle.kts | 1 + detekt.yml | 2 ++ domain/build.gradle.kts | 1 + 6 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 buildSrc/src/main/kotlin/detekt-setting.gradle.kts create mode 100644 detekt.yml diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 969d5b8..6923ba5 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,6 +1,7 @@ plugins { android `kotlin-android` + `detekt-setting` } val version = Project.Version.value diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 09cafd9..c843b07 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -10,10 +10,11 @@ repositories { object PluginVersion { const val GRADLE = "4.2.2" const val KOTLIN = "1.5.21" - + const val DETEKT = "1.17.1" } dependencies { implementation("com.android.tools.build:gradle:${PluginVersion.GRADLE}") implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:${PluginVersion.KOTLIN}") + implementation("io.gitlab.arturbosch.detekt:detekt-gradle-plugin:${PluginVersion.DETEKT}") } diff --git a/buildSrc/src/main/kotlin/detekt-setting.gradle.kts b/buildSrc/src/main/kotlin/detekt-setting.gradle.kts new file mode 100644 index 0000000..d2fbe10 --- /dev/null +++ b/buildSrc/src/main/kotlin/detekt-setting.gradle.kts @@ -0,0 +1,25 @@ +plugins { + id("io.gitlab.arturbosch.detekt") +} + +detekt { + buildUponDefaultConfig = true + allRules = true + autoCorrect = true + config = files( + "${rootProject.projectDir}/detekt.yml" + ) + + reports { + html.enabled = true + txt.enabled = false + sarif.enabled = false + xml.enabled = true + } +} + +dependencies { + detektPlugins("io.gitlab.arturbosch.detekt:detekt-formatting:1.17.1") +} + + diff --git a/data/build.gradle.kts b/data/build.gradle.kts index 38ac923..baf2038 100644 --- a/data/build.gradle.kts +++ b/data/build.gradle.kts @@ -1,5 +1,6 @@ plugins { `android-library` + `detekt-setting` } dependencies { diff --git a/detekt.yml b/detekt.yml new file mode 100644 index 0000000..07afc5a --- /dev/null +++ b/detekt.yml @@ -0,0 +1,2 @@ +build: + maxIssues: 0 \ No newline at end of file diff --git a/domain/build.gradle.kts b/domain/build.gradle.kts index b3f6c19..1dd658e 100644 --- a/domain/build.gradle.kts +++ b/domain/build.gradle.kts @@ -1,5 +1,6 @@ plugins { kotlin + `detekt-setting` } dependencies { From 12300b4b63b8f09b5203f654d7a0448857f0cc59 Mon Sep 17 00:00:00 2001 From: beomjo Date: Wed, 28 Jul 2021 03:15:25 +0900 Subject: [PATCH 006/273] =?UTF-8?q?build:=20Data=20module=20android=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- data/build.gradle.kts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/data/build.gradle.kts b/data/build.gradle.kts index baf2038..353b5be 100644 --- a/data/build.gradle.kts +++ b/data/build.gradle.kts @@ -3,6 +3,16 @@ plugins { `detekt-setting` } +android { + compileSdkVersion(Project.Config.ANDROID_COMPILE) + + defaultConfig { + minSdkVersion(Project.Config.ANDROID_MIN) + targetSdkVersion(Project.Config.ANDROID_TARGET) + } +} + + dependencies { implementation(project(":domain")) } From d34eccaeba2076f88ff640ed931d4ede9427a433 Mon Sep 17 00:00:00 2001 From: beomjo Date: Wed, 28 Jul 2021 03:16:29 +0900 Subject: [PATCH 007/273] =?UTF-8?q?build:=20Workflow=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/android.yml | 143 ++++++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 .github/workflows/android.yml diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml new file mode 100644 index 0000000..0468df7 --- /dev/null +++ b/.github/workflows/android.yml @@ -0,0 +1,143 @@ +name: Android CI + +on: + # push: + # branches: [ main, develop ] + pull_request: + branches: [ main, develop ] + +jobs: + android_lint: + name: AndroidLint + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: set up JDK 8 + uses: actions/setup-java@v2 + with: + java-version: '8' + distribution: 'adopt' + + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Run Android Lint + run: ./gradlew lintRelease + + - name: Workflow Failed Notification to Slack + uses: rtCamp/action-slack-notify@v2 + if: ${{ failure() }} + env: + SLACK_CHANNEL: github-notification + SLACK_COLOR: ${{ job.status }} + SLACK_ICON: https://user-images.githubusercontent.com/39984656/126071498-60496f8c-4971-4bb1-9609-2cab573c1079.png + SLACK_MESSAGE: '[${{ github.workflow }}.${{ github.action }}] Failed!! :rage:' + SLACK_TITLE: Message + SLACK_USERNAME: Github Notification + SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} + + + detekt: + name: detekt + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: set up JDK 8 + uses: actions/setup-java@v2 + with: + java-version: '8' + distribution: 'adopt' + + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Run detekt + run: ./gradlew detekt + + - name: Workflow Failed Notification to Slack + uses: rtCamp/action-slack-notify@v2 + if: ${{ failure() }} + env: + SLACK_CHANNEL: github-notification + SLACK_COLOR: ${{ job.status }} + SLACK_ICON: https://user-images.githubusercontent.com/39984656/126071498-60496f8c-4971-4bb1-9609-2cab573c1079.png + SLACK_MESSAGE: '[${{ github.workflow }}.${{ github.action }}] Failed!! :rage:' + SLACK_TITLE: Message + SLACK_USERNAME: Github Notification + SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} + + + unit_test: + name: UnitTest + needs: [ android_lint, ktlint, detekt ] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: set up JDK 8 + uses: actions/setup-java@v2 + with: + java-version: '8' + distribution: 'adopt' + + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Unit Test + run: ./gradlew testDebugUnitTest + + - name: Android Test Report + uses: asadmansr/android-test-report-action@v1.2.0 + if: ${{ always() }} + with: + name: reports + path: app/build/test-results + + - name: Workflow Failed Notification to Slack + uses: rtCamp/action-slack-notify@v2 + if: ${{ failure() }} + env: + SLACK_CHANNEL: github-notification + SLACK_COLOR: ${{ job.status }} + SLACK_ICON: https://user-images.githubusercontent.com/39984656/126071498-60496f8c-4971-4bb1-9609-2cab573c1079.png + SLACK_MESSAGE: '[${{ github.workflow }}.${{ github.action }}] Failed!! :rage:' + SLACK_TITLE: Message + SLACK_USERNAME: Github Notification + SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} + + + build: + name: Build + needs: [ android_lint, ktlint, detekt, unit_test ] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: set up JDK 8 + uses: actions/setup-java@v2 + with: + java-version: '8' + distribution: 'adopt' + + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Clean Project + run: ./gradlew clean --stacktrace + + - name: Build AAB + run: ./gradlew bundleRelease --stacktrace + + - name: Workflow Failed Notification to Slack + uses: rtCamp/action-slack-notify@v2 + if: ${{ failure() }} + env: + SLACK_CHANNEL: github-notification + SLACK_COLOR: ${{ job.status }} + SLACK_ICON: https://user-images.githubusercontent.com/39984656/126071498-60496f8c-4971-4bb1-9609-2cab573c1079.png + SLACK_MESSAGE: '[${{ github.workflow }}.${{ github.action }}] Failed!! :rage:' + SLACK_TITLE: Message + SLACK_USERNAME: Github Notification + SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} \ No newline at end of file From 1e9e61eee749d52582c8b7444ea01020feb45bfb Mon Sep 17 00:00:00 2001 From: beomjo Date: Wed, 28 Jul 2021 03:19:13 +0900 Subject: [PATCH 008/273] =?UTF-8?q?build:=20Workflow=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/android.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 0468df7..72a8374 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -1,8 +1,8 @@ name: Android CI on: - # push: - # branches: [ main, develop ] + push: + branches: [ main, develop ] pull_request: branches: [ main, develop ] From 8f6ae69fa1c422195552e11c6dbd9ea93d1db2a7 Mon Sep 17 00:00:00 2001 From: beomjo Date: Wed, 28 Jul 2021 03:21:12 +0900 Subject: [PATCH 009/273] =?UTF-8?q?build:=20Workflow=20needs=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/android.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 72a8374..7d14b56 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -71,7 +71,7 @@ jobs: unit_test: name: UnitTest - needs: [ android_lint, ktlint, detekt ] + needs: [ android_lint, detekt ] runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 @@ -110,7 +110,7 @@ jobs: build: name: Build - needs: [ android_lint, ktlint, detekt, unit_test ] + needs: [ android_lint, detekt, unit_test ] runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 From 3330da14c2577897ac3ac4ef3fb6750577375ca1 Mon Sep 17 00:00:00 2001 From: beomjo Date: Wed, 28 Jul 2021 03:37:10 +0900 Subject: [PATCH 010/273] =?UTF-8?q?fix:=20=20Lint,=20Detekt=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=EC=82=AC=ED=95=AD=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle.kts | 3 +++ .../io/beomjo/kakao/search/MainActivity.kt | 2 +- app/src/main/res/values-night/themes.xml | 16 ---------------- .../io/beomjo/kakao/search/ExampleUnitTest.kt | 4 ++-- data/src/main/AndroidManifest.xml | 2 ++ 5 files changed, 8 insertions(+), 19 deletions(-) delete mode 100644 app/src/main/res/values-night/themes.xml create mode 100644 data/src/main/AndroidManifest.xml diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 6923ba5..1c1cb69 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -51,8 +51,11 @@ dependencies { implementation(Dependency.KTX.CORE) implementation(Dependency.AndroidX.APP_COMPAT) implementation(Dependency.AndroidX.MATERIAL) + implementation(Dependency.AndroidX.APP_COMPAT) implementation(Dependency.AndroidX.CONSTRAINT_LAYOUT) + implementation(Dependency.Google.MATERIAL) + testImplementation(Dependency.Test.JUNIT) androidTestImplementation(Dependency.AndroidTest.TEST_RUNNER) diff --git a/app/src/main/kotlin/io/beomjo/kakao/search/MainActivity.kt b/app/src/main/kotlin/io/beomjo/kakao/search/MainActivity.kt index cb44bcc..f4d6b37 100644 --- a/app/src/main/kotlin/io/beomjo/kakao/search/MainActivity.kt +++ b/app/src/main/kotlin/io/beomjo/kakao/search/MainActivity.kt @@ -8,4 +8,4 @@ class MainActivity : AppCompatActivity() { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) } -} \ No newline at end of file +} diff --git a/app/src/main/res/values-night/themes.xml b/app/src/main/res/values-night/themes.xml deleted file mode 100644 index c0097d1..0000000 --- a/app/src/main/res/values-night/themes.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - \ No newline at end of file diff --git a/app/src/test/java/io/beomjo/kakao/search/ExampleUnitTest.kt b/app/src/test/java/io/beomjo/kakao/search/ExampleUnitTest.kt index d07715b..32f68dc 100644 --- a/app/src/test/java/io/beomjo/kakao/search/ExampleUnitTest.kt +++ b/app/src/test/java/io/beomjo/kakao/search/ExampleUnitTest.kt @@ -2,7 +2,7 @@ package io.beomjo.kakao.search import org.junit.Test -import org.junit.Assert.* +import org.junit.Assert.assertEquals /** * Example local unit test, which will execute on the development machine (host). @@ -14,4 +14,4 @@ class ExampleUnitTest { fun addition_isCorrect() { assertEquals(4, 2 + 2) } -} \ No newline at end of file +} diff --git a/data/src/main/AndroidManifest.xml b/data/src/main/AndroidManifest.xml new file mode 100644 index 0000000..dc643bd --- /dev/null +++ b/data/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file From 4b71858cc0634565928ce6c4621e6ad165d6a140 Mon Sep 17 00:00:00 2001 From: beomjo Date: Wed, 28 Jul 2021 04:11:57 +0900 Subject: [PATCH 011/273] =?UTF-8?q?build:=20Hilt=20=EC=84=B8=ED=8C=85?= =?UTF-8?q?=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle.kts | 5 ++++- buildSrc/build.gradle.kts | 2 ++ domain/build.gradle.kts | 4 ---- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 1c1cb69..42cac8f 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,6 +1,7 @@ plugins { android `kotlin-android` + `kotlin-kapt` `detekt-setting` } @@ -56,8 +57,10 @@ dependencies { implementation(Dependency.Google.MATERIAL) - testImplementation(Dependency.Test.JUNIT) + implementation(Dependency.Hilt.CORE) + kapt(Dependency.Hilt.APT) + testImplementation(Dependency.Test.JUNIT) androidTestImplementation(Dependency.AndroidTest.TEST_RUNNER) androidTestImplementation(Dependency.AndroidTest.ESPRESSO_CORE) } diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index c843b07..39daea5 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -11,10 +11,12 @@ object PluginVersion { const val GRADLE = "4.2.2" const val KOTLIN = "1.5.21" const val DETEKT = "1.17.1" + const val HILT = "2.38" } dependencies { implementation("com.android.tools.build:gradle:${PluginVersion.GRADLE}") implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:${PluginVersion.KOTLIN}") implementation("io.gitlab.arturbosch.detekt:detekt-gradle-plugin:${PluginVersion.DETEKT}") + implementation("com.google.dagger:hilt-android-gradle-plugin:${PluginVersion.HILT}") } diff --git a/domain/build.gradle.kts b/domain/build.gradle.kts index 1dd658e..a69db24 100644 --- a/domain/build.gradle.kts +++ b/domain/build.gradle.kts @@ -2,7 +2,3 @@ plugins { kotlin `detekt-setting` } - -dependencies { - -} From 040ca54768698d770ec5c1deadbe39cc40f38bde Mon Sep 17 00:00:00 2001 From: beomjo Date: Fri, 30 Jul 2021 00:36:56 +0900 Subject: [PATCH 012/273] =?UTF-8?q?build:=20Submodule=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitmodules | 4 ++++ android-compilation | 1 + settings.gradle.kts | 3 ++- 3 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 .gitmodules create mode 160000 android-compilation diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..f331047 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,4 @@ +[submodule "android-compilation"] + path = android-compilation + url = git@github.com-personal:beomjo/android-compilation.git + branch = main diff --git a/android-compilation b/android-compilation new file mode 160000 index 0000000..ef32211 --- /dev/null +++ b/android-compilation @@ -0,0 +1 @@ +Subproject commit ef3221153e797f6bf6be07bbd777268b4ff55a4f diff --git a/settings.gradle.kts b/settings.gradle.kts index a636130..680c70f 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -2,5 +2,6 @@ rootProject.name = "Kakao Search" include( ":app", ":domain", - ":data" + ":data", + ":android-compilation" ) From 07a74c00f62e745e40160878d846dbf4305b82d7 Mon Sep 17 00:00:00 2001 From: beomjo Date: Fri, 30 Jul 2021 00:37:14 +0900 Subject: [PATCH 013/273] build: Add Dependencies --- app/build.gradle.kts | 29 +++++++++++++++------ buildSrc/src/main/kotlin/AndroidEnv.kt | 7 ++++++ buildSrc/src/main/kotlin/Project.kt | 35 -------------------------- buildSrc/src/main/kotlin/Version.kt | 23 +++++++++++++++++ data/build.gradle.kts | 6 ++--- 5 files changed, 55 insertions(+), 45 deletions(-) create mode 100644 buildSrc/src/main/kotlin/AndroidEnv.kt delete mode 100644 buildSrc/src/main/kotlin/Project.kt create mode 100644 buildSrc/src/main/kotlin/Version.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 42cac8f..0ba9095 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -5,16 +5,16 @@ plugins { `detekt-setting` } -val version = Project.Version.value +val version = Version.getVersionProperty() android { - compileSdkVersion(Project.Config.ANDROID_COMPILE) - buildToolsVersion = Project.Config.BUILD_TOOL + compileSdkVersion(AndroidEnv.ANDROID_COMPILE) + buildToolsVersion = AndroidEnv.BUILD_TOOL defaultConfig { - applicationId = "io.beomjo.kakao.search" - minSdkVersion(Project.Config.ANDROID_MIN) - targetSdkVersion(Project.Config.ANDROID_TARGET) + applicationId = AndroidEnv.APPLICATION_ID + minSdkVersion(AndroidEnv.ANDROID_MIN) + targetSdkVersion(AndroidEnv.ANDROID_TARGET) vectorDrawables.useSupportLibrary = true versionCode = version.code versionName = version.name @@ -49,18 +49,33 @@ dependencies { implementation(project(":data")) implementation(Dependency.Kotlin.SDK) - implementation(Dependency.KTX.CORE) + implementation(Dependency.Kotlin.COROUTINE_CORE) + implementation(Dependency.Kotlin.COROUTINE_ANDROID) + + implementation(Dependency.AndroidX.APP_COMPAT) implementation(Dependency.AndroidX.MATERIAL) implementation(Dependency.AndroidX.APP_COMPAT) implementation(Dependency.AndroidX.CONSTRAINT_LAYOUT) + implementation(Dependency.KTX.CORE) + implementation(Dependency.KTX.LIFECYCLE_LIVEDATA) + implementation(Dependency.KTX.LIFECYCLE_VIEWMODEL) + implementation(Dependency.KTX.ACTIVITY) + implementation(Dependency.KTX.FRAGMENT) + implementation(Dependency.Google.MATERIAL) + implementation(Dependency.Google.GSON) + + implementation(Dependency.Glide.CORE) + kapt(Dependency.Glide.APT) implementation(Dependency.Hilt.CORE) kapt(Dependency.Hilt.APT) testImplementation(Dependency.Test.JUNIT) + testImplementation(Dependency.Test.MOCKK) + testImplementation(Dependency.Test.COROUTINE_TEST) androidTestImplementation(Dependency.AndroidTest.TEST_RUNNER) androidTestImplementation(Dependency.AndroidTest.ESPRESSO_CORE) } diff --git a/buildSrc/src/main/kotlin/AndroidEnv.kt b/buildSrc/src/main/kotlin/AndroidEnv.kt new file mode 100644 index 0000000..e1d3795 --- /dev/null +++ b/buildSrc/src/main/kotlin/AndroidEnv.kt @@ -0,0 +1,7 @@ +object AndroidEnv { + const val APPLICATION_ID ="io.beomjo.kakao.search" + const val ANDROID_COMPILE = 30 + const val ANDROID_TARGET = 30 + const val ANDROID_MIN = 21 + const val BUILD_TOOL = "30.0.3" +} diff --git a/buildSrc/src/main/kotlin/Project.kt b/buildSrc/src/main/kotlin/Project.kt deleted file mode 100644 index 06923a6..0000000 --- a/buildSrc/src/main/kotlin/Project.kt +++ /dev/null @@ -1,35 +0,0 @@ -import java.io.FileInputStream -import java.util.* - -object Project { - - object Config { - const val ANDROID_COMPILE = 30 - const val ANDROID_TARGET = 30 - const val ANDROID_MIN = 21 - const val BUILD_TOOL = "30.0.3" - } - - object Version { - private const val VERSION_FILE_NAME = "version.properties" - - data class VersionProperty( - val code: Int, - val name: String - ) - - private fun getVersionProperty(): VersionProperty { - val prop = loadVersionVersionPropertyFile() - return VersionProperty( - prop.getProperty("version.code", "1").toInt(), - prop.getProperty("version.name", "1") - ) - } - - private fun loadVersionVersionPropertyFile(): Properties { - FileInputStream(VERSION_FILE_NAME).use { return Properties().apply { load(it) } } - } - - val value = getVersionProperty() - } -} diff --git a/buildSrc/src/main/kotlin/Version.kt b/buildSrc/src/main/kotlin/Version.kt new file mode 100644 index 0000000..de6b2ed --- /dev/null +++ b/buildSrc/src/main/kotlin/Version.kt @@ -0,0 +1,23 @@ +import java.io.FileInputStream +import java.util.* + +object Version { + private const val VERSION_FILE_NAME = "version.properties" + + data class VersionProperty( + val code: Int, + val name: String + ) + + fun getVersionProperty(): VersionProperty { + val prop = loadVersionVersionPropertyFile() + return VersionProperty( + prop.getProperty("version.code", "1").toInt(), + prop.getProperty("version.name", "1") + ) + } + + private fun loadVersionVersionPropertyFile(): Properties { + FileInputStream(VERSION_FILE_NAME).use { return Properties().apply { load(it) } } + } +} \ No newline at end of file diff --git a/data/build.gradle.kts b/data/build.gradle.kts index 353b5be..b47790d 100644 --- a/data/build.gradle.kts +++ b/data/build.gradle.kts @@ -4,11 +4,11 @@ plugins { } android { - compileSdkVersion(Project.Config.ANDROID_COMPILE) + compileSdkVersion(AndroidEnv.Config.ANDROID_COMPILE) defaultConfig { - minSdkVersion(Project.Config.ANDROID_MIN) - targetSdkVersion(Project.Config.ANDROID_TARGET) + minSdkVersion(AndroidEnv.Config.ANDROID_MIN) + targetSdkVersion(AndroidEnv.Config.ANDROID_TARGET) } } From a3e70375d381a54209b0f18cf1febfa6adb02ffc Mon Sep 17 00:00:00 2001 From: beomjo Date: Fri, 30 Jul 2021 00:40:08 +0900 Subject: [PATCH 014/273] =?UTF-8?q?build:=20TestDependency=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle.kts | 12 ++++++------ buildSrc/src/main/kotlin/AndroidTestDependency.kt | 4 ++++ buildSrc/src/main/kotlin/Dependency.kt | 14 -------------- buildSrc/src/main/kotlin/TestDependency.kt | 8 ++++++++ data/build.gradle.kts | 6 +++--- 5 files changed, 21 insertions(+), 23 deletions(-) create mode 100644 buildSrc/src/main/kotlin/AndroidTestDependency.kt create mode 100644 buildSrc/src/main/kotlin/TestDependency.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 0ba9095..b9b1ab8 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -19,7 +19,7 @@ android { versionCode = version.code versionName = version.name - testInstrumentationRunner = Dependency.Test.ANDROID_JUNIT_RUNNER + testInstrumentationRunner = TestDependency.ANDROID_JUNIT_RUNNER } buildTypes { @@ -73,9 +73,9 @@ dependencies { implementation(Dependency.Hilt.CORE) kapt(Dependency.Hilt.APT) - testImplementation(Dependency.Test.JUNIT) - testImplementation(Dependency.Test.MOCKK) - testImplementation(Dependency.Test.COROUTINE_TEST) - androidTestImplementation(Dependency.AndroidTest.TEST_RUNNER) - androidTestImplementation(Dependency.AndroidTest.ESPRESSO_CORE) + testImplementation(TestDependency.JUNIT) + testImplementation(TestDependency.MOCKK) + testImplementation(TestDependency.COROUTINE_TEST) + androidTestImplementation(AndroidTestDependency.TEST_RUNNER) + androidTestImplementation(AndroidTestDependency.ESPRESSO_CORE) } diff --git a/buildSrc/src/main/kotlin/AndroidTestDependency.kt b/buildSrc/src/main/kotlin/AndroidTestDependency.kt new file mode 100644 index 0000000..7ac1b1d --- /dev/null +++ b/buildSrc/src/main/kotlin/AndroidTestDependency.kt @@ -0,0 +1,4 @@ +object AndroidTestDependency { + const val TEST_RUNNER = "androidx.test:runner:1.4.0" + const val ESPRESSO_CORE = "androidx.test.espresso:espresso-core:3.4.0" +} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/Dependency.kt b/buildSrc/src/main/kotlin/Dependency.kt index a61afe2..462b260 100644 --- a/buildSrc/src/main/kotlin/Dependency.kt +++ b/buildSrc/src/main/kotlin/Dependency.kt @@ -47,20 +47,6 @@ object Dependency { } - object Test { - const val JUNIT = "junit:junit:4.13.2" - const val ARCH_CORE = "androidx.arch.core:core-testing:2.1.0" - const val ANDROIDX_TEST_CORE = "androidx.test:core:1.4.0-beta02" - const val COROUTINE_TEST = "org.jetbrains.kotlinx:kotlinx-coroutines-test:1.5.1" - const val ANDROID_JUNIT_RUNNER = "AndroidJUnitRunner" - const val MOCKK = "io.mockk:mockk:1.12.0" - } - - object AndroidTest { - const val TEST_RUNNER = "androidx.test:runner:1.4.0" - const val ESPRESSO_CORE = "androidx.test.espresso:espresso-core:3.4.0" - } - object OkHttp { const val CORE = "com.squareup.okhttp3:okhttp:5.0.0-alpha.2" const val LOGGING_INTERCEPTOR = "com.squareup.okhttp3:logging-interceptor:5.0.0-alpha.2" diff --git a/buildSrc/src/main/kotlin/TestDependency.kt b/buildSrc/src/main/kotlin/TestDependency.kt new file mode 100644 index 0000000..c7fb74f --- /dev/null +++ b/buildSrc/src/main/kotlin/TestDependency.kt @@ -0,0 +1,8 @@ +object TestDependency { + const val JUNIT = "junit:junit:4.13.2" + const val ARCH_CORE = "androidx.arch.core:core-testing:2.1.0" + const val ANDROIDX_TEST_CORE = "androidx.test:core:1.4.0-beta02" + const val COROUTINE_TEST = "org.jetbrains.kotlinx:kotlinx-coroutines-test:1.5.1" + const val ANDROID_JUNIT_RUNNER = "AndroidJUnitRunner" + const val MOCKK = "io.mockk:mockk:1.12.0" +} \ No newline at end of file diff --git a/data/build.gradle.kts b/data/build.gradle.kts index b47790d..adc1bf3 100644 --- a/data/build.gradle.kts +++ b/data/build.gradle.kts @@ -4,11 +4,11 @@ plugins { } android { - compileSdkVersion(AndroidEnv.Config.ANDROID_COMPILE) + compileSdkVersion(AndroidEnv.ANDROID_COMPILE) defaultConfig { - minSdkVersion(AndroidEnv.Config.ANDROID_MIN) - targetSdkVersion(AndroidEnv.Config.ANDROID_TARGET) + minSdkVersion(AndroidEnv.ANDROID_MIN) + targetSdkVersion(AndroidEnv.ANDROID_TARGET) } } From de7d32d5766215f5185f2bcb56df1604b9fa3f9b Mon Sep 17 00:00:00 2001 From: beomjo Date: Fri, 30 Jul 2021 00:45:01 +0900 Subject: [PATCH 015/273] =?UTF-8?q?build:=20Room=20Dependency=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle.kts | 3 +++ buildSrc/src/main/kotlin/Dependency.kt | 10 ++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index b9b1ab8..a959f0f 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -73,6 +73,9 @@ dependencies { implementation(Dependency.Hilt.CORE) kapt(Dependency.Hilt.APT) + implementation(Dependency.Room.RUNTIME) + kapt(Dependency.Room.APT) + testImplementation(TestDependency.JUNIT) testImplementation(TestDependency.MOCKK) testImplementation(TestDependency.COROUTINE_TEST) diff --git a/buildSrc/src/main/kotlin/Dependency.kt b/buildSrc/src/main/kotlin/Dependency.kt index 462b260..2ab5cb4 100644 --- a/buildSrc/src/main/kotlin/Dependency.kt +++ b/buildSrc/src/main/kotlin/Dependency.kt @@ -4,7 +4,8 @@ object Dependency { const val SDK = "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.5.21" const val COROUTINE_CORE = "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.1" const val COROUTINE_ANDROID = "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.1" - const val COROUTINE_PLAY_SERVICE = "org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.5.1" + const val COROUTINE_PLAY_SERVICE = + "org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.5.1" const val REFLECTION = "org.jetbrains.kotlin:kotlin-reflect:1.5.21" } @@ -71,8 +72,13 @@ object Dependency { const val APT = "com.google.dagger:hilt-android-compiler:2.37" } + object Room { + const val RUNTIME = "androidx.room:room-runtime:2.3.0" + const val APT = "androidx.room:room-compiler:2.3.0" + } + // Etc const val SHIMMER = "com.facebook.shimmer:shimmer:0.5.0" const val BINDABLES = "com.github.skydoves:bindables:1.0.8" - const val GOOGLE_BUTTON ="com.shobhitpuri.custombuttons:google-signin:1.0.0" + const val GOOGLE_BUTTON = "com.shobhitpuri.custombuttons:google-signin:1.0.0" } From 02d63bb284238da07f86063bfcf419454e04c140 Mon Sep 17 00:00:00 2001 From: beomjo Date: Fri, 30 Jul 2021 00:46:16 +0900 Subject: [PATCH 016/273] build: Add Paging3 Dependency --- app/build.gradle.kts | 2 ++ buildSrc/src/main/kotlin/Dependency.kt | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index a959f0f..09f8d82 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -76,6 +76,8 @@ dependencies { implementation(Dependency.Room.RUNTIME) kapt(Dependency.Room.APT) + implementation(Dependency.Paging3.RUNTIME) + testImplementation(TestDependency.JUNIT) testImplementation(TestDependency.MOCKK) testImplementation(TestDependency.COROUTINE_TEST) diff --git a/buildSrc/src/main/kotlin/Dependency.kt b/buildSrc/src/main/kotlin/Dependency.kt index 2ab5cb4..b27c122 100644 --- a/buildSrc/src/main/kotlin/Dependency.kt +++ b/buildSrc/src/main/kotlin/Dependency.kt @@ -77,6 +77,10 @@ object Dependency { const val APT = "androidx.room:room-compiler:2.3.0" } + object Paging3 { + const val RUNTIME= "androidx.paging:paging-runtime:3.0.0" + } + // Etc const val SHIMMER = "com.facebook.shimmer:shimmer:0.5.0" const val BINDABLES = "com.github.skydoves:bindables:1.0.8" From b9e1a649e4b3d177957537a7f8edffdb6d6d8f22 Mon Sep 17 00:00:00 2001 From: beomjo Date: Fri, 30 Jul 2021 00:48:43 +0900 Subject: [PATCH 017/273] build: Add Navigation Component Dependency --- app/build.gradle.kts | 3 +++ buildSrc/src/main/kotlin/Dependency.kt | 7 ++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 09f8d82..c4931dd 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -78,6 +78,9 @@ dependencies { implementation(Dependency.Paging3.RUNTIME) + implementation(Dependency.Navigation.FRAGMENT) + implementation(Dependency.Navigation.UI) + testImplementation(TestDependency.JUNIT) testImplementation(TestDependency.MOCKK) testImplementation(TestDependency.COROUTINE_TEST) diff --git a/buildSrc/src/main/kotlin/Dependency.kt b/buildSrc/src/main/kotlin/Dependency.kt index b27c122..3f7f470 100644 --- a/buildSrc/src/main/kotlin/Dependency.kt +++ b/buildSrc/src/main/kotlin/Dependency.kt @@ -78,7 +78,12 @@ object Dependency { } object Paging3 { - const val RUNTIME= "androidx.paging:paging-runtime:3.0.0" + const val RUNTIME = "androidx.paging:paging-runtime:3.0.0" + } + + object Navigation { + const val FRAGMENT = "androidx.navigation:navigation-fragment-ktx:2.3.5" + const val UI = "androidx.navigation:navigation-ui-ktx:2.3.5" } // Etc From 22d673790ba9930bc9064939d474ce349c5d2dfb Mon Sep 17 00:00:00 2001 From: beomjo Date: Fri, 30 Jul 2021 00:59:55 +0900 Subject: [PATCH 018/273] build: Gradle Dependency version check --- build.gradle.kts | 4 ++ buildSrc/build.gradle.kts | 3 ++ .../main/kotlin/dependency-check.gradle.kts | 38 +++++++++++++++++++ 3 files changed, 45 insertions(+) create mode 100644 buildSrc/src/main/kotlin/dependency-check.gradle.kts diff --git a/build.gradle.kts b/build.gradle.kts index 693ec32..f2ecfe7 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,3 +1,7 @@ +plugins { + `dependency-check` +} + subprojects { repositories { google() diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 39daea5..119e2e5 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -5,6 +5,7 @@ plugins { repositories { google() mavenCentral() + gradlePluginPortal() } object PluginVersion { @@ -12,6 +13,7 @@ object PluginVersion { const val KOTLIN = "1.5.21" const val DETEKT = "1.17.1" const val HILT = "2.38" + const val DEPENDENCY_CHECKER = "0.39.0" } dependencies { @@ -19,4 +21,5 @@ dependencies { implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:${PluginVersion.KOTLIN}") implementation("io.gitlab.arturbosch.detekt:detekt-gradle-plugin:${PluginVersion.DETEKT}") implementation("com.google.dagger:hilt-android-gradle-plugin:${PluginVersion.HILT}") + implementation("com.github.ben-manes:gradle-versions-plugin:${PluginVersion.DEPENDENCY_CHECKER}") } diff --git a/buildSrc/src/main/kotlin/dependency-check.gradle.kts b/buildSrc/src/main/kotlin/dependency-check.gradle.kts new file mode 100644 index 0000000..9e4e7d1 --- /dev/null +++ b/buildSrc/src/main/kotlin/dependency-check.gradle.kts @@ -0,0 +1,38 @@ +import com.github.benmanes.gradle.versions.updates.DependencyUpdatesTask + +plugins { + id("com.github.ben-manes.versions") +} + +val versioningTasksGroupName = "Dependency tasks" + +fun isNonStable(version: String): Boolean { + val stableKeyword = listOf("RELEASE", "FINAL", "GA").any { version.toUpperCase().contains(it) } + val regex = "^[0-9,.v-]+(-r)?$".toRegex() + val isStable = stableKeyword || regex.matches(version) + return isStable.not() +} + +fun DependencyUpdatesTask.setOptionalParameters() { + checkForGradleUpdate = true + outputFormatter = "html" + outputDir = "app/build/generated/reports/dependencyUpdatesCheck" + reportfileName = "report" +} + +tasks.create("dependencyUpdatesCheck") { + group = versioningTasksGroupName + description = "Check Dependency Updates" + + resolutionStrategy { + componentSelection { + all { + if (isNonStable(candidate.version) && !isNonStable(currentVersion)) { + reject("Release candidate") + } + } + } + } + + setOptionalParameters() +} From da7791ff5aaeddc9843539a7355f70e0253ceade Mon Sep 17 00:00:00 2001 From: beomjo Date: Fri, 30 Jul 2021 01:00:58 +0900 Subject: [PATCH 019/273] build: Branch Push trigger disabled --- .github/workflows/android.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 7d14b56..dc5fbf1 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -1,8 +1,8 @@ name: Android CI on: - push: - branches: [ main, develop ] +# push: +# branches: [ main, develop ] pull_request: branches: [ main, develop ] From 9af838d384a12d17569a1b1aa856142b583139cd Mon Sep 17 00:00:00 2001 From: beomjo Date: Fri, 30 Jul 2021 01:04:28 +0900 Subject: [PATCH 020/273] =?UTF-8?q?build:=20Dependency=20=EC=B5=9C?= =?UTF-8?q?=EC=8B=A0=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- buildSrc/build.gradle.kts | 2 +- buildSrc/src/main/kotlin/Dependency.kt | 10 +++++----- buildSrc/src/main/kotlin/TestDependency.kt | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 119e2e5..87299c9 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -12,7 +12,7 @@ object PluginVersion { const val GRADLE = "4.2.2" const val KOTLIN = "1.5.21" const val DETEKT = "1.17.1" - const val HILT = "2.38" + const val HILT = "2.38.1" const val DEPENDENCY_CHECKER = "0.39.0" } diff --git a/buildSrc/src/main/kotlin/Dependency.kt b/buildSrc/src/main/kotlin/Dependency.kt index 3f7f470..383763a 100644 --- a/buildSrc/src/main/kotlin/Dependency.kt +++ b/buildSrc/src/main/kotlin/Dependency.kt @@ -10,7 +10,7 @@ object Dependency { } object AndroidX { - const val MATERIAL = "androidx.compose.material:material:1.0.0-rc02" + const val MATERIAL = "androidx.compose.material:material:1.0.0" const val CONSTRAINT_LAYOUT = "androidx.constraintlayout:constraintlayout:2.1.0-rc01" const val APP_COMPAT = "androidx.appcompat:appcompat:1.3.1" const val SWIPE_REFRESH_LAYOUT = "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0" @@ -21,7 +21,7 @@ object Dependency { const val CORE = "androidx.core:core-ktx:1.7.0-alpha01" const val LIFECYCLE_VIEWMODEL = "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" const val LIFECYCLE_LIVEDATA = "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" - const val ACTIVITY = "androidx.activity:activity-ktx:1.3.0-rc02" + const val ACTIVITY = "androidx.activity:activity-ktx:1.3.0" const val FRAGMENT = "androidx.fragment:fragment-ktx:1.3.6" } @@ -68,8 +68,8 @@ object Dependency { } object Hilt { - const val CORE = "com.google.dagger:hilt-android:2.37" - const val APT = "com.google.dagger:hilt-android-compiler:2.37" + const val CORE = "com.google.dagger:hilt-android:2.38.1" + const val APT = "com.google.dagger:hilt-android-compiler:2.38.1" } object Room { @@ -78,7 +78,7 @@ object Dependency { } object Paging3 { - const val RUNTIME = "androidx.paging:paging-runtime:3.0.0" + const val RUNTIME = "androidx.paging:paging-runtime:3.0.1" } object Navigation { diff --git a/buildSrc/src/main/kotlin/TestDependency.kt b/buildSrc/src/main/kotlin/TestDependency.kt index c7fb74f..3e5f4ec 100644 --- a/buildSrc/src/main/kotlin/TestDependency.kt +++ b/buildSrc/src/main/kotlin/TestDependency.kt @@ -1,7 +1,7 @@ object TestDependency { const val JUNIT = "junit:junit:4.13.2" const val ARCH_CORE = "androidx.arch.core:core-testing:2.1.0" - const val ANDROIDX_TEST_CORE = "androidx.test:core:1.4.0-beta02" + const val ANDROIDX_TEST_CORE = "androidx.test:core:1.4.0" const val COROUTINE_TEST = "org.jetbrains.kotlinx:kotlinx-coroutines-test:1.5.1" const val ANDROID_JUNIT_RUNNER = "AndroidJUnitRunner" const val MOCKK = "io.mockk:mockk:1.12.0" From 1fcf0d6180260c49401bb76fab512048a43d6e4f Mon Sep 17 00:00:00 2001 From: beomjo Date: Fri, 30 Jul 2021 01:10:58 +0900 Subject: [PATCH 021/273] =?UTF-8?q?chore:=20ClassName=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle.kts | 2 +- buildSrc/src/main/kotlin/Version.kt | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index c4931dd..9f2278f 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -5,7 +5,7 @@ plugins { `detekt-setting` } -val version = Version.getVersionProperty() +val version: Version.Property = Version.getVersionProperty() android { compileSdkVersion(AndroidEnv.ANDROID_COMPILE) diff --git a/buildSrc/src/main/kotlin/Version.kt b/buildSrc/src/main/kotlin/Version.kt index de6b2ed..823252d 100644 --- a/buildSrc/src/main/kotlin/Version.kt +++ b/buildSrc/src/main/kotlin/Version.kt @@ -4,14 +4,14 @@ import java.util.* object Version { private const val VERSION_FILE_NAME = "version.properties" - data class VersionProperty( + data class Property( val code: Int, val name: String ) - fun getVersionProperty(): VersionProperty { + fun getVersionProperty(): Property { val prop = loadVersionVersionPropertyFile() - return VersionProperty( + return Property( prop.getProperty("version.code", "1").toInt(), prop.getProperty("version.name", "1") ) From 60f7dc77bdb110f2cda666c0cc56fa763488fbe5 Mon Sep 17 00:00:00 2001 From: beomjo Date: Fri, 30 Jul 2021 01:15:35 +0900 Subject: [PATCH 022/273] =?UTF-8?q?build:=20RestKey=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle.kts | 5 +++++ buildSrc/src/main/kotlin/Const.kt | 1 + 2 files changed, 6 insertions(+) create mode 100644 buildSrc/src/main/kotlin/Const.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 9f2278f..e31be4a 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,3 +1,5 @@ +import com.android.build.gradle.internal.cxx.configure.gradleLocalProperties + plugins { android `kotlin-android` @@ -6,6 +8,7 @@ plugins { } val version: Version.Property = Version.getVersionProperty() +val restKey: String = gradleLocalProperties(rootDir).getProperty(REST_KEY) android { compileSdkVersion(AndroidEnv.ANDROID_COMPILE) @@ -20,6 +23,8 @@ android { versionName = version.name testInstrumentationRunner = TestDependency.ANDROID_JUNIT_RUNNER + + buildConfigField("String", REST_KEY, "\"$restKey\"") } buildTypes { diff --git a/buildSrc/src/main/kotlin/Const.kt b/buildSrc/src/main/kotlin/Const.kt new file mode 100644 index 0000000..fd47a13 --- /dev/null +++ b/buildSrc/src/main/kotlin/Const.kt @@ -0,0 +1 @@ +const val REST_KEY = "REST_KEY" \ No newline at end of file From 5a2dfe9c0b381c84ba9d82a9cf2cc3128cc8f6df Mon Sep 17 00:00:00 2001 From: beomjo Date: Fri, 30 Jul 2021 01:19:21 +0900 Subject: [PATCH 023/273] =?UTF-8?q?feat:=20Application=20=ED=81=B4?= =?UTF-8?q?=EB=9E=98=EC=8A=A4=20Hilt=20=EC=82=AC=EC=9A=A9=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/AndroidManifest.xml | 1 + app/src/main/kotlin/io/beomjo/kakao/search/SearchApp.kt | 7 +++++++ 2 files changed, 8 insertions(+) create mode 100644 app/src/main/kotlin/io/beomjo/kakao/search/SearchApp.kt diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index b3942b4..d96a888 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -3,6 +3,7 @@ package="io.beomjo.kakao.search"> Date: Fri, 30 Jul 2021 01:22:45 +0900 Subject: [PATCH 024/273] =?UTF-8?q?build:=20Package=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/AndroidManifest.xml | 6 +++--- .../{beomjo/kakao => github/beomjo}/search/MainActivity.kt | 2 +- .../io/{beomjo/kakao => github/beomjo}/search/SearchApp.kt | 2 +- app/src/main/res/layout/activity_main.xml | 2 +- .../kakao => github/beomjo}/search/ExampleUnitTest.kt | 2 +- buildSrc/src/main/kotlin/AndroidEnv.kt | 2 +- data/src/main/AndroidManifest.xml | 2 +- .../io/{beomjo/kakao => github/beomjo}/search/.gitkeep | 0 .../io/{beomjo/kakao => github/beomjo}/search/.gitkeep | 0 9 files changed, 9 insertions(+), 9 deletions(-) rename app/src/main/kotlin/io/{beomjo/kakao => github/beomjo}/search/MainActivity.kt (89%) rename app/src/main/kotlin/io/{beomjo/kakao => github/beomjo}/search/SearchApp.kt (79%) rename app/src/test/java/io/{beomjo/kakao => github/beomjo}/search/ExampleUnitTest.kt (91%) rename data/src/main/kotlin/io/{beomjo/kakao => github/beomjo}/search/.gitkeep (100%) rename domain/src/main/kotlin/io/{beomjo/kakao => github/beomjo}/search/.gitkeep (100%) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d96a888..fdeae8b 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,16 +1,16 @@ + package="io.github.beomjo.search"> - + diff --git a/app/src/main/kotlin/io/beomjo/kakao/search/MainActivity.kt b/app/src/main/kotlin/io/github/beomjo/search/MainActivity.kt similarity index 89% rename from app/src/main/kotlin/io/beomjo/kakao/search/MainActivity.kt rename to app/src/main/kotlin/io/github/beomjo/search/MainActivity.kt index f4d6b37..99c0b87 100644 --- a/app/src/main/kotlin/io/beomjo/kakao/search/MainActivity.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/MainActivity.kt @@ -1,4 +1,4 @@ -package io.beomjo.kakao.search +package io.github.beomjo.search import androidx.appcompat.app.AppCompatActivity import android.os.Bundle diff --git a/app/src/main/kotlin/io/beomjo/kakao/search/SearchApp.kt b/app/src/main/kotlin/io/github/beomjo/search/SearchApp.kt similarity index 79% rename from app/src/main/kotlin/io/beomjo/kakao/search/SearchApp.kt rename to app/src/main/kotlin/io/github/beomjo/search/SearchApp.kt index 0ab1070..c6fb388 100644 --- a/app/src/main/kotlin/io/beomjo/kakao/search/SearchApp.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/SearchApp.kt @@ -1,4 +1,4 @@ -package io.beomjo.kakao.search +package io.github.beomjo.search import android.app.Application import dagger.hilt.android.HiltAndroidApp diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 4fc2444..afadd24 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -4,7 +4,7 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - tools:context=".MainActivity"> + tools:context="io.github.beomjo.search.MainActivity"> - \ No newline at end of file + \ No newline at end of file diff --git a/data/src/main/kotlin/io/beomjo/kakao/search/.gitkeep b/data/src/main/kotlin/io/github/beomjo/search/.gitkeep similarity index 100% rename from data/src/main/kotlin/io/beomjo/kakao/search/.gitkeep rename to data/src/main/kotlin/io/github/beomjo/search/.gitkeep diff --git a/domain/src/main/kotlin/io/beomjo/kakao/search/.gitkeep b/domain/src/main/kotlin/io/github/beomjo/search/.gitkeep similarity index 100% rename from domain/src/main/kotlin/io/beomjo/kakao/search/.gitkeep rename to domain/src/main/kotlin/io/github/beomjo/search/.gitkeep From 2ec5234f4b1b5fb0ddaf4800025d6897e6d3a992 Mon Sep 17 00:00:00 2001 From: beomjo Date: Fri, 30 Jul 2021 01:53:21 +0900 Subject: [PATCH 025/273] feat: Provide Api Key --- app/build.gradle.kts | 8 ++++++++ .../beomjo/search/di/SingletonModule.kt | 19 +++++++++++++++++++ domain/build.gradle.kts | 4 ++++ .../kotlin/io/github/beomjo/search/.gitkeep | 0 .../kotlin/io/github/beomjo/search/ApiKey.kt | 7 +++++++ 5 files changed, 38 insertions(+) create mode 100644 app/src/main/kotlin/io/github/beomjo/search/di/SingletonModule.kt delete mode 100644 domain/src/main/kotlin/io/github/beomjo/search/.gitkeep create mode 100644 domain/src/main/kotlin/io/github/beomjo/search/ApiKey.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index e31be4a..719b747 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -46,6 +46,14 @@ android { kotlinOptions { jvmTarget = JavaVersion.VERSION_1_8.toString() + + } + + kapt { + javacOptions { + option("-Adagger.fastInit=ENABLED") + option("-Adagger.hilt.android.internal.disableAndroidSuperclassValidation=true") + } } } diff --git a/app/src/main/kotlin/io/github/beomjo/search/di/SingletonModule.kt b/app/src/main/kotlin/io/github/beomjo/search/di/SingletonModule.kt new file mode 100644 index 0000000..71ba38c --- /dev/null +++ b/app/src/main/kotlin/io/github/beomjo/search/di/SingletonModule.kt @@ -0,0 +1,19 @@ +package io.github.beomjo.search.di + +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import io.github.beomjo.search.ApiKey +import io.github.beomjo.search.BuildConfig + +@Module +@InstallIn(SingletonComponent::class) +internal object SingletonModule { + + @Provides + @ApiKey + fun provideApiKey(): String { + return BuildConfig.REST_KEY + } +} \ No newline at end of file diff --git a/domain/build.gradle.kts b/domain/build.gradle.kts index a69db24..9deef21 100644 --- a/domain/build.gradle.kts +++ b/domain/build.gradle.kts @@ -2,3 +2,7 @@ plugins { kotlin `detekt-setting` } + +dependencies { + implementation(group = "javax.inject", name = "javax.inject", version = "1") +} diff --git a/domain/src/main/kotlin/io/github/beomjo/search/.gitkeep b/domain/src/main/kotlin/io/github/beomjo/search/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/domain/src/main/kotlin/io/github/beomjo/search/ApiKey.kt b/domain/src/main/kotlin/io/github/beomjo/search/ApiKey.kt new file mode 100644 index 0000000..37ffa4a --- /dev/null +++ b/domain/src/main/kotlin/io/github/beomjo/search/ApiKey.kt @@ -0,0 +1,7 @@ +package io.github.beomjo.search + +import javax.inject.Qualifier + +@Retention(AnnotationRetention.RUNTIME) +@Qualifier +annotation class ApiKey From 4a5aeb5ec2a9339e1928b123c3e97c4c5e354468 Mon Sep 17 00:00:00 2001 From: beomjo Date: Fri, 30 Jul 2021 02:02:37 +0900 Subject: [PATCH 026/273] chore: Detekt error fix --- app/src/main/kotlin/io/github/beomjo/search/SearchApp.kt | 2 +- .../main/kotlin/io/github/beomjo/search/di/SingletonModule.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/kotlin/io/github/beomjo/search/SearchApp.kt b/app/src/main/kotlin/io/github/beomjo/search/SearchApp.kt index c6fb388..50ff5ec 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/SearchApp.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/SearchApp.kt @@ -4,4 +4,4 @@ import android.app.Application import dagger.hilt.android.HiltAndroidApp @HiltAndroidApp -class SearchApp : Application() \ No newline at end of file +class SearchApp : Application() diff --git a/app/src/main/kotlin/io/github/beomjo/search/di/SingletonModule.kt b/app/src/main/kotlin/io/github/beomjo/search/di/SingletonModule.kt index 71ba38c..9d6c277 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/di/SingletonModule.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/di/SingletonModule.kt @@ -16,4 +16,4 @@ internal object SingletonModule { fun provideApiKey(): String { return BuildConfig.REST_KEY } -} \ No newline at end of file +} From de457f3ab50310825a51457776562876c971410a Mon Sep 17 00:00:00 2001 From: beomjo Date: Fri, 30 Jul 2021 02:07:51 +0900 Subject: [PATCH 027/273] chore: Change RestApi Variable Nullable --- app/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 719b747..3b03937 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -8,7 +8,7 @@ plugins { } val version: Version.Property = Version.getVersionProperty() -val restKey: String = gradleLocalProperties(rootDir).getProperty(REST_KEY) +val restKey: String? = gradleLocalProperties(rootDir).getProperty(REST_KEY) android { compileSdkVersion(AndroidEnv.ANDROID_COMPILE) From 34dcadc343a0756334d06e9a63796ef30d7c080c Mon Sep 17 00:00:00 2001 From: beomjo Date: Fri, 30 Jul 2021 02:36:00 +0900 Subject: [PATCH 028/273] chore: Change .gitignore --- .gitignore | 18 ++++++++++-------- .idea/.gitignore | 3 --- .idea/compiler.xml | 6 ------ .idea/gradle.xml | 19 ------------------- .idea/jarRepositories.xml | 30 ------------------------------ .idea/misc.xml | 9 --------- .idea/runConfigurations.xml | 10 ---------- 7 files changed, 10 insertions(+), 85 deletions(-) delete mode 100644 .idea/.gitignore delete mode 100644 .idea/compiler.xml delete mode 100644 .idea/gradle.xml delete mode 100644 .idea/jarRepositories.xml delete mode 100644 .idea/misc.xml delete mode 100644 .idea/runConfigurations.xml diff --git a/.gitignore b/.gitignore index c1a448e..ff1fc5f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,14 +1,15 @@ *.iml .gradle /local.properties -/.idea -/.idea/ -/.idea/caches -/.idea/libraries -/.idea/modules.xml -/.idea/workspace.xml -/.idea/navEditor.xml -/.idea/assetWizardSettings.xml +.idea +.idea/ +.idea/* +.idea/caches +.idea/libraries +.idea/modules.xml +.idea/workspace.xml +.idea/navEditor.xml +.idea/assetWizardSettings.xml .DS_Store /build /captures @@ -18,3 +19,4 @@ local.properties .idea/misc.xml .idea/gradle.xml .idea/compiler.xml + diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index 26d3352..0000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml diff --git a/.idea/compiler.xml b/.idea/compiler.xml deleted file mode 100644 index 61a9130..0000000 --- a/.idea/compiler.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml deleted file mode 100644 index 440480e..0000000 --- a/.idea/gradle.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml deleted file mode 100644 index 0380d8d..0000000 --- a/.idea/jarRepositories.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index d5d35ec..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml deleted file mode 100644 index 797acea..0000000 --- a/.idea/runConfigurations.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - \ No newline at end of file From f21aee5ba7a83f8462567f2904728a020b07034a Mon Sep 17 00:00:00 2001 From: beomjo Date: Tue, 3 Aug 2021 14:08:10 +0900 Subject: [PATCH 029/273] build: Update Gradle version 7.0.0 --- app/build.gradle.kts | 2 +- buildSrc/build.gradle.kts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 3b03937..64df0e5 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -29,7 +29,7 @@ android { buildTypes { getByName("release") { - minifyEnabled(false) + isMinifyEnabled = true proguardFiles( getDefaultProguardFile( "proguard-android-optimize.txt" diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 87299c9..86b3e64 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -9,7 +9,7 @@ repositories { } object PluginVersion { - const val GRADLE = "4.2.2" + const val GRADLE = "7.0.0" const val KOTLIN = "1.5.21" const val DETEKT = "1.17.1" const val HILT = "2.38.1" From aa57e2307b2cf1005992538a75b8025b82e2becd Mon Sep 17 00:00:00 2001 From: beomjo Date: Tue, 3 Aug 2021 14:29:45 +0900 Subject: [PATCH 030/273] =?UTF-8?q?feat:=20MainActivity=20NavHostFragment?= =?UTF-8?q?=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/res/layout/activity_main.xml | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index afadd24..955f8c2 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -6,13 +6,16 @@ android:layout_height="match_parent" tools:context="io.github.beomjo.search.MainActivity"> - + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:navGraph="@navigation/nav_graph" /> \ No newline at end of file From c1eeacff81f9add7f83640d7bd761fa67bfb7525 Mon Sep 17 00:00:00 2001 From: beomjo Date: Tue, 3 Aug 2021 14:29:57 +0900 Subject: [PATCH 031/273] =?UTF-8?q?feat:=20nav=5Fgraph=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/res/navigation/nav_graph.xml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 app/src/main/res/navigation/nav_graph.xml diff --git a/app/src/main/res/navigation/nav_graph.xml b/app/src/main/res/navigation/nav_graph.xml new file mode 100644 index 0000000..8e0008b --- /dev/null +++ b/app/src/main/res/navigation/nav_graph.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file From fe9946bcd3791fe8d30c14f291efd52a2aa99c46 Mon Sep 17 00:00:00 2001 From: beomjo Date: Tue, 3 Aug 2021 14:46:55 +0900 Subject: [PATCH 032/273] build: Databinding, ViewBinding enabled --- app/build.gradle.kts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 64df0e5..4ab89ad 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -39,6 +39,11 @@ android { } } + buildFeatures { + dataBinding = true + viewBinding = true + } + compileOptions { sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 From 111d8a457fcc75bf4cf9a25ec568a1895f2707f7 Mon Sep 17 00:00:00 2001 From: beomjo Date: Tue, 3 Aug 2021 15:03:23 +0900 Subject: [PATCH 033/273] =?UTF-8?q?build:=20Safe=20Args=20plugin=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle.kts | 1 + buildSrc/build.gradle.kts | 2 ++ 2 files changed, 3 insertions(+) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 4ab89ad..09754d0 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -5,6 +5,7 @@ plugins { `kotlin-android` `kotlin-kapt` `detekt-setting` + id("androidx.navigation.safeargs.kotlin") } val version: Version.Property = Version.getVersionProperty() diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 86b3e64..edd3654 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -14,6 +14,7 @@ object PluginVersion { const val DETEKT = "1.17.1" const val HILT = "2.38.1" const val DEPENDENCY_CHECKER = "0.39.0" + const val SAFE_ARGS = "2.1.0" } dependencies { @@ -22,4 +23,5 @@ dependencies { implementation("io.gitlab.arturbosch.detekt:detekt-gradle-plugin:${PluginVersion.DETEKT}") implementation("com.google.dagger:hilt-android-gradle-plugin:${PluginVersion.HILT}") implementation("com.github.ben-manes:gradle-versions-plugin:${PluginVersion.DEPENDENCY_CHECKER}") + implementation("androidx.navigation:navigation-safe-args-gradle-plugin:${PluginVersion.SAFE_ARGS}") } From 6ebd579cc2a59e4bb92a1504e467f780d4453ab7 Mon Sep 17 00:00:00 2001 From: beomjo Date: Tue, 3 Aug 2021 15:09:15 +0900 Subject: [PATCH 034/273] build: Change safe args plugin version --- buildSrc/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index edd3654..424a4eb 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -14,7 +14,7 @@ object PluginVersion { const val DETEKT = "1.17.1" const val HILT = "2.38.1" const val DEPENDENCY_CHECKER = "0.39.0" - const val SAFE_ARGS = "2.1.0" + const val SAFE_ARGS = "2.3.5" } dependencies { From 40079b53321d05fb5e282ac8cd537a28fc01ef5b Mon Sep 17 00:00:00 2001 From: beomjo Date: Tue, 3 Aug 2021 15:11:14 +0900 Subject: [PATCH 035/273] =?UTF-8?q?feat:=20CafeAndBlogFragment,=20DetailFr?= =?UTF-8?q?agment=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Graph에 설정 --- .../beomjo/search/ui/CafeAndBlogFragment.kt | 30 +++++++++++++++++++ .../github/beomjo/search/ui/DetailFragment.kt | 18 +++++++++++ .../res/layout/fragment_cafe_and_blog.xml | 13 ++++++++ app/src/main/res/layout/fragment_detail.xml | 12 ++++++++ app/src/main/res/navigation/nav_graph.xml | 20 ++++++++++++- app/src/main/res/values/strings.xml | 2 ++ 6 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 app/src/main/kotlin/io/github/beomjo/search/ui/CafeAndBlogFragment.kt create mode 100644 app/src/main/kotlin/io/github/beomjo/search/ui/DetailFragment.kt create mode 100644 app/src/main/res/layout/fragment_cafe_and_blog.xml create mode 100644 app/src/main/res/layout/fragment_detail.xml diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/CafeAndBlogFragment.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/CafeAndBlogFragment.kt new file mode 100644 index 0000000..d7fbf3b --- /dev/null +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/CafeAndBlogFragment.kt @@ -0,0 +1,30 @@ +package io.github.beomjo.search.ui + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.annotation.NonNull +import androidx.fragment.app.Fragment +import androidx.navigation.fragment.findNavController +import io.github.beomjo.search.databinding.FragmentCafeAndBlogBinding + +class CafeAndBlogFragment : Fragment() { + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + val binding = FragmentCafeAndBlogBinding.inflate(layoutInflater) + setView(binding) + return binding.root + } + + private fun setView(binding: FragmentCafeAndBlogBinding) { + binding.text.setOnClickListener { + CafeAndBlogFragmentDirections.actionCafeAndBlogDestToDetailFragment().let { + findNavController().navigate(it) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/DetailFragment.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/DetailFragment.kt new file mode 100644 index 0000000..32b971a --- /dev/null +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/DetailFragment.kt @@ -0,0 +1,18 @@ +package io.github.beomjo.search.ui + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import io.github.beomjo.search.R + +class DetailFragment : Fragment() { + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + return inflater.inflate(R.layout.fragment_detail, container, false) + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_cafe_and_blog.xml b/app/src/main/res/layout/fragment_cafe_and_blog.xml new file mode 100644 index 0000000..9a1b2eb --- /dev/null +++ b/app/src/main/res/layout/fragment_cafe_and_blog.xml @@ -0,0 +1,13 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_detail.xml b/app/src/main/res/layout/fragment_detail.xml new file mode 100644 index 0000000..a49b956 --- /dev/null +++ b/app/src/main/res/layout/fragment_detail.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/navigation/nav_graph.xml b/app/src/main/res/navigation/nav_graph.xml index 8e0008b..f0c6e9a 100644 --- a/app/src/main/res/navigation/nav_graph.xml +++ b/app/src/main/res/navigation/nav_graph.xml @@ -1,6 +1,24 @@ + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/nav_graph" + app:startDestination="@id/cafe_and_blog_dest"> + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index db97778..2ff0002 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,3 +1,5 @@ kakao-search + Cafe and Blog Fragment + Detail Fragment \ No newline at end of file From dbcbb9fec8c64722ddcfd0d8c28abaa20c958eec Mon Sep 17 00:00:00 2001 From: beomjo Date: Tue, 3 Aug 2021 15:19:20 +0900 Subject: [PATCH 036/273] =?UTF-8?q?chore:=20ClassName=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{CafeAndBlogFragment.kt => HomeFragment.kt} | 11 +++++------ .../main/res/layout/fragment_cafe_and_blog.xml | 13 ------------- app/src/main/res/layout/fragment_home.xml | 16 ++++++++++++++++ app/src/main/res/navigation/nav_graph.xml | 10 +++++----- app/src/main/res/values/strings.xml | 2 +- 5 files changed, 27 insertions(+), 25 deletions(-) rename app/src/main/kotlin/io/github/beomjo/search/ui/{CafeAndBlogFragment.kt => HomeFragment.kt} (60%) delete mode 100644 app/src/main/res/layout/fragment_cafe_and_blog.xml create mode 100644 app/src/main/res/layout/fragment_home.xml diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/CafeAndBlogFragment.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/HomeFragment.kt similarity index 60% rename from app/src/main/kotlin/io/github/beomjo/search/ui/CafeAndBlogFragment.kt rename to app/src/main/kotlin/io/github/beomjo/search/ui/HomeFragment.kt index d7fbf3b..08bdadc 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/CafeAndBlogFragment.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/HomeFragment.kt @@ -4,25 +4,24 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import androidx.annotation.NonNull import androidx.fragment.app.Fragment import androidx.navigation.fragment.findNavController -import io.github.beomjo.search.databinding.FragmentCafeAndBlogBinding +import io.github.beomjo.search.databinding.FragmentHomeBinding -class CafeAndBlogFragment : Fragment() { +class HomeFragment : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { - val binding = FragmentCafeAndBlogBinding.inflate(layoutInflater) + val binding = FragmentHomeBinding.inflate(layoutInflater) setView(binding) return binding.root } - private fun setView(binding: FragmentCafeAndBlogBinding) { + private fun setView(binding: FragmentHomeBinding) { binding.text.setOnClickListener { - CafeAndBlogFragmentDirections.actionCafeAndBlogDestToDetailFragment().let { + HomeFragmentDirections.actionCafeAndBlogDestToDetailFragment().let { findNavController().navigate(it) } } diff --git a/app/src/main/res/layout/fragment_cafe_and_blog.xml b/app/src/main/res/layout/fragment_cafe_and_blog.xml deleted file mode 100644 index 9a1b2eb..0000000 --- a/app/src/main/res/layout/fragment_cafe_and_blog.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml new file mode 100644 index 0000000..dba3a97 --- /dev/null +++ b/app/src/main/res/layout/fragment_home.xml @@ -0,0 +1,16 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/navigation/nav_graph.xml b/app/src/main/res/navigation/nav_graph.xml index f0c6e9a..4ea2c75 100644 --- a/app/src/main/res/navigation/nav_graph.xml +++ b/app/src/main/res/navigation/nav_graph.xml @@ -3,13 +3,13 @@ xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/nav_graph" - app:startDestination="@id/cafe_and_blog_dest"> + app:startDestination="@id/home_dest"> + android:id="@+id/home_dest" + android:name="io.github.beomjo.search.ui.HomeFragment" + android:label="@string/home_fragment_title" + tools:layout="@layout/fragment_home"> kakao-search - Cafe and Blog Fragment + Home Fragment Detail Fragment \ No newline at end of file From d6ce180206b701b15f5d7b8ec2d82429c6fa5777 Mon Sep 17 00:00:00 2001 From: beomjo Date: Tue, 3 Aug 2021 15:45:02 +0900 Subject: [PATCH 037/273] =?UTF-8?q?feat:=20SearchFragment=20=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20=EB=B0=8F=20nav=5Fgraph=20=EB=93=B1=EB=A1=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../github/beomjo/search/ui/HomeFragment.kt | 2 +- .../github/beomjo/search/ui/SearchFragment.kt | 18 +++++++++++++++ app/src/main/res/layout/fragment_search.xml | 16 ++++++++++++++ app/src/main/res/navigation/nav_graph.xml | 22 ++++++++++++++++--- app/src/main/res/values/strings.xml | 1 + 5 files changed, 55 insertions(+), 4 deletions(-) create mode 100644 app/src/main/kotlin/io/github/beomjo/search/ui/SearchFragment.kt create mode 100644 app/src/main/res/layout/fragment_search.xml diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/HomeFragment.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/HomeFragment.kt index 08bdadc..6588c06 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/HomeFragment.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/HomeFragment.kt @@ -21,7 +21,7 @@ class HomeFragment : Fragment() { private fun setView(binding: FragmentHomeBinding) { binding.text.setOnClickListener { - HomeFragmentDirections.actionCafeAndBlogDestToDetailFragment().let { + HomeFragmentDirections.actionHomeDestToDetailDest().let { findNavController().navigate(it) } } diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/SearchFragment.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/SearchFragment.kt new file mode 100644 index 0000000..37e1ed8 --- /dev/null +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/SearchFragment.kt @@ -0,0 +1,18 @@ +package io.github.beomjo.search.ui + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import io.github.beomjo.search.R + +class SearchFragment : Fragment() { + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + return inflater.inflate(R.layout.fragment_search, container, false) + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_search.xml b/app/src/main/res/layout/fragment_search.xml new file mode 100644 index 0000000..2d46605 --- /dev/null +++ b/app/src/main/res/layout/fragment_search.xml @@ -0,0 +1,16 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/navigation/nav_graph.xml b/app/src/main/res/navigation/nav_graph.xml index 4ea2c75..86ebbcf 100644 --- a/app/src/main/res/navigation/nav_graph.xml +++ b/app/src/main/res/navigation/nav_graph.xml @@ -11,14 +11,30 @@ android:label="@string/home_fragment_title" tools:layout="@layout/fragment_home"> + + + + + + + + + android:label="@string/detail_fragment_title" + tools:layout="@layout/fragment_detail" /> \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a5ce24b..6daa702 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,5 +1,6 @@ kakao-search Home Fragment + Search Fragment Detail Fragment \ No newline at end of file From eec724b9f90b42567579a0748043878d83b1d9af Mon Sep 17 00:00:00 2001 From: beomjo Date: Tue, 3 Aug 2021 16:24:03 +0900 Subject: [PATCH 038/273] =?UTF-8?q?feat:=20BottomNavigation=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../io/github/beomjo/search/MainActivity.kt | 18 ++++++- app/src/main/res/drawable/ic_home.xml | 5 ++ app/src/main/res/drawable/ic_search.xml | 5 ++ .../main/res/layout-h470dp/activity_main.xml | 38 +++++++++++++ .../main/res/layout-w960dp/activity_main.xml | 38 +++++++++++++ app/src/main/res/layout/activity_main.xml | 53 +++++++++++++------ app/src/main/res/menu/bottom_nav_menu.xml | 11 ++++ app/src/main/res/values/strings.xml | 2 + 8 files changed, 152 insertions(+), 18 deletions(-) create mode 100644 app/src/main/res/drawable/ic_home.xml create mode 100644 app/src/main/res/drawable/ic_search.xml create mode 100644 app/src/main/res/layout-h470dp/activity_main.xml create mode 100644 app/src/main/res/layout-w960dp/activity_main.xml create mode 100644 app/src/main/res/menu/bottom_nav_menu.xml diff --git a/app/src/main/kotlin/io/github/beomjo/search/MainActivity.kt b/app/src/main/kotlin/io/github/beomjo/search/MainActivity.kt index 99c0b87..bb7d87d 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/MainActivity.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/MainActivity.kt @@ -2,10 +2,26 @@ package io.github.beomjo.search import androidx.appcompat.app.AppCompatActivity import android.os.Bundle +import androidx.databinding.DataBindingUtil +import androidx.navigation.NavController +import androidx.navigation.fragment.NavHostFragment +import androidx.navigation.ui.setupWithNavController +import com.google.android.material.bottomnavigation.BottomNavigationView +import io.github.beomjo.search.databinding.ActivityMainBinding class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(R.layout.activity_main) + val binding = + DataBindingUtil.setContentView(this, R.layout.activity_main) + val navHostFragment = + supportFragmentManager.findFragmentById(R.id.nav_host_container_fragment) as NavHostFragment + val navController = navHostFragment.navController + setupBottomNavMenu(navController) + } + + private fun setupBottomNavMenu(navController: NavController) { + val bottomNav = findViewById(R.id.bottom_nav_view) + bottomNav?.setupWithNavController(navController) } } diff --git a/app/src/main/res/drawable/ic_home.xml b/app/src/main/res/drawable/ic_home.xml new file mode 100644 index 0000000..e6f32a4 --- /dev/null +++ b/app/src/main/res/drawable/ic_home.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_search.xml b/app/src/main/res/drawable/ic_search.xml new file mode 100644 index 0000000..dd4b0c1 --- /dev/null +++ b/app/src/main/res/drawable/ic_search.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/layout-h470dp/activity_main.xml b/app/src/main/res/layout-h470dp/activity_main.xml new file mode 100644 index 0000000..2704585 --- /dev/null +++ b/app/src/main/res/layout-h470dp/activity_main.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout-w960dp/activity_main.xml b/app/src/main/res/layout-w960dp/activity_main.xml new file mode 100644 index 0000000..2704585 --- /dev/null +++ b/app/src/main/res/layout-w960dp/activity_main.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 955f8c2..cf93e79 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -1,21 +1,40 @@ - + xmlns:tools="http://schemas.android.com/tools"> - + - \ No newline at end of file + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/bottom_nav_menu.xml b/app/src/main/res/menu/bottom_nav_menu.xml new file mode 100644 index 0000000..82443ce --- /dev/null +++ b/app/src/main/res/menu/bottom_nav_menu.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 6daa702..ad8d660 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -3,4 +3,6 @@ Home Fragment Search Fragment Detail Fragment + Home + Search \ No newline at end of file From 2aa5ae693d292e35be328661cbe879f65386d1a8 Mon Sep 17 00:00:00 2001 From: beomjo Date: Tue, 3 Aug 2021 16:57:48 +0900 Subject: [PATCH 039/273] =?UTF-8?q?feat:=20=ED=99=94=EB=A9=B4=20Orientatio?= =?UTF-8?q?n=EC=97=90=20=EB=94=B0=EB=9D=BC=20layout=20inflate=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../io/github/beomjo/search/MainActivity.kt | 70 ++++++++++++++++--- .../main/res/layout-w960dp/activity_main.xml | 46 ++++++++---- app/src/main/res/layout/activity_main.xml | 62 ++++++++++------ app/src/main/res/layout/fragment_detail.xml | 11 ++- app/src/main/res/layout/fragment_home.xml | 14 ++-- app/src/main/res/layout/fragment_search.xml | 15 ++-- app/src/main/res/layout/layout_header.xml | 13 ++++ app/src/main/res/menu/nav_drawer_menu.xml | 13 ++++ 8 files changed, 184 insertions(+), 60 deletions(-) create mode 100644 app/src/main/res/layout/layout_header.xml create mode 100644 app/src/main/res/menu/nav_drawer_menu.xml diff --git a/app/src/main/kotlin/io/github/beomjo/search/MainActivity.kt b/app/src/main/kotlin/io/github/beomjo/search/MainActivity.kt index bb7d87d..7a1da25 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/MainActivity.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/MainActivity.kt @@ -2,26 +2,74 @@ package io.github.beomjo.search import androidx.appcompat.app.AppCompatActivity import android.os.Bundle +import android.view.Menu import androidx.databinding.DataBindingUtil import androidx.navigation.NavController import androidx.navigation.fragment.NavHostFragment +import androidx.navigation.ui.AppBarConfiguration +import androidx.navigation.ui.navigateUp +import androidx.navigation.ui.setupActionBarWithNavController import androidx.navigation.ui.setupWithNavController -import com.google.android.material.bottomnavigation.BottomNavigationView +import com.google.android.material.navigation.NavigationView import io.github.beomjo.search.databinding.ActivityMainBinding class MainActivity : AppCompatActivity() { + + private lateinit var binding: ActivityMainBinding + + private lateinit var navController: NavController + + private lateinit var appBarConfiguration: AppBarConfiguration + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - val binding = - DataBindingUtil.setContentView(this, R.layout.activity_main) - val navHostFragment = - supportFragmentManager.findFragmentById(R.id.nav_host_container_fragment) as NavHostFragment - val navController = navHostFragment.navController - setupBottomNavMenu(navController) + + binding = DataBindingUtil.setContentView(this, R.layout.activity_main) + + val navHostFragment = getNavHostFragment() + navController = navHostFragment.navController + + setAppBarConfiguration() + + setupActionBar() + + setupBottomNavMenu() + + setupNavigationMenu() + } + + private fun getNavHostFragment() = + supportFragmentManager.findFragmentById(R.id.nav_host_container_fragment) as NavHostFragment + + private fun setAppBarConfiguration() { + appBarConfiguration = if (binding.drawerLayout != null) { + AppBarConfiguration( + setOf(R.id.home_dest, R.id.search_dest), + binding.drawerLayout + ) + } else { + AppBarConfiguration(navController.graph) + } + } + + private fun setupActionBar() { + setupActionBarWithNavController(navController, appBarConfiguration) + } + + private fun setupBottomNavMenu() { + binding.bottomNavView?.setupWithNavController(navController) + } + + private fun setupNavigationMenu() { + binding.navView?.setupWithNavController(navController) + } + + override fun onSupportNavigateUp(): Boolean { + return navController.navigateUp(appBarConfiguration) } - private fun setupBottomNavMenu(navController: NavController) { - val bottomNav = findViewById(R.id.bottom_nav_view) - bottomNav?.setupWithNavController(navController) + override fun onCreateOptionsMenu(menu: Menu): Boolean { + binding.navView ?: return false + return super.onCreateOptionsMenu(menu) } -} +} \ No newline at end of file diff --git a/app/src/main/res/layout-w960dp/activity_main.xml b/app/src/main/res/layout-w960dp/activity_main.xml index 2704585..c817b41 100644 --- a/app/src/main/res/layout-w960dp/activity_main.xml +++ b/app/src/main/res/layout-w960dp/activity_main.xml @@ -4,6 +4,7 @@ xmlns:tools="http://schemas.android.com/tools"> + @@ -12,27 +13,48 @@ - + app:menu="@menu/nav_drawer_menu" /> + - + + + app:layout_constraintTop_toBottomOf="@id/toolbar" + app:navGraph="@navigation/nav_graph" /> + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index cf93e79..cd1c101 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -10,31 +10,47 @@ type="io.github.beomjo.search.MainActivity" /> - - - - - - + android:layout_height="match_parent"> + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_detail.xml b/app/src/main/res/layout/fragment_detail.xml index a49b956..bd33715 100644 --- a/app/src/main/res/layout/fragment_detail.xml +++ b/app/src/main/res/layout/fragment_detail.xml @@ -1,12 +1,17 @@ + android:text="@string/detail_fragment_title" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml index dba3a97..005cfdb 100644 --- a/app/src/main/res/layout/fragment_home.xml +++ b/app/src/main/res/layout/fragment_home.xml @@ -1,6 +1,6 @@ - + android:text="@string/home_fragment_title" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_search.xml b/app/src/main/res/layout/fragment_search.xml index 2d46605..29aac4c 100644 --- a/app/src/main/res/layout/fragment_search.xml +++ b/app/src/main/res/layout/fragment_search.xml @@ -1,16 +1,19 @@ - + android:text="@string/search_fragment_title" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> \ No newline at end of file diff --git a/app/src/main/res/layout/layout_header.xml b/app/src/main/res/layout/layout_header.xml new file mode 100644 index 0000000..27a3a7a --- /dev/null +++ b/app/src/main/res/layout/layout_header.xml @@ -0,0 +1,13 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/nav_drawer_menu.xml b/app/src/main/res/menu/nav_drawer_menu.xml new file mode 100644 index 0000000..167766a --- /dev/null +++ b/app/src/main/res/menu/nav_drawer_menu.xml @@ -0,0 +1,13 @@ + + + + + + + From 865b4e28ebead467f9ff32bac91fae94d4392ef5 Mon Sep 17 00:00:00 2001 From: beomjo Date: Tue, 3 Aug 2021 17:16:37 +0900 Subject: [PATCH 040/273] =?UTF-8?q?build:=20Build=20=EC=84=A4=EC=A0=95=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle.kts | 7 +++---- app/src/main/AndroidManifest.xml | 1 - 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 09754d0..7e3d7d5 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -12,13 +12,13 @@ val version: Version.Property = Version.getVersionProperty() val restKey: String? = gradleLocalProperties(rootDir).getProperty(REST_KEY) android { - compileSdkVersion(AndroidEnv.ANDROID_COMPILE) + compileSdk = AndroidEnv.ANDROID_COMPILE buildToolsVersion = AndroidEnv.BUILD_TOOL defaultConfig { applicationId = AndroidEnv.APPLICATION_ID - minSdkVersion(AndroidEnv.ANDROID_MIN) - targetSdkVersion(AndroidEnv.ANDROID_TARGET) + minSdk = AndroidEnv.ANDROID_MIN + targetSdk = AndroidEnv.ANDROID_TARGET vectorDrawables.useSupportLibrary = true versionCode = version.code versionName = version.name @@ -71,7 +71,6 @@ dependencies { implementation(Dependency.Kotlin.COROUTINE_CORE) implementation(Dependency.Kotlin.COROUTINE_ANDROID) - implementation(Dependency.AndroidX.APP_COMPAT) implementation(Dependency.AndroidX.MATERIAL) implementation(Dependency.AndroidX.APP_COMPAT) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index fdeae8b..9353489 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -4,7 +4,6 @@ Date: Tue, 3 Aug 2021 17:24:36 +0900 Subject: [PATCH 041/273] docs: Update README.md --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 2409c27..20c0b8f 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,10 @@ # kakao-search +## Clone Project +``` +$ git clone --recursive https://github.com/beomjo/kakao-search.git +``` + ## API API from https://developers.kakao.com/ in your local.properties From 64307dee49fe87a529335eaa91f3bf1583bf29dd Mon Sep 17 00:00:00 2001 From: beomjo Date: Tue, 3 Aug 2021 17:25:53 +0900 Subject: [PATCH 042/273] chore: Change Submodule Remote URL --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index f331047..5c6adde 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +1,4 @@ [submodule "android-compilation"] path = android-compilation - url = git@github.com-personal:beomjo/android-compilation.git + url = git@github.com:beomjo/android-compilation.git branch = main From 21f5c578828163abd6b36ff0792eab1618b4d4ff Mon Sep 17 00:00:00 2001 From: beomjo Date: Tue, 3 Aug 2021 17:27:34 +0900 Subject: [PATCH 043/273] chore: Change Submodule Remote URL --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index 5c6adde..54d8bd2 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +1,4 @@ [submodule "android-compilation"] path = android-compilation - url = git@github.com:beomjo/android-compilation.git + url = https://github.com/beomjo/android-compilation.git branch = main From acd07f5f8bf39a62ca66a90a9ad29afc5d818af0 Mon Sep 17 00:00:00 2001 From: beomjo Date: Tue, 3 Aug 2021 17:32:19 +0900 Subject: [PATCH 044/273] docs: Update README.md --- README.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 20c0b8f..d66808e 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,11 @@ -# kakao-search +

kakao-search

+ +

+ + Build Status + ktlint +

+ ## Clone Project ``` From df753eb508bd50a987f2fb3e55cca68bef525521 Mon Sep 17 00:00:00 2001 From: beomjo Date: Tue, 3 Aug 2021 22:00:30 +0900 Subject: [PATCH 045/273] chore: Fix detekt error --- app/src/main/kotlin/io/github/beomjo/search/MainActivity.kt | 3 +-- .../main/kotlin/io/github/beomjo/search/ui/DetailFragment.kt | 2 +- app/src/main/kotlin/io/github/beomjo/search/ui/HomeFragment.kt | 2 +- .../main/kotlin/io/github/beomjo/search/ui/SearchFragment.kt | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/app/src/main/kotlin/io/github/beomjo/search/MainActivity.kt b/app/src/main/kotlin/io/github/beomjo/search/MainActivity.kt index 7a1da25..722a64c 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/MainActivity.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/MainActivity.kt @@ -10,7 +10,6 @@ import androidx.navigation.ui.AppBarConfiguration import androidx.navigation.ui.navigateUp import androidx.navigation.ui.setupActionBarWithNavController import androidx.navigation.ui.setupWithNavController -import com.google.android.material.navigation.NavigationView import io.github.beomjo.search.databinding.ActivityMainBinding class MainActivity : AppCompatActivity() { @@ -72,4 +71,4 @@ class MainActivity : AppCompatActivity() { binding.navView ?: return false return super.onCreateOptionsMenu(menu) } -} \ No newline at end of file +} diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/DetailFragment.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/DetailFragment.kt index 32b971a..fe1af2d 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/DetailFragment.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/DetailFragment.kt @@ -15,4 +15,4 @@ class DetailFragment : Fragment() { ): View? { return inflater.inflate(R.layout.fragment_detail, container, false) } -} \ No newline at end of file +} diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/HomeFragment.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/HomeFragment.kt index 6588c06..5489d36 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/HomeFragment.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/HomeFragment.kt @@ -26,4 +26,4 @@ class HomeFragment : Fragment() { } } } -} \ No newline at end of file +} diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/SearchFragment.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/SearchFragment.kt index 37e1ed8..2255e2d 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/SearchFragment.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/SearchFragment.kt @@ -15,4 +15,4 @@ class SearchFragment : Fragment() { ): View? { return inflater.inflate(R.layout.fragment_search, container, false) } -} \ No newline at end of file +} From 6777fce19dddce48fea8149ab2cb35070817c05b Mon Sep 17 00:00:00 2001 From: beomjo Date: Tue, 3 Aug 2021 22:00:38 +0900 Subject: [PATCH 046/273] chore: Update Submodule --- android-compilation | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android-compilation b/android-compilation index ef32211..42bbdff 160000 --- a/android-compilation +++ b/android-compilation @@ -1 +1 @@ -Subproject commit ef3221153e797f6bf6be07bbd777268b4ff55a4f +Subproject commit 42bbdff7290043d13e681c2c4a96091c71e0db6e From 95f1ef5a048ef488c8f22c0c2878e36bc0affc87 Mon Sep 17 00:00:00 2001 From: beomjo Date: Tue, 3 Aug 2021 22:01:13 +0900 Subject: [PATCH 047/273] build: Github action java version 11 --- .github/workflows/android.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index dc5fbf1..154a795 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -13,10 +13,10 @@ jobs: steps: - uses: actions/checkout@v2 - - name: set up JDK 8 + - name: set up JDK 11 uses: actions/setup-java@v2 with: - java-version: '8' + java-version: '11' distribution: 'adopt' - name: Grant execute permission for gradlew @@ -44,10 +44,10 @@ jobs: steps: - uses: actions/checkout@v2 - - name: set up JDK 8 + - name: set up JDK 11 uses: actions/setup-java@v2 with: - java-version: '8' + java-version: '11' distribution: 'adopt' - name: Grant execute permission for gradlew @@ -76,10 +76,10 @@ jobs: steps: - uses: actions/checkout@v2 - - name: set up JDK 8 + - name: set up JDK 11 uses: actions/setup-java@v2 with: - java-version: '8' + java-version: '11' distribution: 'adopt' - name: Grant execute permission for gradlew @@ -115,10 +115,10 @@ jobs: steps: - uses: actions/checkout@v2 - - name: set up JDK 8 + - name: set up JDK 11 uses: actions/setup-java@v2 with: - java-version: '8' + java-version: '11' distribution: 'adopt' - name: Grant execute permission for gradlew From 2c1dc3f64c83788342bf52e66f0455228a93c598 Mon Sep 17 00:00:00 2001 From: beomjo Date: Tue, 3 Aug 2021 22:04:12 +0900 Subject: [PATCH 048/273] build: Delete Java 8 Compile Option --- app/build.gradle.kts | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 3b03937..a306964 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -39,16 +39,6 @@ android { } } - compileOptions { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 - } - - kotlinOptions { - jvmTarget = JavaVersion.VERSION_1_8.toString() - - } - kapt { javacOptions { option("-Adagger.fastInit=ENABLED") From cb8bed507f749d1811fdf1c5634392bbef52c6dd Mon Sep 17 00:00:00 2001 From: beomjo Date: Tue, 3 Aug 2021 22:07:18 +0900 Subject: [PATCH 049/273] chore: Update Submodule --- android-compilation | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android-compilation b/android-compilation index ef32211..7c525c0 160000 --- a/android-compilation +++ b/android-compilation @@ -1 +1 @@ -Subproject commit ef3221153e797f6bf6be07bbd777268b4ff55a4f +Subproject commit 7c525c0db7accf23400e0fcf4d38449876f042cb From a4a5ea1ecc8a9183c717681eda8aa58d92e5bfdb Mon Sep 17 00:00:00 2001 From: beomjo Date: Tue, 3 Aug 2021 22:35:07 +0900 Subject: [PATCH 050/273] chore: Add License info --- LICENSE | 201 ++++++++++++++++++ README.md | 21 +- app/build.gradle.kts | 16 ++ app/src/main/AndroidManifest.xml | 16 +- .../io/github/beomjo/search/MainActivity.kt | 16 ++ .../io/github/beomjo/search/SearchApp.kt | 16 ++ .../beomjo/search/di/SingletonModule.kt | 16 ++ .../github/beomjo/search/ui/DetailFragment.kt | 16 ++ .../github/beomjo/search/ui/HomeFragment.kt | 16 ++ .../github/beomjo/search/ui/SearchFragment.kt | 16 ++ .../main/res/layout-h470dp/activity_main.xml | 18 +- .../main/res/layout-w960dp/activity_main.xml | 16 +- app/src/main/res/layout/activity_main.xml | 16 +- app/src/main/res/layout/fragment_detail.xml | 16 +- app/src/main/res/layout/fragment_home.xml | 16 +- app/src/main/res/layout/fragment_search.xml | 16 +- app/src/main/res/layout/layout_header.xml | 19 +- app/src/main/res/menu/bottom_nav_menu.xml | 16 +- app/src/main/res/menu/nav_drawer_menu.xml | 16 +- .../res/mipmap-anydpi-v26/ic_launcher.xml | 16 +- .../mipmap-anydpi-v26/ic_launcher_round.xml | 16 +- app/src/main/res/navigation/nav_graph.xml | 16 +- app/src/main/res/values/colors.xml | 16 +- app/src/main/res/values/strings.xml | 15 ++ app/src/main/res/values/themes.xml | 15 ++ build.gradle.kts | 17 ++ buildSrc/build.gradle.kts | 16 ++ buildSrc/src/main/kotlin/AndroidEnv.kt | 16 ++ .../src/main/kotlin/AndroidTestDependency.kt | 16 ++ buildSrc/src/main/kotlin/Const.kt | 16 ++ buildSrc/src/main/kotlin/Dependency.kt | 16 ++ buildSrc/src/main/kotlin/TestDependency.kt | 16 ++ buildSrc/src/main/kotlin/Version.kt | 16 ++ .../main/kotlin/dependency-check.gradle.kts | 16 ++ .../src/main/kotlin/detekt-setting.gradle.kts | 16 ++ data/build.gradle.kts | 16 ++ data/src/main/AndroidManifest.xml | 16 +- domain/build.gradle.kts | 16 ++ .../kotlin/io/github/beomjo/search/ApiKey.kt | 16 ++ 39 files changed, 799 insertions(+), 19 deletions(-) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..29772ec --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Designed and developed by 2021 beomjo + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md index d66808e..5371079 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@

kakao-search

- + License Build Status ktlint

@@ -18,4 +18,21 @@ in your local.properties ``` REST_KEY={YOUR_KEY} -``` +``` + +## LICENSE +```xml +Designed and developed by 2021 beomjo + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +``` \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 609f8e8..a042c1d 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,3 +1,19 @@ +/* + * Designed and developed by 2021 beomjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import com.android.build.gradle.internal.cxx.configure.gradleLocalProperties plugins { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 9353489..3c2cb75 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,4 +1,18 @@ - + diff --git a/app/src/main/kotlin/io/github/beomjo/search/MainActivity.kt b/app/src/main/kotlin/io/github/beomjo/search/MainActivity.kt index 722a64c..e11e4eb 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/MainActivity.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/MainActivity.kt @@ -1,3 +1,19 @@ +/* + * Designed and developed by 2021 beomjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package io.github.beomjo.search import androidx.appcompat.app.AppCompatActivity diff --git a/app/src/main/kotlin/io/github/beomjo/search/SearchApp.kt b/app/src/main/kotlin/io/github/beomjo/search/SearchApp.kt index 50ff5ec..cd804d9 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/SearchApp.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/SearchApp.kt @@ -1,3 +1,19 @@ +/* + * Designed and developed by 2021 beomjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package io.github.beomjo.search import android.app.Application diff --git a/app/src/main/kotlin/io/github/beomjo/search/di/SingletonModule.kt b/app/src/main/kotlin/io/github/beomjo/search/di/SingletonModule.kt index 9d6c277..7515e21 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/di/SingletonModule.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/di/SingletonModule.kt @@ -1,3 +1,19 @@ +/* + * Designed and developed by 2021 beomjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package io.github.beomjo.search.di import dagger.Module diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/DetailFragment.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/DetailFragment.kt index fe1af2d..4be50bc 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/DetailFragment.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/DetailFragment.kt @@ -1,3 +1,19 @@ +/* + * Designed and developed by 2021 beomjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package io.github.beomjo.search.ui import android.os.Bundle diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/HomeFragment.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/HomeFragment.kt index 5489d36..bf3d85d 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/HomeFragment.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/HomeFragment.kt @@ -1,3 +1,19 @@ +/* + * Designed and developed by 2021 beomjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package io.github.beomjo.search.ui import android.os.Bundle diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/SearchFragment.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/SearchFragment.kt index 2255e2d..22b622b 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/SearchFragment.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/SearchFragment.kt @@ -1,3 +1,19 @@ +/* + * Designed and developed by 2021 beomjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package io.github.beomjo.search.ui import android.os.Bundle diff --git a/app/src/main/res/layout-h470dp/activity_main.xml b/app/src/main/res/layout-h470dp/activity_main.xml index 2704585..852e639 100644 --- a/app/src/main/res/layout-h470dp/activity_main.xml +++ b/app/src/main/res/layout-h470dp/activity_main.xml @@ -1,9 +1,24 @@ - + + @@ -12,6 +27,7 @@ + + diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index cd1c101..eee3e63 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -1,4 +1,18 @@ - + diff --git a/app/src/main/res/layout/fragment_detail.xml b/app/src/main/res/layout/fragment_detail.xml index bd33715..6a4bcb4 100644 --- a/app/src/main/res/layout/fragment_detail.xml +++ b/app/src/main/res/layout/fragment_detail.xml @@ -1,4 +1,18 @@ - + + + - + diff --git a/app/src/main/res/menu/bottom_nav_menu.xml b/app/src/main/res/menu/bottom_nav_menu.xml index 82443ce..b22c8c7 100644 --- a/app/src/main/res/menu/bottom_nav_menu.xml +++ b/app/src/main/res/menu/bottom_nav_menu.xml @@ -1,4 +1,18 @@ - + + + diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml index eca70cf..e7561ac 100644 --- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -1,4 +1,18 @@ - + diff --git a/app/src/main/res/navigation/nav_graph.xml b/app/src/main/res/navigation/nav_graph.xml index 86ebbcf..7525aa2 100644 --- a/app/src/main/res/navigation/nav_graph.xml +++ b/app/src/main/res/navigation/nav_graph.xml @@ -1,4 +1,18 @@ - + + #FFBB86FC #FF6200EE diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ad8d660..299af82 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,4 +1,19 @@ + kakao-search Home Fragment Search Fragment diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index 21d8f92..606468c 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -1,4 +1,19 @@ + + + \ No newline at end of file From 84c5ca8f1956bbbcfe345969786eedc767e4205f Mon Sep 17 00:00:00 2001 From: beomjo Date: Wed, 8 Sep 2021 02:06:14 +0900 Subject: [PATCH 230/273] chore: Set Image width percent --- app/src/main/res/layout/activity_detail.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/res/layout/activity_detail.xml b/app/src/main/res/layout/activity_detail.xml index 80f464c..8866eb7 100644 --- a/app/src/main/res/layout/activity_detail.xml +++ b/app/src/main/res/layout/activity_detail.xml @@ -71,6 +71,7 @@ android:id="@+id/image" android:layout_width="0dp" android:layout_height="0dp" + app:layout_constraintWidth_percent="0.3" android:layout_marginTop="10dp" android:adjustViewBounds="true" android:contentDescription="@android:string/untitled" From ca51ea1e07e2ff436d3fb7c957edbd00796ce58e Mon Sep 17 00:00:00 2001 From: beomjo Date: Thu, 9 Sep 2021 00:46:52 +0900 Subject: [PATCH 231/273] feat: Changing the tab name, modifying the layout of the detailed screen. --- .../io/github/beomjo/search/navigator/Tab.kt | 4 +- .../beomjo/search/ui/activity/MainActivity.kt | 2 +- ...ookmarkFragment.kt => FavoriteFragment.kt} | 9 +- app/src/main/res/drawable/ic_favorite.xml | 5 + .../main/res/drawable/ic_favorite_fill.xml | 10 + .../main/res/drawable/selector_favorite.xml | 5 + app/src/main/res/layout/activity_detail.xml | 249 +++++++++--------- ...ent_bookmark.xml => fragment_favorite.xml} | 4 +- app/src/main/res/menu/bottom_nav_menu.xml | 6 +- app/src/main/res/menu/nav_drawer_menu.xml | 6 +- app/src/main/res/navigation/main_graph.xml | 6 +- app/src/main/res/values-ko/strings.xml | 5 +- app/src/main/res/values/strings.xml | 5 +- 13 files changed, 171 insertions(+), 145 deletions(-) rename app/src/main/kotlin/io/github/beomjo/search/ui/fragment/{BookmarkFragment.kt => FavoriteFragment.kt} (78%) create mode 100644 app/src/main/res/drawable/ic_favorite.xml create mode 100644 app/src/main/res/drawable/ic_favorite_fill.xml create mode 100644 app/src/main/res/drawable/selector_favorite.xml rename app/src/main/res/layout/{fragment_bookmark.xml => fragment_favorite.xml} (92%) diff --git a/app/src/main/kotlin/io/github/beomjo/search/navigator/Tab.kt b/app/src/main/kotlin/io/github/beomjo/search/navigator/Tab.kt index 2650bd0..4ee7747 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/navigator/Tab.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/navigator/Tab.kt @@ -1,7 +1,7 @@ package io.github.beomjo.search.navigator import io.github.beomjo.search.R -import io.github.beomjo.search.ui.fragment.BookmarkFragment +import io.github.beomjo.search.ui.fragment.FavoriteFragment import io.github.beomjo.search.ui.fragment.SearchFragment enum class Tab( @@ -9,7 +9,7 @@ enum class Tab( val tag: String ) { SEARCH(R.id.search_dest, SearchFragment.TAG), - BOOKMARK(R.id.bookmark_dest, BookmarkFragment.TAG); + FAVORITE(R.id.favorite, FavoriteFragment.TAG); companion object } diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/activity/MainActivity.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/activity/MainActivity.kt index fc29d16..40ff733 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/activity/MainActivity.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/activity/MainActivity.kt @@ -42,7 +42,7 @@ class MainActivity : BaseActivity(R.layout.activity_main) { private val appBarConfiguration: AppBarConfiguration by lazy { AppBarConfiguration( - setOf(R.id.bookmark_dest, R.id.search_dest), + setOf(R.id.favorite, R.id.search_dest), binding.drawerLayout ) } diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/fragment/BookmarkFragment.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/fragment/FavoriteFragment.kt similarity index 78% rename from app/src/main/kotlin/io/github/beomjo/search/ui/fragment/BookmarkFragment.kt rename to app/src/main/kotlin/io/github/beomjo/search/ui/fragment/FavoriteFragment.kt index c461e0d..8289a8f 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/fragment/BookmarkFragment.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/fragment/FavoriteFragment.kt @@ -21,20 +21,19 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment -import androidx.navigation.fragment.findNavController -import io.github.beomjo.search.databinding.FragmentBookmarkBinding +import io.github.beomjo.search.databinding.FragmentFavoriteBinding -class BookmarkFragment : Fragment() { +class FavoriteFragment : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { - val binding = FragmentBookmarkBinding.inflate(layoutInflater) + val binding = FragmentFavoriteBinding.inflate(layoutInflater) return binding.root } companion object { - val TAG = BookmarkFragment::class.java.simpleName + val TAG = FavoriteFragment::class.java.simpleName } } diff --git a/app/src/main/res/drawable/ic_favorite.xml b/app/src/main/res/drawable/ic_favorite.xml new file mode 100644 index 0000000..83a924b --- /dev/null +++ b/app/src/main/res/drawable/ic_favorite.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_favorite_fill.xml b/app/src/main/res/drawable/ic_favorite_fill.xml new file mode 100644 index 0000000..48979b2 --- /dev/null +++ b/app/src/main/res/drawable/ic_favorite_fill.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/selector_favorite.xml b/app/src/main/res/drawable/selector_favorite.xml new file mode 100644 index 0000000..3ab163d --- /dev/null +++ b/app/src/main/res/drawable/selector_favorite.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_detail.xml b/app/src/main/res/layout/activity_detail.xml index 8866eb7..e21b2ca 100644 --- a/app/src/main/res/layout/activity_detail.xml +++ b/app/src/main/res/layout/activity_detail.xml @@ -24,15 +24,20 @@ type="io.github.beomjo.search.entity.Document" /> - + android:layout_height="wrap_content" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent"> - + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_bookmark.xml b/app/src/main/res/layout/fragment_favorite.xml similarity index 92% rename from app/src/main/res/layout/fragment_bookmark.xml rename to app/src/main/res/layout/fragment_favorite.xml index c99f002..c178bcb 100644 --- a/app/src/main/res/layout/fragment_bookmark.xml +++ b/app/src/main/res/layout/fragment_favorite.xml @@ -18,14 +18,14 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - tools:context="io.github.beomjo.search.ui.fragment.BookmarkFragment"> + tools:context="io.github.beomjo.search.ui.fragment.FavoriteFragment"> + android:id="@id/favorite" + android:icon="@drawable/ic_favorite" + android:title="@string/favorite" /> \ No newline at end of file diff --git a/app/src/main/res/menu/nav_drawer_menu.xml b/app/src/main/res/menu/nav_drawer_menu.xml index 7270aa9..e2a9cf6 100644 --- a/app/src/main/res/menu/nav_drawer_menu.xml +++ b/app/src/main/res/menu/nav_drawer_menu.xml @@ -21,8 +21,8 @@ android:title="@string/search_fragment_title" /> + android:id="@id/favorite" + android:icon="@drawable/ic_favorite" + android:title="@string/favorite" /> diff --git a/app/src/main/res/navigation/main_graph.xml b/app/src/main/res/navigation/main_graph.xml index 4f32591..372eee6 100644 --- a/app/src/main/res/navigation/main_graph.xml +++ b/app/src/main/res/navigation/main_graph.xml @@ -26,9 +26,9 @@ + android:id="@+id/favorite" + android:name="io.github.beomjo.search.ui.fragment.FavoriteFragment" + tools:layout="@layout/fragment_favorite"> Kakao Search - Bookmark Fragment + Favorite Fragment Search Fragment Detail Fragment - 북마크 + 좋아하는 검색 검색어를 입력하세요. 재시도 @@ -31,4 +31,5 @@ %1$tY년 %1$tm월 %1$td일 %1$tY년 %1$tm월 결과가 존재하지 않습니다. + 상세페이지로 이동 \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e0f63ff..449ea03 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -15,10 +15,10 @@ limitations under the License. --> Kakao Search - Bookmark Fragment + Favorite Fragment Search Fragment Detail Fragment - Bookmark + Favorite Search Input Search Keyword RETRY @@ -30,4 +30,5 @@ %1$tY-%1$tm-%1$td %1$tY-%1$tm The result does not exist. + Go Detail \ No newline at end of file From 7e69c30262f923e1b5314fe585fcf84e3aa2b5f3 Mon Sep 17 00:00:00 2001 From: beomjo Date: Thu, 9 Sep 2021 00:47:26 +0900 Subject: [PATCH 232/273] chore: Remove unused resource --- app/src/main/res/drawable/ic_bookmark.xml | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 app/src/main/res/drawable/ic_bookmark.xml diff --git a/app/src/main/res/drawable/ic_bookmark.xml b/app/src/main/res/drawable/ic_bookmark.xml deleted file mode 100644 index 7b2915b..0000000 --- a/app/src/main/res/drawable/ic_bookmark.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - From 96fa073aa4aa1cc0ab810dd0e231b27a248a133f Mon Sep 17 00:00:00 2001 From: beomjo Date: Thu, 9 Sep 2021 00:54:28 +0900 Subject: [PATCH 233/273] feat: Add detailActivity backbutton --- .../io/github/beomjo/search/ui/activity/DetailActivity.kt | 3 +++ app/src/main/res/drawable/ic_arrow_back.xml | 5 +++++ app/src/main/res/layout/activity_detail.xml | 1 + 3 files changed, 9 insertions(+) create mode 100644 app/src/main/res/drawable/ic_arrow_back.xml diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/activity/DetailActivity.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/activity/DetailActivity.kt index 997904f..299e08b 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/activity/DetailActivity.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/activity/DetailActivity.kt @@ -37,6 +37,9 @@ class DetailActivity : BaseActivity(R.layout.activity_det binding { lifecycleOwner = this@DetailActivity document = intent.getParcelableExtra(KEY_DOCUMENT) + toolBar.setNavigationOnClickListener { + onBackPressed() + } } } diff --git a/app/src/main/res/drawable/ic_arrow_back.xml b/app/src/main/res/drawable/ic_arrow_back.xml new file mode 100644 index 0000000..abf7df1 --- /dev/null +++ b/app/src/main/res/drawable/ic_arrow_back.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/layout/activity_detail.xml b/app/src/main/res/layout/activity_detail.xml index e21b2ca..6c5499e 100644 --- a/app/src/main/res/layout/activity_detail.xml +++ b/app/src/main/res/layout/activity_detail.xml @@ -43,6 +43,7 @@ android:id="@+id/toolBar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" + app:navigationIcon="@drawable/ic_arrow_back" app:title="@{document.type.name()}" /> From 653e2de6030c052047c35f3d66b43c328c9d0fd7 Mon Sep 17 00:00:00 2001 From: beomjo Date: Thu, 9 Sep 2021 01:31:41 +0900 Subject: [PATCH 234/273] feat: Implementation of detailed movement and favorite selector connection --- .../github/beomjo/search/ui/activity/DetailActivity.kt | 10 +++++++++- app/src/main/res/drawable/ic_favorite_fill.xml | 2 +- app/src/main/res/drawable/selector_favorite.xml | 4 ++-- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/activity/DetailActivity.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/activity/DetailActivity.kt index 299e08b..0354e7c 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/activity/DetailActivity.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/activity/DetailActivity.kt @@ -18,6 +18,7 @@ package io.github.beomjo.search.ui.activity import android.content.Context import android.content.Intent +import android.net.Uri import android.os.Bundle import dagger.hilt.android.AndroidEntryPoint import io.github.beomjo.search.R @@ -36,10 +37,17 @@ class DetailActivity : BaseActivity(R.layout.activity_det private fun bindLayout() { binding { lifecycleOwner = this@DetailActivity - document = intent.getParcelableExtra(KEY_DOCUMENT) + val documentData = intent.getParcelableExtra(KEY_DOCUMENT) + document = documentData toolBar.setNavigationOnClickListener { onBackPressed() } + moveWebviewBtn.setOnClickListener { + startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(documentData?.url))) + } + favoriteBtn.setOnClickListener { + favoriteBtn.isSelected = !favoriteBtn.isSelected + } } } diff --git a/app/src/main/res/drawable/ic_favorite_fill.xml b/app/src/main/res/drawable/ic_favorite_fill.xml index 48979b2..0e42ffc 100644 --- a/app/src/main/res/drawable/ic_favorite_fill.xml +++ b/app/src/main/res/drawable/ic_favorite_fill.xml @@ -5,6 +5,6 @@ android:viewportWidth="24" android:viewportHeight="24"> diff --git a/app/src/main/res/drawable/selector_favorite.xml b/app/src/main/res/drawable/selector_favorite.xml index 3ab163d..8f8dc33 100644 --- a/app/src/main/res/drawable/selector_favorite.xml +++ b/app/src/main/res/drawable/selector_favorite.xml @@ -1,5 +1,5 @@ - - + + \ No newline at end of file From 2485676dab416376a972cf20d2f700ce2418ef42 Mon Sep 17 00:00:00 2001 From: beomjo Date: Thu, 9 Sep 2021 02:43:57 +0900 Subject: [PATCH 235/273] feat: Add search item favorite button --- .../res/layout/search_list_document_item.xml | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/app/src/main/res/layout/search_list_document_item.xml b/app/src/main/res/layout/search_list_document_item.xml index 17f5652..9510680 100644 --- a/app/src/main/res/layout/search_list_document_item.xml +++ b/app/src/main/res/layout/search_list_document_item.xml @@ -44,10 +44,10 @@ android:contentDescription="@android:string/untitled" android:scaleType="fitCenter" app:imageUrl="@{document.thumbnail}" - app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintBottom_toBottomOf="@id/datetime" app:layout_constraintDimensionRatio="1" app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintTop_toTopOf="parent" /> + app:layout_constraintTop_toTopOf="@id/name" /> + + From 3754b8b3d7f35656ddb87952f610b146a13b1843 Mon Sep 17 00:00:00 2001 From: beomjo Date: Thu, 9 Sep 2021 03:33:05 +0900 Subject: [PATCH 236/273] feat: Implement visit usecase, add Visit Entity --- .../io/github/beomjo/search/entity/Visit.kt | 8 ++++ .../search/repository/SearchRepository.kt | 5 +++ .../search/usecase/GetSearchItemVisit.kt | 15 ++++++++ .../search/usecase/SetSearchItemVisit.kt | 15 ++++++++ .../search/usecase/GetSearchItemVisitSpec.kt | 38 +++++++++++++++++++ .../search/usecase/SetSearchItemVisitSpec.kt | 34 +++++++++++++++++ 6 files changed, 115 insertions(+) create mode 100644 domain/src/main/kotlin/io/github/beomjo/search/entity/Visit.kt create mode 100644 domain/src/main/kotlin/io/github/beomjo/search/usecase/GetSearchItemVisit.kt create mode 100644 domain/src/main/kotlin/io/github/beomjo/search/usecase/SetSearchItemVisit.kt create mode 100644 domain/src/test/java/io/github/beomjo/search/usecase/GetSearchItemVisitSpec.kt create mode 100644 domain/src/test/java/io/github/beomjo/search/usecase/SetSearchItemVisitSpec.kt diff --git a/domain/src/main/kotlin/io/github/beomjo/search/entity/Visit.kt b/domain/src/main/kotlin/io/github/beomjo/search/entity/Visit.kt new file mode 100644 index 0000000..c044345 --- /dev/null +++ b/domain/src/main/kotlin/io/github/beomjo/search/entity/Visit.kt @@ -0,0 +1,8 @@ +package io.github.beomjo.search.entity + +import java.util.* + +data class Visit( + val date: Date?, + val url: String, +) \ No newline at end of file diff --git a/domain/src/main/kotlin/io/github/beomjo/search/repository/SearchRepository.kt b/domain/src/main/kotlin/io/github/beomjo/search/repository/SearchRepository.kt index 351e1d0..6759b59 100644 --- a/domain/src/main/kotlin/io/github/beomjo/search/repository/SearchRepository.kt +++ b/domain/src/main/kotlin/io/github/beomjo/search/repository/SearchRepository.kt @@ -19,6 +19,7 @@ package io.github.beomjo.search.repository import androidx.paging.PagingData import io.github.beomjo.search.entity.Document import io.github.beomjo.search.entity.History +import io.github.beomjo.search.entity.Visit import io.github.beomjo.search.usecase.SearchPagingParam import kotlinx.coroutines.flow.Flow @@ -29,4 +30,8 @@ interface SearchRepository { suspend fun insertSearchHistory(history: History) fun getSearchHistoryList(): Flow> + + suspend fun setVisit(visit: Visit) + + fun getVisit(url:String) :Flow } diff --git a/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetSearchItemVisit.kt b/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetSearchItemVisit.kt new file mode 100644 index 0000000..b71a976 --- /dev/null +++ b/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetSearchItemVisit.kt @@ -0,0 +1,15 @@ +package io.github.beomjo.search.usecase + +import io.github.beomjo.search.entity.Visit +import io.github.beomjo.search.repository.SearchRepository +import io.github.beomjo.search.usecase.base.FlowUseCase +import kotlinx.coroutines.flow.Flow +import javax.inject.Inject + +class GetSearchItemVisit @Inject constructor( + private val searchRepository: SearchRepository +) : FlowUseCase() { + override fun execute(parameters: String): Flow { + return searchRepository.getVisit(parameters) + } +} \ No newline at end of file diff --git a/domain/src/main/kotlin/io/github/beomjo/search/usecase/SetSearchItemVisit.kt b/domain/src/main/kotlin/io/github/beomjo/search/usecase/SetSearchItemVisit.kt new file mode 100644 index 0000000..2890d11 --- /dev/null +++ b/domain/src/main/kotlin/io/github/beomjo/search/usecase/SetSearchItemVisit.kt @@ -0,0 +1,15 @@ +package io.github.beomjo.search.usecase + +import io.github.beomjo.search.entity.Visit +import io.github.beomjo.search.repository.SearchRepository +import io.github.beomjo.search.usecase.base.UseCase +import java.util.* +import javax.inject.Inject + +class SetSearchItemVisit @Inject constructor( + private val searchRepository: SearchRepository +) : UseCase() { + override suspend fun execute(url: String) { + searchRepository.setVisit(Visit(Date(), url)) + } +} \ No newline at end of file diff --git a/domain/src/test/java/io/github/beomjo/search/usecase/GetSearchItemVisitSpec.kt b/domain/src/test/java/io/github/beomjo/search/usecase/GetSearchItemVisitSpec.kt new file mode 100644 index 0000000..b451a54 --- /dev/null +++ b/domain/src/test/java/io/github/beomjo/search/usecase/GetSearchItemVisitSpec.kt @@ -0,0 +1,38 @@ +package io.github.beomjo.search.usecase + +import io.github.beomjo.search.entity.Visit +import io.github.beomjo.search.repository.SearchRepository +import io.kotest.core.spec.style.BehaviorSpec +import io.kotest.matchers.shouldBe +import io.mockk.* +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.flowOf + +class GetSearchItemVisitSpec : BehaviorSpec() { + + private val searchRepository = mockk() + + init { + Given("Given a url") { + val expectUrl = "http://" + val visit = mockk { + every { url } returns expectUrl + } + val useCase = GetSearchItemVisit(searchRepository) + every { searchRepository.getVisit(expectUrl) } returns flowOf(visit) + + When("Invoke") { + val result = useCase.invoke(expectUrl) + + Then("Should return a visit") { + verify { searchRepository.getVisit(eq(expectUrl)) } + result.first().url shouldBe expectUrl + } + } + } + + afterTest { + unmockkAll() + } + } +} \ No newline at end of file diff --git a/domain/src/test/java/io/github/beomjo/search/usecase/SetSearchItemVisitSpec.kt b/domain/src/test/java/io/github/beomjo/search/usecase/SetSearchItemVisitSpec.kt new file mode 100644 index 0000000..716f042 --- /dev/null +++ b/domain/src/test/java/io/github/beomjo/search/usecase/SetSearchItemVisitSpec.kt @@ -0,0 +1,34 @@ +package io.github.beomjo.search.usecase + +import io.github.beomjo.search.entity.Visit +import io.github.beomjo.search.repository.SearchRepository +import io.kotest.core.spec.style.BehaviorSpec +import io.kotest.matchers.shouldBe +import io.mockk.* + +class SetSearchItemVisitSpec : BehaviorSpec() { + + private val searchRepository = mockk() + + init { + Given("Given a url") { + val url = "http://..." + val useCase = SetSearchItemVisit(searchRepository) + val slot = slot() + coEvery { searchRepository.setVisit(capture(slot)) } just Runs + + When("Invoke") { + useCase.invoke(url) + + Then("Should call setVisit of SearchRepository") { + coEvery { searchRepository.setVisit(any()) } + slot.captured.url shouldBe url + } + } + } + + afterTest { + unmockkAll() + } + } +} \ No newline at end of file From 1f7d3d6af0e634839f70d09aa6ac3f9d7a23ae5c Mon Sep 17 00:00:00 2001 From: beomjo Date: Thu, 9 Sep 2021 03:50:04 +0900 Subject: [PATCH 237/273] chore: Change class naming --- .../search/ui/activity/DetailActivity.kt | 8 ++--- .../search/ui/adapter/SearchPagingAdapter.kt | 6 ++-- .../ui/adapter/diff/DocumentDiffUtil.kt | 4 +-- .../viewholders/SearchDocumentViewHolder.kt | 8 ++--- .../ui/paging/SearchSeparatorGenerator.kt | 20 ++++++------- .../search/ui/viewmodels/SearchViewModel.kt | 2 +- app/src/main/res/layout/activity_detail.xml | 2 +- .../res/layout/search_list_document_item.xml | 2 +- .../ui/viewmodels/SearchViewModelSpec.kt | 2 +- .../io/github/beomjo/search/DataModule.kt | 4 +-- .../search/datasource/local/AppDatabase.kt | 8 ++--- .../{DocumentDao.kt => SearchDocumentDao.kt} | 10 +++---- ...ocumentTable.kt => SearchDocumentTable.kt} | 2 +- .../remote/api/paging/SearchRemoteMediator.kt | 24 +++++++-------- ...umentMapper.kt => SearchDocumentMapper.kt} | 30 +++++++++---------- .../search/repository/SearchRepositoryImpl.kt | 17 ++++++++--- .../remote/SearchRemoteMediatorSpec.kt | 8 ++--- .../repository/SearchRepositoryImplSpec.kt | 12 ++++---- .../entity/{Document.kt => SearchDocument.kt} | 2 +- ...{DocumentList.kt => SearchDocumentList.kt} | 10 +++---- .../search/repository/SearchRepository.kt | 4 +-- .../search/usecase/GetSearchPagingData.kt | 4 +-- .../search/usecase/GetSearchPagingDataSpec.kt | 4 +-- 23 files changed, 101 insertions(+), 92 deletions(-) rename data/src/main/kotlin/io/github/beomjo/search/datasource/local/dao/{DocumentDao.kt => SearchDocumentDao.kt} (79%) rename data/src/main/kotlin/io/github/beomjo/search/datasource/local/table/{DocumentTable.kt => SearchDocumentTable.kt} (96%) rename data/src/main/kotlin/io/github/beomjo/search/mapper/{DocumentMapper.kt => SearchDocumentMapper.kt} (75%) rename domain/src/main/kotlin/io/github/beomjo/search/entity/{Document.kt => SearchDocument.kt} (97%) rename domain/src/main/kotlin/io/github/beomjo/search/entity/{DocumentList.kt => SearchDocumentList.kt} (74%) diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/activity/DetailActivity.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/activity/DetailActivity.kt index 0354e7c..e6f3657 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/activity/DetailActivity.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/activity/DetailActivity.kt @@ -24,7 +24,7 @@ import dagger.hilt.android.AndroidEntryPoint import io.github.beomjo.search.R import io.github.beomjo.search.base.BaseActivity import io.github.beomjo.search.databinding.ActivityDetailBinding -import io.github.beomjo.search.entity.Document +import io.github.beomjo.search.entity.SearchDocument @AndroidEntryPoint class DetailActivity : BaseActivity(R.layout.activity_detail) { @@ -37,7 +37,7 @@ class DetailActivity : BaseActivity(R.layout.activity_det private fun bindLayout() { binding { lifecycleOwner = this@DetailActivity - val documentData = intent.getParcelableExtra(KEY_DOCUMENT) + val documentData = intent.getParcelableExtra(KEY_DOCUMENT) document = documentData toolBar.setNavigationOnClickListener { onBackPressed() @@ -53,9 +53,9 @@ class DetailActivity : BaseActivity(R.layout.activity_det companion object { private const val KEY_DOCUMENT = "DetailActivity.Document" - fun action(context: Context, document: Document) { + fun action(context: Context, searchDocument: SearchDocument) { Intent(context, DetailActivity::class.java) - .apply { putExtra(KEY_DOCUMENT, document) } + .apply { putExtra(KEY_DOCUMENT, searchDocument) } .let { context.startActivity(it) } } } diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/SearchPagingAdapter.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/SearchPagingAdapter.kt index 98a3742..a4df28e 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/SearchPagingAdapter.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/SearchPagingAdapter.kt @@ -20,14 +20,14 @@ import android.view.ViewGroup import androidx.paging.PagingDataAdapter import androidx.recyclerview.widget.RecyclerView import io.github.beomjo.search.R -import io.github.beomjo.search.entity.Document +import io.github.beomjo.search.entity.SearchDocument import io.github.beomjo.search.ui.adapter.diff.DocumentDiffUtil import io.github.beomjo.search.ui.adapter.viewholders.SearchDocumentViewHolder import io.github.beomjo.search.ui.adapter.viewholders.SearchSeparatorViewHolder import io.github.beomjo.search.ui.viewmodels.SearchViewModel.SearchUiItem class SearchPagingAdapter( - private val onClickItem: (Document) -> Unit + private val onClickItem: (SearchDocument) -> Unit ) : PagingDataAdapter(DocumentDiffUtil()) { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { @@ -48,7 +48,7 @@ class SearchPagingAdapter( getItem(position)?.let { when (it) { is SearchUiItem.DocumentItem -> (holder as SearchDocumentViewHolder).bind( - it.document, + it.searchDocument, onClickItem ) is SearchUiItem.SeparatorItem -> (holder as SearchSeparatorViewHolder).bind(it.description) diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/diff/DocumentDiffUtil.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/diff/DocumentDiffUtil.kt index d0d4d97..7c08b31 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/diff/DocumentDiffUtil.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/diff/DocumentDiffUtil.kt @@ -26,8 +26,8 @@ class DocumentDiffUtil : DiffUtil.ItemCallback() { ): Boolean { val isSameDocumentItem = oldItem is SearchUiItem.DocumentItem && newItem is SearchUiItem.DocumentItem && - oldItem.document.title == newItem.document.title && - oldItem.document.date == newItem.document.date + oldItem.searchDocument.title == newItem.searchDocument.title && + oldItem.searchDocument.date == newItem.searchDocument.date val isSameSeparatorItem = oldItem is SearchUiItem.SeparatorItem && newItem is SearchUiItem.SeparatorItem && oldItem.description == newItem.description diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/viewholders/SearchDocumentViewHolder.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/viewholders/SearchDocumentViewHolder.kt index 7e2fa2b..c617247 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/viewholders/SearchDocumentViewHolder.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/viewholders/SearchDocumentViewHolder.kt @@ -20,16 +20,16 @@ import android.view.LayoutInflater import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView import io.github.beomjo.search.databinding.SearchListDocumentItemBinding -import io.github.beomjo.search.entity.Document +import io.github.beomjo.search.entity.SearchDocument class SearchDocumentViewHolder( private val binding: SearchListDocumentItemBinding, ) : RecyclerView.ViewHolder(binding.root) { - fun bind(document: Document, onClickItem: (Document) -> Unit) { + fun bind(searchDocument: SearchDocument, onClickItem: (SearchDocument) -> Unit) { binding.apply { - this.document = document - documentContainer.setOnClickListener { onClickItem(document) } + this.document = searchDocument + documentContainer.setOnClickListener { onClickItem(searchDocument) } executePendingBindings() } } diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/paging/SearchSeparatorGenerator.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/paging/SearchSeparatorGenerator.kt index bc561cd..6d2c2df 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/paging/SearchSeparatorGenerator.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/paging/SearchSeparatorGenerator.kt @@ -7,12 +7,12 @@ import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject import io.github.beomjo.search.R -import io.github.beomjo.search.entity.Document +import io.github.beomjo.search.entity.SearchDocument import io.github.beomjo.search.ui.viewmodels.SearchViewModel import io.github.beomjo.search.util.DateHelper class SearchSeparatorGenerator @AssistedInject constructor( - @Assisted val pagingData: PagingData, + @Assisted val pagingData: PagingData, private val dateHelper: DateHelper ) { @@ -21,13 +21,13 @@ class SearchSeparatorGenerator @AssistedInject constructor( .insertSeparators { before, after -> if (after == null) return@insertSeparators null if (before == null) return@insertSeparators SearchViewModel.SearchUiItem.SeparatorItem( - "${after.document.title.first()}" + "${after.searchDocument.title.first()}" ) - val beforeFirstWord = before.document.title.first() - val afterFirstWord = after.document.title.first() + val beforeFirstWord = before.searchDocument.title.first() + val afterFirstWord = after.searchDocument.title.first() return@insertSeparators when (beforeFirstWord != afterFirstWord) { - true -> SearchViewModel.SearchUiItem.SeparatorItem("${after.document.title.first()}") + true -> SearchViewModel.SearchUiItem.SeparatorItem("${after.searchDocument.title.first()}") else -> null } } @@ -38,11 +38,11 @@ class SearchSeparatorGenerator @AssistedInject constructor( .insertSeparators { before, after -> if (after == null) return@insertSeparators null if (before == null) return@insertSeparators SearchViewModel.SearchUiItem.SeparatorItem( - dateHelper.convert(after.document.date) + dateHelper.convert(after.searchDocument.date) ) - val beforeDate = before.document.date - val afterDate = after.document.date + val beforeDate = before.searchDocument.date + val afterDate = after.searchDocument.date val beforeDateString = dateHelper.convert(beforeDate, R.string.date_month) val afterDateString = dateHelper.convert(afterDate) @@ -56,5 +56,5 @@ class SearchSeparatorGenerator @AssistedInject constructor( @AssistedFactory interface SearchSeparatorFactory { - fun create(pagingData: PagingData): SearchSeparatorGenerator + fun create(pagingData: PagingData): SearchSeparatorGenerator } diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/SearchViewModel.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/SearchViewModel.kt index 952e1ee..4e4204c 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/SearchViewModel.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/SearchViewModel.kt @@ -85,7 +85,7 @@ class SearchViewModel @Inject constructor( } sealed class SearchUiItem { - data class DocumentItem(val document: Document) : SearchUiItem() + data class DocumentItem(val searchDocument: SearchDocument) : SearchUiItem() data class SeparatorItem(val description: String) : SearchUiItem() } } diff --git a/app/src/main/res/layout/activity_detail.xml b/app/src/main/res/layout/activity_detail.xml index 6c5499e..e4fc0d6 100644 --- a/app/src/main/res/layout/activity_detail.xml +++ b/app/src/main/res/layout/activity_detail.xml @@ -21,7 +21,7 @@ + type="io.github.beomjo.search.entity.SearchDocument" /> diff --git a/app/src/main/res/layout/search_list_document_item.xml b/app/src/main/res/layout/search_list_document_item.xml index 9510680..9c2cc70 100644 --- a/app/src/main/res/layout/search_list_document_item.xml +++ b/app/src/main/res/layout/search_list_document_item.xml @@ -21,7 +21,7 @@ + type="io.github.beomjo.search.entity.SearchDocument" /> ( + val pagingData = PagingData.from( listOf(mockk()) ) diff --git a/data/src/main/kotlin/io/github/beomjo/search/DataModule.kt b/data/src/main/kotlin/io/github/beomjo/search/DataModule.kt index c39306a..8806043 100644 --- a/data/src/main/kotlin/io/github/beomjo/search/DataModule.kt +++ b/data/src/main/kotlin/io/github/beomjo/search/DataModule.kt @@ -24,7 +24,7 @@ import dagger.hilt.InstallIn import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent import io.github.beomjo.search.datasource.local.AppDatabase -import io.github.beomjo.search.datasource.local.dao.DocumentDao +import io.github.beomjo.search.datasource.local.dao.SearchDocumentDao import io.github.beomjo.search.datasource.local.dao.RemoteKeyDao import io.github.beomjo.search.datasource.local.dao.SearchHistoryDao import io.github.beomjo.search.datasource.remote.api.RetrofitAdapter @@ -55,7 +55,7 @@ internal object DataModule { @Singleton @Provides - fun provideDocumentDao(database: AppDatabase): DocumentDao { + fun provideDocumentDao(database: AppDatabase): SearchDocumentDao { return database.documentDao() } diff --git a/data/src/main/kotlin/io/github/beomjo/search/datasource/local/AppDatabase.kt b/data/src/main/kotlin/io/github/beomjo/search/datasource/local/AppDatabase.kt index 0f646dd..c96fa9e 100644 --- a/data/src/main/kotlin/io/github/beomjo/search/datasource/local/AppDatabase.kt +++ b/data/src/main/kotlin/io/github/beomjo/search/datasource/local/AppDatabase.kt @@ -22,22 +22,22 @@ import androidx.room.Room import androidx.room.RoomDatabase import androidx.room.TypeConverters import io.github.beomjo.search.datasource.local.converter.DateConverter -import io.github.beomjo.search.datasource.local.dao.DocumentDao +import io.github.beomjo.search.datasource.local.dao.SearchDocumentDao import io.github.beomjo.search.datasource.local.dao.RemoteKeyDao import io.github.beomjo.search.datasource.local.dao.SearchHistoryDao -import io.github.beomjo.search.datasource.local.table.DocumentTable +import io.github.beomjo.search.datasource.local.table.SearchDocumentTable import io.github.beomjo.search.datasource.local.table.RemoteKeyTable import io.github.beomjo.search.datasource.local.table.SearchHistoryTable @Database( - entities = [DocumentTable::class, RemoteKeyTable::class, SearchHistoryTable::class], + entities = [SearchDocumentTable::class, RemoteKeyTable::class, SearchHistoryTable::class], version = 1, exportSchema = false ) @TypeConverters(DateConverter::class) internal abstract class AppDatabase : RoomDatabase() { - abstract fun documentDao(): DocumentDao + abstract fun documentDao(): SearchDocumentDao abstract fun remoteKeyDao(): RemoteKeyDao diff --git a/data/src/main/kotlin/io/github/beomjo/search/datasource/local/dao/DocumentDao.kt b/data/src/main/kotlin/io/github/beomjo/search/datasource/local/dao/SearchDocumentDao.kt similarity index 79% rename from data/src/main/kotlin/io/github/beomjo/search/datasource/local/dao/DocumentDao.kt rename to data/src/main/kotlin/io/github/beomjo/search/datasource/local/dao/SearchDocumentDao.kt index c121e92..a8b3160 100644 --- a/data/src/main/kotlin/io/github/beomjo/search/datasource/local/dao/DocumentDao.kt +++ b/data/src/main/kotlin/io/github/beomjo/search/datasource/local/dao/SearchDocumentDao.kt @@ -21,26 +21,26 @@ import androidx.room.Dao import androidx.room.Insert import androidx.room.OnConflictStrategy import androidx.room.Query -import io.github.beomjo.search.datasource.local.table.DocumentTable +import io.github.beomjo.search.datasource.local.table.SearchDocumentTable @Dao -internal interface DocumentDao { +internal interface SearchDocumentDao { @Insert(onConflict = OnConflictStrategy.REPLACE) - suspend fun insertDocuments(documents: List) + suspend fun insertDocuments(documents: List) @Query( "SELECT * FROM document_table " + "WHERE title Like '%'||:query||'%' or content Like '%'||:query||'%' " + "ORDER BY date DESC" ) - fun getDocumentByDate(query: String): PagingSource + fun getDocumentByDate(query: String): PagingSource @Query( "SELECT * FROM document_table " + "WHERE title Like '%'||:query||'%' or content Like '%'||:query||'%' " + "ORDER BY title ASC" ) - fun getDocumentByTitle(query: String): PagingSource + fun getDocumentByTitle(query: String): PagingSource @Query("DELETE from document_table") suspend fun clearAllDocuments() diff --git a/data/src/main/kotlin/io/github/beomjo/search/datasource/local/table/DocumentTable.kt b/data/src/main/kotlin/io/github/beomjo/search/datasource/local/table/SearchDocumentTable.kt similarity index 96% rename from data/src/main/kotlin/io/github/beomjo/search/datasource/local/table/DocumentTable.kt rename to data/src/main/kotlin/io/github/beomjo/search/datasource/local/table/SearchDocumentTable.kt index d79ee49..0dee8d0 100644 --- a/data/src/main/kotlin/io/github/beomjo/search/datasource/local/table/DocumentTable.kt +++ b/data/src/main/kotlin/io/github/beomjo/search/datasource/local/table/SearchDocumentTable.kt @@ -23,7 +23,7 @@ import io.github.beomjo.search.entity.DocumentType import java.util.Date @Entity(tableName = "document_table") -internal data class DocumentTable( +internal data class SearchDocumentTable( @field:SerializedName("type") val type: DocumentType, @PrimaryKey diff --git a/data/src/main/kotlin/io/github/beomjo/search/datasource/remote/api/paging/SearchRemoteMediator.kt b/data/src/main/kotlin/io/github/beomjo/search/datasource/remote/api/paging/SearchRemoteMediator.kt index fe7fd41..5c4d002 100644 --- a/data/src/main/kotlin/io/github/beomjo/search/datasource/remote/api/paging/SearchRemoteMediator.kt +++ b/data/src/main/kotlin/io/github/beomjo/search/datasource/remote/api/paging/SearchRemoteMediator.kt @@ -25,10 +25,10 @@ import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject import io.github.beomjo.search.datasource.local.AppDatabase -import io.github.beomjo.search.datasource.local.table.DocumentTable +import io.github.beomjo.search.datasource.local.table.SearchDocumentTable import io.github.beomjo.search.datasource.local.table.RemoteKeyTable import io.github.beomjo.search.datasource.remote.api.service.DocumentsApi -import io.github.beomjo.search.entity.DocumentList +import io.github.beomjo.search.entity.SearchDocumentList import io.github.beomjo.search.entity.DocumentType import io.github.beomjo.search.mapper.toEntity import io.github.beomjo.search.mapper.toTable @@ -41,11 +41,11 @@ internal class SearchRemoteMediator @AssistedInject constructor( @Assisted private val requestParam: SearchPagingParam, private val documentApi: DocumentsApi, private val database: AppDatabase, -) : RemoteMediator() { +) : RemoteMediator() { override suspend fun load( loadType: LoadType, - state: PagingState + state: PagingState ): MediatorResult { try { val position: Int = when (loadType) { @@ -73,7 +73,7 @@ internal class SearchRemoteMediator @AssistedInject constructor( val nextKey = if (documentList.hasMore) position + 1 else null val keys = RemoteKeyTable(position = position, prevKey = prevKey, nextKey = nextKey) - database.documentDao().insertDocuments(documentList.documents.map { it.toTable() }) + database.documentDao().insertDocuments(documentList.searchDocuments.map { it.toTable() }) database.remoteKeyDao().insertKey(keys) } @@ -103,7 +103,7 @@ internal class SearchRemoteMediator @AssistedInject constructor( DocumentType.BOOK -> fetchBookList(position, PER_PAGE_SIZE) } - private suspend fun fetchBlogList(pagePosition: Int, pageSize: Int): DocumentList { + private suspend fun fetchBlogList(pagePosition: Int, pageSize: Int): SearchDocumentList { if (pagePosition > MAX_PAGE_POSITION) return getEmptyDocumentList() return documentApi.fetchBlog( query = requestParam.query, @@ -113,7 +113,7 @@ internal class SearchRemoteMediator @AssistedInject constructor( ).toEntity() } - private suspend fun fetchCafeList(pagePosition: Int, pageSize: Int): DocumentList { + private suspend fun fetchCafeList(pagePosition: Int, pageSize: Int): SearchDocumentList { if (pagePosition > MAX_PAGE_POSITION) return getEmptyDocumentList() return documentApi.fetchCafe( query = requestParam.query, @@ -123,7 +123,7 @@ internal class SearchRemoteMediator @AssistedInject constructor( ).toEntity() } - private suspend fun fetchWebList(pagePosition: Int, pageSize: Int): DocumentList { + private suspend fun fetchWebList(pagePosition: Int, pageSize: Int): SearchDocumentList { if (pagePosition > MAX_PAGE_POSITION) return getEmptyDocumentList() return documentApi.fetchWeb( query = requestParam.query, @@ -133,7 +133,7 @@ internal class SearchRemoteMediator @AssistedInject constructor( ).toEntity() } - private suspend fun fetchImageList(pagePosition: Int, pageSize: Int): DocumentList { + private suspend fun fetchImageList(pagePosition: Int, pageSize: Int): SearchDocumentList { if (pagePosition > MAX_PAGE_POSITION) return getEmptyDocumentList() val documentList = documentApi.fetchImages( query = requestParam.query, @@ -142,13 +142,13 @@ internal class SearchRemoteMediator @AssistedInject constructor( size = pageSize ).toEntity() return documentList.copy( - documents = documentList.documents.map { + searchDocuments = documentList.searchDocuments.map { it.copy(content = requestParam.query) } ) } - private suspend fun fetchBookList(pagePosition: Int, pageSize: Int): DocumentList { + private suspend fun fetchBookList(pagePosition: Int, pageSize: Int): SearchDocumentList { if (pagePosition > MAX_PAGE_POSITION) return getEmptyDocumentList() return documentApi.fetchBook( query = requestParam.query, @@ -158,7 +158,7 @@ internal class SearchRemoteMediator @AssistedInject constructor( ).toEntity() } - private fun getEmptyDocumentList() = DocumentList(hasMore = false, emptyList()) + private fun getEmptyDocumentList() = SearchDocumentList(hasMore = false, emptyList()) companion object { const val STARTING_POSITION = 1 diff --git a/data/src/main/kotlin/io/github/beomjo/search/mapper/DocumentMapper.kt b/data/src/main/kotlin/io/github/beomjo/search/mapper/SearchDocumentMapper.kt similarity index 75% rename from data/src/main/kotlin/io/github/beomjo/search/mapper/DocumentMapper.kt rename to data/src/main/kotlin/io/github/beomjo/search/mapper/SearchDocumentMapper.kt index c0077d1..1803bb4 100644 --- a/data/src/main/kotlin/io/github/beomjo/search/mapper/DocumentMapper.kt +++ b/data/src/main/kotlin/io/github/beomjo/search/mapper/SearchDocumentMapper.kt @@ -16,9 +16,9 @@ package io.github.beomjo.search.mapper -import io.github.beomjo.search.datasource.local.table.DocumentTable -import io.github.beomjo.search.entity.Document -import io.github.beomjo.search.entity.DocumentList +import io.github.beomjo.search.datasource.local.table.SearchDocumentTable +import io.github.beomjo.search.entity.SearchDocument +import io.github.beomjo.search.entity.SearchDocumentList import io.github.beomjo.search.entity.DocumentType import io.github.beomjo.search.model.BlogResponse import io.github.beomjo.search.model.BookResponse @@ -28,10 +28,10 @@ import io.github.beomjo.search.model.ImageResponse import io.github.beomjo.search.model.WebResponse import java.lang.IllegalStateException -internal fun DocumentListResponse.toEntity(): DocumentList { - return DocumentList( +internal fun DocumentListResponse.toEntity(): SearchDocumentList { + return SearchDocumentList( hasMore = !meta.isEnd, - documents = documents.map { + searchDocuments = documents.map { when (it) { is BlogResponse -> it.toEntity() is CafeResponse -> it.toEntity() @@ -44,7 +44,7 @@ internal fun DocumentListResponse.toEntity(): DocumentList { ) } -internal fun BlogResponse.toEntity(): Document = Document( +internal fun BlogResponse.toEntity(): SearchDocument = SearchDocument( type = DocumentType.BLOG, url = url, thumbnail = thumbnail, @@ -53,7 +53,7 @@ internal fun BlogResponse.toEntity(): Document = Document( date = datetime, ) -internal fun CafeResponse.toEntity(): Document = Document( +internal fun CafeResponse.toEntity(): SearchDocument = SearchDocument( type = DocumentType.CAFE, url = url, thumbnail = thumbnail, @@ -62,7 +62,7 @@ internal fun CafeResponse.toEntity(): Document = Document( date = datetime, ) -internal fun ImageResponse.toEntity(): Document = Document( +internal fun ImageResponse.toEntity(): SearchDocument = SearchDocument( type = DocumentType.IMAGE, url = docUrl, thumbnail = thumbnailUrl, @@ -71,7 +71,7 @@ internal fun ImageResponse.toEntity(): Document = Document( date = datetime, ) -internal fun WebResponse.toEntity(): Document = Document( +internal fun WebResponse.toEntity(): SearchDocument = SearchDocument( type = DocumentType.WEB, url = url, thumbnail = "", @@ -80,7 +80,7 @@ internal fun WebResponse.toEntity(): Document = Document( date = datetime, ) -internal fun BookResponse.toEntity(): Document = Document( +internal fun BookResponse.toEntity(): SearchDocument = SearchDocument( type = DocumentType.BOOK, url = url, thumbnail = thumbnail, @@ -89,8 +89,8 @@ internal fun BookResponse.toEntity(): Document = Document( date = datetime, ) -internal fun Document.toTable(): DocumentTable { - return DocumentTable( +internal fun SearchDocument.toTable(): SearchDocumentTable { + return SearchDocumentTable( type = this.type, url = this.url, thumbnail = this.thumbnail, @@ -100,8 +100,8 @@ internal fun Document.toTable(): DocumentTable { ) } -internal fun DocumentTable.toEntity(): Document { - return Document( +internal fun SearchDocumentTable.toEntity(): SearchDocument { + return SearchDocument( type = this.type, url = this.url, thumbnail = this.thumbnail, diff --git a/data/src/main/kotlin/io/github/beomjo/search/repository/SearchRepositoryImpl.kt b/data/src/main/kotlin/io/github/beomjo/search/repository/SearchRepositoryImpl.kt index 4490302..f3fbef4 100644 --- a/data/src/main/kotlin/io/github/beomjo/search/repository/SearchRepositoryImpl.kt +++ b/data/src/main/kotlin/io/github/beomjo/search/repository/SearchRepositoryImpl.kt @@ -21,17 +21,19 @@ import androidx.paging.map import androidx.paging.ExperimentalPagingApi import androidx.paging.Pager import androidx.paging.PagingConfig -import io.github.beomjo.search.datasource.local.dao.DocumentDao +import io.github.beomjo.search.datasource.local.dao.SearchDocumentDao import io.github.beomjo.search.datasource.local.dao.SearchHistoryDao import io.github.beomjo.search.datasource.remote.api.paging.SearchRemoteMediator import io.github.beomjo.search.datasource.remote.api.paging.SearchRemoteMediatorFactory -import io.github.beomjo.search.entity.Document +import io.github.beomjo.search.entity.SearchDocument import io.github.beomjo.search.entity.History import io.github.beomjo.search.entity.SortType +import io.github.beomjo.search.entity.Visit import io.github.beomjo.search.mapper.toEntity import io.github.beomjo.search.mapper.toTable import io.github.beomjo.search.usecase.SearchPagingParam import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map import javax.inject.Inject import javax.inject.Singleton @@ -39,10 +41,10 @@ import javax.inject.Singleton @Singleton internal class SearchRepositoryImpl @Inject constructor( private val searchRemoteMediatorFactory: SearchRemoteMediatorFactory, - private val documentDao: DocumentDao, + private val documentDao: SearchDocumentDao, private val searchHistoryDao: SearchHistoryDao ) : SearchRepository { - override fun getDocumentPagingData(param: SearchPagingParam): Flow> { + override fun getDocumentPagingData(param: SearchPagingParam): Flow> { @OptIn(ExperimentalPagingApi::class) return Pager( config = PagingConfig( @@ -72,4 +74,11 @@ internal class SearchRepositoryImpl @Inject constructor( historyList.map { it.toEntity() } } } + + override suspend fun setVisit(visit: Visit) { + } + + override fun getVisit(url: String): Flow { + return flowOf() + } } diff --git a/data/src/test/java/io/github/beomjo/search/datasource/remote/SearchRemoteMediatorSpec.kt b/data/src/test/java/io/github/beomjo/search/datasource/remote/SearchRemoteMediatorSpec.kt index 471742e..0e96a5d 100644 --- a/data/src/test/java/io/github/beomjo/search/datasource/remote/SearchRemoteMediatorSpec.kt +++ b/data/src/test/java/io/github/beomjo/search/datasource/remote/SearchRemoteMediatorSpec.kt @@ -23,7 +23,7 @@ import androidx.paging.RemoteMediator import androidx.room.withTransaction import io.github.beomjo.search.data.R import io.github.beomjo.search.datasource.local.AppDatabase -import io.github.beomjo.search.datasource.local.table.DocumentTable +import io.github.beomjo.search.datasource.local.table.SearchDocumentTable import io.github.beomjo.search.datasource.local.table.RemoteKeyTable import io.github.beomjo.search.datasource.remote.api.paging.SearchRemoteMediator import io.github.beomjo.search.datasource.remote.api.service.DocumentsApi @@ -59,7 +59,7 @@ internal class SearchRemoteMediatorSpec : BehaviorSpec() { private val database: AppDatabase = mockk(relaxUnitFun = true) - private val state = mockk>() + private val state = mockk>() private val blogResponse = mockk> { every { meta.isEnd } returns false @@ -198,7 +198,7 @@ internal class SearchRemoteMediatorSpec : BehaviorSpec() { sort = Sort.ACCURACY, ) - val state = mockk>() + val state = mockk>() val pageSize = SearchRemoteMediator.PER_PAGE_SIZE @@ -893,7 +893,7 @@ internal class SearchRemoteMediatorSpec : BehaviorSpec() { sort = Sort.ACCURACY, ) - val state = mockk>() + val state = mockk>() val allTypePageSize = SearchRemoteMediator.PER_PAGE_SIZE / SearchRemoteMediator.DOCUMENT_TYPE_NUM diff --git a/data/src/test/java/io/github/beomjo/search/repository/SearchRepositoryImplSpec.kt b/data/src/test/java/io/github/beomjo/search/repository/SearchRepositoryImplSpec.kt index 89f59bb..13a5f03 100644 --- a/data/src/test/java/io/github/beomjo/search/repository/SearchRepositoryImplSpec.kt +++ b/data/src/test/java/io/github/beomjo/search/repository/SearchRepositoryImplSpec.kt @@ -19,9 +19,9 @@ package io.github.beomjo.search.repository import androidx.paging.ExperimentalPagingApi import androidx.paging.PagingData import androidx.paging.PagingSource -import io.github.beomjo.search.datasource.local.dao.DocumentDao +import io.github.beomjo.search.datasource.local.dao.SearchDocumentDao import io.github.beomjo.search.datasource.local.dao.SearchHistoryDao -import io.github.beomjo.search.datasource.local.table.DocumentTable +import io.github.beomjo.search.datasource.local.table.SearchDocumentTable import io.github.beomjo.search.datasource.local.table.SearchHistoryTable import io.github.beomjo.search.datasource.remote.api.paging.SearchRemoteMediator import io.github.beomjo.search.datasource.remote.api.paging.SearchRemoteMediatorFactory @@ -43,9 +43,9 @@ internal class SearchRepositoryImplSpec : BehaviorSpec() { private val searchRemoteMediator = mockk(relaxed = true) - private val pagingSource = mockk>(relaxed = true) + private val pagingSource = mockk>(relaxed = true) - private val documentDao = mockk(relaxed = true) + private val documentDao = mockk(relaxed = true) private val searchHistoryDao = mockk(relaxed = true) @@ -73,7 +73,7 @@ internal class SearchRepositoryImplSpec : BehaviorSpec() { val resultFlow = searchRepositoryImpl.getDocumentPagingData(param) Then("Returns PagingData sorted by TITLE") { - resultFlow.first().shouldBeTypeOf>() + resultFlow.first().shouldBeTypeOf>() coVerify { documentDao.getDocumentByTitle(eq(param.query)) } coVerify(inverse = true) { documentDao.getDocumentByDate(any()) } @@ -103,7 +103,7 @@ internal class SearchRepositoryImplSpec : BehaviorSpec() { val resultFlow = searchRepositoryImpl.getDocumentPagingData(param) Then("Returns PagingData sorted by DATE") { - resultFlow.first().shouldBeTypeOf>() + resultFlow.first().shouldBeTypeOf>() coVerify(inverse = true) { documentDao.getDocumentByTitle(any()) } coVerify { documentDao.getDocumentByDate(eq(param.query)) } diff --git a/domain/src/main/kotlin/io/github/beomjo/search/entity/Document.kt b/domain/src/main/kotlin/io/github/beomjo/search/entity/SearchDocument.kt similarity index 97% rename from domain/src/main/kotlin/io/github/beomjo/search/entity/Document.kt rename to domain/src/main/kotlin/io/github/beomjo/search/entity/SearchDocument.kt index 2c146e1..0d5b374 100644 --- a/domain/src/main/kotlin/io/github/beomjo/search/entity/Document.kt +++ b/domain/src/main/kotlin/io/github/beomjo/search/entity/SearchDocument.kt @@ -21,7 +21,7 @@ import kotlinx.android.parcel.Parcelize import java.util.Date @Parcelize -data class Document( +data class SearchDocument( val type: DocumentType, val url: String, val thumbnail: String, diff --git a/domain/src/main/kotlin/io/github/beomjo/search/entity/DocumentList.kt b/domain/src/main/kotlin/io/github/beomjo/search/entity/SearchDocumentList.kt similarity index 74% rename from domain/src/main/kotlin/io/github/beomjo/search/entity/DocumentList.kt rename to domain/src/main/kotlin/io/github/beomjo/search/entity/SearchDocumentList.kt index 3b1b693..0b87558 100644 --- a/domain/src/main/kotlin/io/github/beomjo/search/entity/DocumentList.kt +++ b/domain/src/main/kotlin/io/github/beomjo/search/entity/SearchDocumentList.kt @@ -16,14 +16,14 @@ package io.github.beomjo.search.entity -data class DocumentList( +data class SearchDocumentList( val hasMore: Boolean, - val documents: List + val searchDocuments: List ) { - operator fun plus(other: DocumentList): DocumentList { - return DocumentList( + operator fun plus(other: SearchDocumentList): SearchDocumentList { + return SearchDocumentList( hasMore = this.hasMore || other.hasMore, - documents = this.documents + other.documents + searchDocuments = this.searchDocuments + other.searchDocuments ) } } diff --git a/domain/src/main/kotlin/io/github/beomjo/search/repository/SearchRepository.kt b/domain/src/main/kotlin/io/github/beomjo/search/repository/SearchRepository.kt index 6759b59..7ac3b59 100644 --- a/domain/src/main/kotlin/io/github/beomjo/search/repository/SearchRepository.kt +++ b/domain/src/main/kotlin/io/github/beomjo/search/repository/SearchRepository.kt @@ -17,7 +17,7 @@ package io.github.beomjo.search.repository import androidx.paging.PagingData -import io.github.beomjo.search.entity.Document +import io.github.beomjo.search.entity.SearchDocument import io.github.beomjo.search.entity.History import io.github.beomjo.search.entity.Visit import io.github.beomjo.search.usecase.SearchPagingParam @@ -25,7 +25,7 @@ import kotlinx.coroutines.flow.Flow interface SearchRepository { - fun getDocumentPagingData(param: SearchPagingParam): Flow> + fun getDocumentPagingData(param: SearchPagingParam): Flow> suspend fun insertSearchHistory(history: History) diff --git a/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetSearchPagingData.kt b/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetSearchPagingData.kt index b4007ed..1133529 100644 --- a/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetSearchPagingData.kt +++ b/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetSearchPagingData.kt @@ -35,8 +35,8 @@ data class SearchPagingParam( class GetSearchPagingData @Inject constructor( private val searchRepository: SearchRepository -) : PagingUseCase() { - override fun execute(parameters: SearchPagingParam): Flow> { +) : PagingUseCase() { + override fun execute(parameters: SearchPagingParam): Flow> { return searchRepository.getDocumentPagingData(parameters) .onStart { searchRepository.insertSearchHistory( diff --git a/domain/src/test/java/io/github/beomjo/search/usecase/GetSearchPagingDataSpec.kt b/domain/src/test/java/io/github/beomjo/search/usecase/GetSearchPagingDataSpec.kt index 2614cfa..ea3c4e0 100644 --- a/domain/src/test/java/io/github/beomjo/search/usecase/GetSearchPagingDataSpec.kt +++ b/domain/src/test/java/io/github/beomjo/search/usecase/GetSearchPagingDataSpec.kt @@ -17,7 +17,7 @@ package io.github.beomjo.search.usecase import androidx.paging.PagingData -import io.github.beomjo.search.entity.Document +import io.github.beomjo.search.entity.SearchDocument import io.github.beomjo.search.entity.DocumentType import io.github.beomjo.search.entity.Sort import io.github.beomjo.search.entity.SortType @@ -43,7 +43,7 @@ class GetSearchPagingDataSpec : BehaviorSpec() { query = "IU", sort = Sort.ACCURACY ) - val pagingData = mockk>() + val pagingData = mockk>() coEvery { searchRepository.getDocumentPagingData(param) } returns flowOf(pagingData) coEvery { searchRepository.insertSearchHistory(any()) } just Runs From 034dfa9abe4a5de8f9d468fb6a3bf3864638f9d5 Mon Sep 17 00:00:00 2001 From: beomjo Date: Thu, 9 Sep 2021 04:15:35 +0900 Subject: [PATCH 238/273] feat: Implement Room Visit Table, Entity, and RepositoryImpl --- .../io/github/beomjo/search/DataModule.kt | 7 ++ .../search/datasource/local/AppDatabase.kt | 11 ++- .../search/datasource/local/dao/VisitDao.kt | 18 +++++ .../datasource/local/table/VisitTable.kt | 15 ++++ .../beomjo/search/mapper/VisitMapper.kt | 18 +++++ .../search/repository/SearchRepositoryImpl.kt | 10 ++- .../repository/SearchRepositoryImplSpec.kt | 77 ++++++++++++++++--- .../search/repository/SearchRepository.kt | 2 +- .../search/usecase/SetSearchItemVisit.kt | 2 +- .../search/usecase/SetSearchItemVisitSpec.kt | 4 +- 10 files changed, 145 insertions(+), 19 deletions(-) create mode 100644 data/src/main/kotlin/io/github/beomjo/search/datasource/local/dao/VisitDao.kt create mode 100644 data/src/main/kotlin/io/github/beomjo/search/datasource/local/table/VisitTable.kt create mode 100644 data/src/main/kotlin/io/github/beomjo/search/mapper/VisitMapper.kt diff --git a/data/src/main/kotlin/io/github/beomjo/search/DataModule.kt b/data/src/main/kotlin/io/github/beomjo/search/DataModule.kt index 8806043..c78a2cc 100644 --- a/data/src/main/kotlin/io/github/beomjo/search/DataModule.kt +++ b/data/src/main/kotlin/io/github/beomjo/search/DataModule.kt @@ -27,6 +27,7 @@ import io.github.beomjo.search.datasource.local.AppDatabase import io.github.beomjo.search.datasource.local.dao.SearchDocumentDao import io.github.beomjo.search.datasource.local.dao.RemoteKeyDao import io.github.beomjo.search.datasource.local.dao.SearchHistoryDao +import io.github.beomjo.search.datasource.local.dao.VisitDao import io.github.beomjo.search.datasource.remote.api.RetrofitAdapter import io.github.beomjo.search.datasource.remote.api.Urls import io.github.beomjo.search.datasource.remote.api.service.DocumentsApi @@ -71,6 +72,12 @@ internal object DataModule { return database.searchHistoryDao() } + @Singleton + @Provides + fun provideVisitDao(database: AppDatabase): VisitDao { + return database.visitDao() + } + @Module @InstallIn(SingletonComponent::class) abstract class DataBindModule { diff --git a/data/src/main/kotlin/io/github/beomjo/search/datasource/local/AppDatabase.kt b/data/src/main/kotlin/io/github/beomjo/search/datasource/local/AppDatabase.kt index c96fa9e..5423bfc 100644 --- a/data/src/main/kotlin/io/github/beomjo/search/datasource/local/AppDatabase.kt +++ b/data/src/main/kotlin/io/github/beomjo/search/datasource/local/AppDatabase.kt @@ -25,12 +25,19 @@ import io.github.beomjo.search.datasource.local.converter.DateConverter import io.github.beomjo.search.datasource.local.dao.SearchDocumentDao import io.github.beomjo.search.datasource.local.dao.RemoteKeyDao import io.github.beomjo.search.datasource.local.dao.SearchHistoryDao +import io.github.beomjo.search.datasource.local.dao.VisitDao import io.github.beomjo.search.datasource.local.table.SearchDocumentTable import io.github.beomjo.search.datasource.local.table.RemoteKeyTable import io.github.beomjo.search.datasource.local.table.SearchHistoryTable +import io.github.beomjo.search.datasource.local.table.VisitTable @Database( - entities = [SearchDocumentTable::class, RemoteKeyTable::class, SearchHistoryTable::class], + entities = [ + SearchDocumentTable::class, + RemoteKeyTable::class, + SearchHistoryTable::class, + VisitTable::class + ], version = 1, exportSchema = false ) @@ -43,6 +50,8 @@ internal abstract class AppDatabase : RoomDatabase() { abstract fun searchHistoryDao(): SearchHistoryDao + abstract fun visitDao(): VisitDao + companion object { private const val NAME = "app_database" diff --git a/data/src/main/kotlin/io/github/beomjo/search/datasource/local/dao/VisitDao.kt b/data/src/main/kotlin/io/github/beomjo/search/datasource/local/dao/VisitDao.kt new file mode 100644 index 0000000..9a027e4 --- /dev/null +++ b/data/src/main/kotlin/io/github/beomjo/search/datasource/local/dao/VisitDao.kt @@ -0,0 +1,18 @@ +package io.github.beomjo.search.datasource.local.dao + +import androidx.room.Dao +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Query +import io.github.beomjo.search.datasource.local.table.VisitTable +import io.github.beomjo.search.entity.Visit +import kotlinx.coroutines.flow.Flow + +@Dao +internal interface VisitDao { + @Insert(onConflict = OnConflictStrategy.REPLACE) + suspend fun insertVisit(visit: VisitTable) + + @Query("SELECT * FROM visit WHERE url == :url") + fun getVisit(url: String): Flow +} \ No newline at end of file diff --git a/data/src/main/kotlin/io/github/beomjo/search/datasource/local/table/VisitTable.kt b/data/src/main/kotlin/io/github/beomjo/search/datasource/local/table/VisitTable.kt new file mode 100644 index 0000000..96eb194 --- /dev/null +++ b/data/src/main/kotlin/io/github/beomjo/search/datasource/local/table/VisitTable.kt @@ -0,0 +1,15 @@ +package io.github.beomjo.search.datasource.local.table + +import androidx.room.Entity +import androidx.room.PrimaryKey +import com.google.gson.annotations.SerializedName +import java.util.* + +@Entity(tableName = "visit") +internal data class VisitTable( + @PrimaryKey + @field:SerializedName("url") + val url: String, + @field:SerializedName("date") + val date: Date?, +) diff --git a/data/src/main/kotlin/io/github/beomjo/search/mapper/VisitMapper.kt b/data/src/main/kotlin/io/github/beomjo/search/mapper/VisitMapper.kt new file mode 100644 index 0000000..b53653f --- /dev/null +++ b/data/src/main/kotlin/io/github/beomjo/search/mapper/VisitMapper.kt @@ -0,0 +1,18 @@ +package io.github.beomjo.search.mapper + +import io.github.beomjo.search.datasource.local.table.VisitTable +import io.github.beomjo.search.entity.Visit + +internal fun VisitTable.toEntity(): Visit { + return Visit( + url = url, + date = date, + ) +} + +internal fun Visit.toTable(): VisitTable { + return VisitTable( + url = url, + date = date, + ) +} diff --git a/data/src/main/kotlin/io/github/beomjo/search/repository/SearchRepositoryImpl.kt b/data/src/main/kotlin/io/github/beomjo/search/repository/SearchRepositoryImpl.kt index f3fbef4..120b452 100644 --- a/data/src/main/kotlin/io/github/beomjo/search/repository/SearchRepositoryImpl.kt +++ b/data/src/main/kotlin/io/github/beomjo/search/repository/SearchRepositoryImpl.kt @@ -23,6 +23,7 @@ import androidx.paging.Pager import androidx.paging.PagingConfig import io.github.beomjo.search.datasource.local.dao.SearchDocumentDao import io.github.beomjo.search.datasource.local.dao.SearchHistoryDao +import io.github.beomjo.search.datasource.local.dao.VisitDao import io.github.beomjo.search.datasource.remote.api.paging.SearchRemoteMediator import io.github.beomjo.search.datasource.remote.api.paging.SearchRemoteMediatorFactory import io.github.beomjo.search.entity.SearchDocument @@ -33,7 +34,6 @@ import io.github.beomjo.search.mapper.toEntity import io.github.beomjo.search.mapper.toTable import io.github.beomjo.search.usecase.SearchPagingParam import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map import javax.inject.Inject import javax.inject.Singleton @@ -42,7 +42,8 @@ import javax.inject.Singleton internal class SearchRepositoryImpl @Inject constructor( private val searchRemoteMediatorFactory: SearchRemoteMediatorFactory, private val documentDao: SearchDocumentDao, - private val searchHistoryDao: SearchHistoryDao + private val searchHistoryDao: SearchHistoryDao, + private val visitDao: VisitDao ) : SearchRepository { override fun getDocumentPagingData(param: SearchPagingParam): Flow> { @OptIn(ExperimentalPagingApi::class) @@ -75,10 +76,11 @@ internal class SearchRepositoryImpl @Inject constructor( } } - override suspend fun setVisit(visit: Visit) { + override suspend fun insertVisit(visit: Visit) { + visitDao.insertVisit(visit = visit.toTable()) } override fun getVisit(url: String): Flow { - return flowOf() + return visitDao.getVisit(url).map { it.toEntity() } } } diff --git a/data/src/test/java/io/github/beomjo/search/repository/SearchRepositoryImplSpec.kt b/data/src/test/java/io/github/beomjo/search/repository/SearchRepositoryImplSpec.kt index 13a5f03..8e87b08 100644 --- a/data/src/test/java/io/github/beomjo/search/repository/SearchRepositoryImplSpec.kt +++ b/data/src/test/java/io/github/beomjo/search/repository/SearchRepositoryImplSpec.kt @@ -21,8 +21,10 @@ import androidx.paging.PagingData import androidx.paging.PagingSource import io.github.beomjo.search.datasource.local.dao.SearchDocumentDao import io.github.beomjo.search.datasource.local.dao.SearchHistoryDao +import io.github.beomjo.search.datasource.local.dao.VisitDao import io.github.beomjo.search.datasource.local.table.SearchDocumentTable import io.github.beomjo.search.datasource.local.table.SearchHistoryTable +import io.github.beomjo.search.datasource.local.table.VisitTable import io.github.beomjo.search.datasource.remote.api.paging.SearchRemoteMediator import io.github.beomjo.search.datasource.remote.api.paging.SearchRemoteMediatorFactory import io.github.beomjo.search.entity.* @@ -49,9 +51,11 @@ internal class SearchRepositoryImplSpec : BehaviorSpec() { private val searchHistoryDao = mockk(relaxed = true) + private val visitDao = mockk(relaxed = true) + init { - Given("Given the SortType.TITLE") { + Given("Give a SortType.TITLE") { val param = SearchPagingParam( documentType = DocumentType.ALL, sortType = SortType.TITLE, @@ -66,7 +70,8 @@ internal class SearchRepositoryImplSpec : BehaviorSpec() { val searchRepositoryImpl = SearchRepositoryImpl( searchRemoteMediatorFactory, documentDao, - searchHistoryDao + searchHistoryDao, + visitDao ) When("invoke fetchPagingData") { @@ -81,7 +86,7 @@ internal class SearchRepositoryImplSpec : BehaviorSpec() { } } - Given("Given the SortType.DATE") { + Given("Give a SortType.DATE") { val param = SearchPagingParam( documentType = DocumentType.ALL, sortType = SortType.DATE, @@ -96,7 +101,8 @@ internal class SearchRepositoryImplSpec : BehaviorSpec() { val searchRepositoryImpl = SearchRepositoryImpl( searchRemoteMediatorFactory, documentDao, - searchHistoryDao + searchHistoryDao, + visitDao ) When("invoke fetchPagingData") { @@ -111,7 +117,7 @@ internal class SearchRepositoryImplSpec : BehaviorSpec() { } } - Given("Given the search query keyword") { + Given("Give a search query keyword") { val history = History( "IU", mockk(), @@ -120,14 +126,15 @@ internal class SearchRepositoryImplSpec : BehaviorSpec() { val searchRepositoryImpl = SearchRepositoryImpl( searchRemoteMediatorFactory, documentDao, - searchHistoryDao + searchHistoryDao, + visitDao ) When("When you call insert history to DB") { searchRepositoryImpl.insertSearchHistory(history) Then("Should be stored in DB") { - coVerify(inverse = false) { searchHistoryDao.insertHistory(eq(history.toTable())) } + coVerify { searchHistoryDao.insertHistory(eq(history.toTable())) } } } } @@ -145,19 +152,69 @@ internal class SearchRepositoryImplSpec : BehaviorSpec() { val searchRepositoryImpl = SearchRepositoryImpl( searchRemoteMediatorFactory, documentDao, - searchHistoryDao + searchHistoryDao, + visitDao ) - When("When you call insert history to DB") { + When("get historyList from DB") { val result = searchRepositoryImpl.getSearchHistoryList() - Then("Should be stored in DB") { + Then("Should bring on history from DB") { verify { searchHistoryDao.getHistoryList() } result.first() shouldBe searchTableList.map { it.toEntity() } } } } + Given("Give a Visit") { + val visit = Visit( + url = "http://", + date = mockk() + ) + + val searchRepositoryImpl = SearchRepositoryImpl( + searchRemoteMediatorFactory, + documentDao, + searchHistoryDao, + visitDao + ) + + When("insert visit to DB") { + searchRepositoryImpl.insertVisit(visit) + + Then("Should be stored in DB") { + coVerify { visitDao.insertVisit(eq(visit.toTable())) } + } + } + } + + Given("Give a url") { + val expectUrl = "http://" + + val visitTable = mockk { + every { url } returns expectUrl + every { date } returns mockk() + } + + every { visitDao.getVisit(expectUrl) } returns flowOf(visitTable) + + val searchRepositoryImpl = SearchRepositoryImpl( + searchRemoteMediatorFactory, + documentDao, + searchHistoryDao, + visitDao + ) + + When("get visit from DB") { + val result = searchRepositoryImpl.getVisit(expectUrl) + + Then("Should bring on visit from DB") { + verify { visitDao.getVisit(eq(expectUrl)) } + result.first() shouldBe visitTable.toEntity() + } + } + } + afterTest { unmockkAll() } diff --git a/domain/src/main/kotlin/io/github/beomjo/search/repository/SearchRepository.kt b/domain/src/main/kotlin/io/github/beomjo/search/repository/SearchRepository.kt index 7ac3b59..c90ae4a 100644 --- a/domain/src/main/kotlin/io/github/beomjo/search/repository/SearchRepository.kt +++ b/domain/src/main/kotlin/io/github/beomjo/search/repository/SearchRepository.kt @@ -31,7 +31,7 @@ interface SearchRepository { fun getSearchHistoryList(): Flow> - suspend fun setVisit(visit: Visit) + suspend fun insertVisit(visit: Visit) fun getVisit(url:String) :Flow } diff --git a/domain/src/main/kotlin/io/github/beomjo/search/usecase/SetSearchItemVisit.kt b/domain/src/main/kotlin/io/github/beomjo/search/usecase/SetSearchItemVisit.kt index 2890d11..49a18cf 100644 --- a/domain/src/main/kotlin/io/github/beomjo/search/usecase/SetSearchItemVisit.kt +++ b/domain/src/main/kotlin/io/github/beomjo/search/usecase/SetSearchItemVisit.kt @@ -10,6 +10,6 @@ class SetSearchItemVisit @Inject constructor( private val searchRepository: SearchRepository ) : UseCase() { override suspend fun execute(url: String) { - searchRepository.setVisit(Visit(Date(), url)) + searchRepository.insertVisit(Visit(Date(), url)) } } \ No newline at end of file diff --git a/domain/src/test/java/io/github/beomjo/search/usecase/SetSearchItemVisitSpec.kt b/domain/src/test/java/io/github/beomjo/search/usecase/SetSearchItemVisitSpec.kt index 716f042..d20c43f 100644 --- a/domain/src/test/java/io/github/beomjo/search/usecase/SetSearchItemVisitSpec.kt +++ b/domain/src/test/java/io/github/beomjo/search/usecase/SetSearchItemVisitSpec.kt @@ -15,13 +15,13 @@ class SetSearchItemVisitSpec : BehaviorSpec() { val url = "http://..." val useCase = SetSearchItemVisit(searchRepository) val slot = slot() - coEvery { searchRepository.setVisit(capture(slot)) } just Runs + coEvery { searchRepository.insertVisit(capture(slot)) } just Runs When("Invoke") { useCase.invoke(url) Then("Should call setVisit of SearchRepository") { - coEvery { searchRepository.setVisit(any()) } + coEvery { searchRepository.insertVisit(any()) } slot.captured.url shouldBe url } } From f71a3db982a0cc15370bf2bdd847f78b6cf707a2 Mon Sep 17 00:00:00 2001 From: beomjo Date: Sat, 11 Sep 2021 02:25:24 +0900 Subject: [PATCH 239/273] feat: Implement Detail Acitivty --- .../search/ui/activity/DetailActivity.kt | 19 +++++++++-- .../search/ui/viewmodels/DetailViewModel.kt | 34 +++++++++++++++++++ app/src/main/res/layout/activity_detail.xml | 18 +++++----- 3 files changed, 59 insertions(+), 12 deletions(-) create mode 100644 app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/DetailViewModel.kt diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/activity/DetailActivity.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/activity/DetailActivity.kt index e6f3657..7bed0c4 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/activity/DetailActivity.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/activity/DetailActivity.kt @@ -25,10 +25,13 @@ import io.github.beomjo.search.R import io.github.beomjo.search.base.BaseActivity import io.github.beomjo.search.databinding.ActivityDetailBinding import io.github.beomjo.search.entity.SearchDocument +import io.github.beomjo.search.ui.viewmodels.DetailViewModel @AndroidEntryPoint class DetailActivity : BaseActivity(R.layout.activity_detail) { + private val detailViewModel: DetailViewModel by getViewModel() + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) bindLayout() @@ -37,13 +40,23 @@ class DetailActivity : BaseActivity(R.layout.activity_det private fun bindLayout() { binding { lifecycleOwner = this@DetailActivity - val documentData = intent.getParcelableExtra(KEY_DOCUMENT) - document = documentData + detailViewModel = this@DetailActivity.detailViewModel.apply { + init(intent.getParcelableExtra(KEY_DOCUMENT)) + } toolBar.setNavigationOnClickListener { onBackPressed() } moveWebviewBtn.setOnClickListener { - startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(documentData?.url))) + this@DetailActivity.detailViewModel.run { + setVisit() + startActivity( + Intent( + Intent.ACTION_VIEW, + Uri.parse(searchDocument.value?.url) + ) + ) + } + } favoriteBtn.setOnClickListener { favoriteBtn.isSelected = !favoriteBtn.isSelected diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/DetailViewModel.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/DetailViewModel.kt new file mode 100644 index 0000000..19a74e7 --- /dev/null +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/DetailViewModel.kt @@ -0,0 +1,34 @@ +package io.github.beomjo.search.ui.viewmodels + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.viewModelScope +import dagger.hilt.android.lifecycle.HiltViewModel +import io.github.beomjo.search.base.BaseViewModel +import io.github.beomjo.search.entity.SearchDocument +import io.github.beomjo.search.usecase.SetSearchItemVisit +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +class DetailViewModel @Inject constructor( + private val setSearchItemVisit: SetSearchItemVisit +) : BaseViewModel() { + + private val _searchDocument = MutableLiveData() + val searchDocument: LiveData = _searchDocument + + fun init(searchDocument: SearchDocument?) { + searchDocument?.let { + _searchDocument.value = it + } ?: kotlin.run { + // TODO DO Back Activity + } + } + + fun setVisit() { + viewModelScope.launch { + setSearchItemVisit(searchDocument.value?.url ?: "") + } + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_detail.xml b/app/src/main/res/layout/activity_detail.xml index e4fc0d6..7165e0c 100644 --- a/app/src/main/res/layout/activity_detail.xml +++ b/app/src/main/res/layout/activity_detail.xml @@ -20,8 +20,8 @@ + name="detailViewModel" + type="io.github.beomjo.search.ui.viewmodels.DetailViewModel" /> @@ -44,7 +44,7 @@ android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:navigationIcon="@drawable/ic_arrow_back" - app:title="@{document.type.name()}" /> + app:title="@{detailViewModel.searchDocument.type.name()}" /> @@ -70,7 +70,7 @@ android:adjustViewBounds="true" android:contentDescription="@android:string/untitled" android:scaleType="fitCenter" - app:imageUrl="@{document.thumbnail}" + app:imageUrl="@{detailViewModel.searchDocument.thumbnail}" app:layout_constraintDimensionRatio="1:1" app:layout_constraintEnd_toEndOf="@id/guide_end" app:layout_constraintStart_toStartOf="@id/guide_start" @@ -84,7 +84,7 @@ android:layout_marginTop="10dp" android:ellipsize="end" android:maxLines="1" - android:text="@{document.type.toString()}" + android:text="@{detailViewModel.searchDocument.type.toString()}" android:textAppearance="?attr/textAppearanceListItem" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="@id/guide_start" @@ -99,7 +99,7 @@ android:ellipsize="end" android:maxLines="2" android:textAppearance="?attr/textAppearanceListItem" - app:html="@{document.title}" + app:html="@{detailViewModel.searchDocument.title}" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="@id/guide_start" app:layout_constraintTop_toBottomOf="@id/name" @@ -111,7 +111,7 @@ android:layout_height="wrap_content" android:layout_marginTop="10dp" android:textAppearance="?attr/textAppearanceListItem" - app:html="@{document.content}" + app:html="@{detailViewModel.searchDocument.content}" app:layout_constraintEnd_toEndOf="@id/guide_end" app:layout_constraintStart_toStartOf="@id/guide_start" app:layout_constraintTop_toBottomOf="@id/title" @@ -123,7 +123,7 @@ android:layout_height="wrap_content" android:layout_marginTop="10dp" android:textAppearance="?attr/textAppearanceListItem" - app:date="@{document.date}" + app:date="@{detailViewModel.searchDocument.date}" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="@id/guide_start" app:layout_constraintTop_toBottomOf="@id/content" @@ -136,7 +136,7 @@ android:layout_marginTop="10dp" android:ellipsize="end" android:maxLines="1" - android:text="@{document.url}" + android:text="@{detailViewModel.searchDocument.url}" android:textAppearance="?attr/textAppearanceListItem" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="@id/guide_start" From 30a94b4505a050d65441ebf50c4b064742f998f7 Mon Sep 17 00:00:00 2001 From: beomjo Date: Sat, 11 Sep 2021 02:25:38 +0900 Subject: [PATCH 240/273] chore: Add dim background color --- app/src/main/res/values/colors.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 19b7e94..a3d6e42 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -19,6 +19,7 @@ #FFA505 #4F4E28 #925F17 + #C0C0C0 #FF000000 #FFFFFFFF \ No newline at end of file From 7b853119336d901cc6660927ebc2b6c278522f58 Mon Sep 17 00:00:00 2001 From: beomjo Date: Sun, 12 Sep 2021 00:06:47 +0900 Subject: [PATCH 241/273] feat: feat: Change the GetVisit Flow return value to nullable --- .../github/beomjo/search/datasource/local/dao/VisitDao.kt | 2 +- .../beomjo/search/repository/SearchRepositoryImpl.kt | 7 +++---- .../io/github/beomjo/search/repository/SearchRepository.kt | 2 +- .../io/github/beomjo/search/usecase/GetSearchItemVisit.kt | 4 ++-- .../io/github/beomjo/search/usecase/base/FlowUseCase.kt | 2 +- 5 files changed, 8 insertions(+), 9 deletions(-) diff --git a/data/src/main/kotlin/io/github/beomjo/search/datasource/local/dao/VisitDao.kt b/data/src/main/kotlin/io/github/beomjo/search/datasource/local/dao/VisitDao.kt index 9a027e4..352f845 100644 --- a/data/src/main/kotlin/io/github/beomjo/search/datasource/local/dao/VisitDao.kt +++ b/data/src/main/kotlin/io/github/beomjo/search/datasource/local/dao/VisitDao.kt @@ -14,5 +14,5 @@ internal interface VisitDao { suspend fun insertVisit(visit: VisitTable) @Query("SELECT * FROM visit WHERE url == :url") - fun getVisit(url: String): Flow + fun getVisit(url: String): Flow } \ No newline at end of file diff --git a/data/src/main/kotlin/io/github/beomjo/search/repository/SearchRepositoryImpl.kt b/data/src/main/kotlin/io/github/beomjo/search/repository/SearchRepositoryImpl.kt index 120b452..7410d0a 100644 --- a/data/src/main/kotlin/io/github/beomjo/search/repository/SearchRepositoryImpl.kt +++ b/data/src/main/kotlin/io/github/beomjo/search/repository/SearchRepositoryImpl.kt @@ -50,8 +50,7 @@ internal class SearchRepositoryImpl @Inject constructor( return Pager( config = PagingConfig( pageSize = SearchRemoteMediator.PER_PAGE_SIZE, - prefetchDistance = 3 - + enablePlaceholders = false ), remoteMediator = searchRemoteMediatorFactory.create(param) ) { @@ -80,7 +79,7 @@ internal class SearchRepositoryImpl @Inject constructor( visitDao.insertVisit(visit = visit.toTable()) } - override fun getVisit(url: String): Flow { - return visitDao.getVisit(url).map { it.toEntity() } + override fun getVisit(url: String): Flow { + return visitDao.getVisit(url).map { it?.toEntity() } } } diff --git a/domain/src/main/kotlin/io/github/beomjo/search/repository/SearchRepository.kt b/domain/src/main/kotlin/io/github/beomjo/search/repository/SearchRepository.kt index c90ae4a..46f5b97 100644 --- a/domain/src/main/kotlin/io/github/beomjo/search/repository/SearchRepository.kt +++ b/domain/src/main/kotlin/io/github/beomjo/search/repository/SearchRepository.kt @@ -33,5 +33,5 @@ interface SearchRepository { suspend fun insertVisit(visit: Visit) - fun getVisit(url:String) :Flow + fun getVisit(url:String) :Flow } diff --git a/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetSearchItemVisit.kt b/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetSearchItemVisit.kt index b71a976..5016518 100644 --- a/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetSearchItemVisit.kt +++ b/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetSearchItemVisit.kt @@ -8,8 +8,8 @@ import javax.inject.Inject class GetSearchItemVisit @Inject constructor( private val searchRepository: SearchRepository -) : FlowUseCase() { - override fun execute(parameters: String): Flow { +) : FlowUseCase() { + override fun execute(parameters: String): Flow { return searchRepository.getVisit(parameters) } } \ No newline at end of file diff --git a/domain/src/main/kotlin/io/github/beomjo/search/usecase/base/FlowUseCase.kt b/domain/src/main/kotlin/io/github/beomjo/search/usecase/base/FlowUseCase.kt index 2d13d74..92687ba 100644 --- a/domain/src/main/kotlin/io/github/beomjo/search/usecase/base/FlowUseCase.kt +++ b/domain/src/main/kotlin/io/github/beomjo/search/usecase/base/FlowUseCase.kt @@ -18,7 +18,7 @@ package io.github.beomjo.search.usecase.base import kotlinx.coroutines.flow.Flow -abstract class FlowUseCase { +abstract class FlowUseCase { operator fun invoke(parameters: P): Flow { return execute(parameters) From 0ade6886490c74b4bd7a9ddac569caf74a9cc440 Mon Sep 17 00:00:00 2001 From: beomjo Date: Sun, 12 Sep 2021 00:07:39 +0900 Subject: [PATCH 242/273] feat: Add dim effect when moving to detail screen with Search Document Item web view --- .../search/ui/adapter/SearchPagingAdapter.kt | 23 ++++++++++-- .../viewholders/SearchDocumentViewHolder.kt | 15 +++++--- .../search/ui/fragment/SearchFragment.kt | 12 ++++--- .../ui/viewmodels/SearchDocumentViewModel.kt | 36 +++++++++++++++++++ .../res/layout/search_list_document_item.xml | 15 ++++---- 5 files changed, 82 insertions(+), 19 deletions(-) create mode 100644 app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/SearchDocumentViewModel.kt diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/SearchPagingAdapter.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/SearchPagingAdapter.kt index a4df28e..36708d2 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/SearchPagingAdapter.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/SearchPagingAdapter.kt @@ -17,17 +17,25 @@ package io.github.beomjo.search.ui.adapter import android.view.ViewGroup +import androidx.lifecycle.LifecycleOwner import androidx.paging.PagingDataAdapter import androidx.recyclerview.widget.RecyclerView +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject import io.github.beomjo.search.R import io.github.beomjo.search.entity.SearchDocument import io.github.beomjo.search.ui.adapter.diff.DocumentDiffUtil import io.github.beomjo.search.ui.adapter.viewholders.SearchDocumentViewHolder import io.github.beomjo.search.ui.adapter.viewholders.SearchSeparatorViewHolder +import io.github.beomjo.search.ui.viewmodels.SearchDocumentViewModelFactory import io.github.beomjo.search.ui.viewmodels.SearchViewModel.SearchUiItem +import javax.inject.Provider -class SearchPagingAdapter( - private val onClickItem: (SearchDocument) -> Unit +class SearchPagingAdapter @AssistedInject constructor( + @Assisted private val lifeCycleOwner: LifecycleOwner, + @Assisted private val onClickItem: (SearchDocument) -> Unit, + private val searchDocumentViewModelProvider: Provider ) : PagingDataAdapter(DocumentDiffUtil()) { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { @@ -48,7 +56,8 @@ class SearchPagingAdapter( getItem(position)?.let { when (it) { is SearchUiItem.DocumentItem -> (holder as SearchDocumentViewHolder).bind( - it.searchDocument, + lifeCycleOwner, + searchDocumentViewModelProvider.get().create(it.searchDocument), onClickItem ) is SearchUiItem.SeparatorItem -> (holder as SearchSeparatorViewHolder).bind(it.description) @@ -56,3 +65,11 @@ class SearchPagingAdapter( } } } + +@AssistedFactory +interface SearchPagingAdapterFactory { + fun create( + lifeCycleOwner: LifecycleOwner, + onClickItem: (SearchDocument) -> Unit + ): SearchPagingAdapter +} \ No newline at end of file diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/viewholders/SearchDocumentViewHolder.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/viewholders/SearchDocumentViewHolder.kt index c617247..92c3035 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/viewholders/SearchDocumentViewHolder.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/viewholders/SearchDocumentViewHolder.kt @@ -18,18 +18,25 @@ package io.github.beomjo.search.ui.adapter.viewholders import android.view.LayoutInflater import android.view.ViewGroup +import androidx.lifecycle.LifecycleOwner import androidx.recyclerview.widget.RecyclerView import io.github.beomjo.search.databinding.SearchListDocumentItemBinding import io.github.beomjo.search.entity.SearchDocument +import io.github.beomjo.search.ui.viewmodels.SearchDocumentViewModel class SearchDocumentViewHolder( private val binding: SearchListDocumentItemBinding, ) : RecyclerView.ViewHolder(binding.root) { - fun bind(searchDocument: SearchDocument, onClickItem: (SearchDocument) -> Unit) { - binding.apply { - this.document = searchDocument - documentContainer.setOnClickListener { onClickItem(searchDocument) } + fun bind( + lifecycleOwner: LifecycleOwner, + searchDocumentViewModel: SearchDocumentViewModel, + onClickItem: (SearchDocument) -> Unit + ) { + binding.run { + this.lifecycleOwner = lifecycleOwner + viewModel = searchDocumentViewModel + documentContainer.setOnClickListener { onClickItem(searchDocumentViewModel.searchDocument) } executePendingBindings() } } diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/fragment/SearchFragment.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/fragment/SearchFragment.kt index 8bedc49..a132dce 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/fragment/SearchFragment.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/fragment/SearchFragment.kt @@ -30,21 +30,22 @@ import io.github.beomjo.search.R import io.github.beomjo.search.base.BaseFragment import io.github.beomjo.search.databinding.FragmentSearchBinding import io.github.beomjo.search.ui.activity.DetailActivity -import io.github.beomjo.search.ui.adapter.SearchControlMenuAdapter -import io.github.beomjo.search.ui.adapter.SearchHistoryAdapter -import io.github.beomjo.search.ui.adapter.SearchPagingAdapter -import io.github.beomjo.search.ui.adapter.SearchPagingLoadStateAdapter +import io.github.beomjo.search.ui.adapter.* import io.github.beomjo.search.ui.viewmodels.SearchViewModel import kotlinx.coroutines.launch import java.util.* +import javax.inject.Inject @AndroidEntryPoint class SearchFragment : BaseFragment(R.layout.fragment_search) { private val searchViewModel: SearchViewModel by getViewModel() + @Inject + lateinit var searchPagingAdapterFactory: SearchPagingAdapterFactory + private val searchPagingAdapter: SearchPagingAdapter by lazy { - SearchPagingAdapter { document -> + searchPagingAdapterFactory.create(this) { document -> DetailActivity.action(this@SearchFragment.requireActivity(), document) } } @@ -53,6 +54,7 @@ class SearchFragment : BaseFragment(R.layout.fragment_sea SearchHistoryAdapter { searchViewModel.query.value = it searchViewModel.search() + defaultViewModelProviderFactory } } diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/SearchDocumentViewModel.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/SearchDocumentViewModel.kt new file mode 100644 index 0000000..6498194 --- /dev/null +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/SearchDocumentViewModel.kt @@ -0,0 +1,36 @@ +package io.github.beomjo.search.ui.viewmodels + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.asLiveData +import androidx.lifecycle.map +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject +import io.github.beomjo.search.entity.SearchDocument +import io.github.beomjo.search.entity.Visit +import io.github.beomjo.search.usecase.GetSearchItemVisit +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.InternalCoroutinesApi +import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.flowOn +import kotlinx.coroutines.launch + +class SearchDocumentViewModel @AssistedInject constructor( + @Assisted val searchDocument: SearchDocument, + getSearchItemVisit: GetSearchItemVisit +) { + val isVisit: LiveData = getSearchItemVisit(searchDocument.url) + .distinctUntilChanged() + .flowOn(Dispatchers.Main) + .asLiveData() + .map { it?.url != null } +} + +@AssistedFactory +interface SearchDocumentViewModelFactory { + fun create(searchDocument: SearchDocument): SearchDocumentViewModel +} + diff --git a/app/src/main/res/layout/search_list_document_item.xml b/app/src/main/res/layout/search_list_document_item.xml index 9c2cc70..a0cfc29 100644 --- a/app/src/main/res/layout/search_list_document_item.xml +++ b/app/src/main/res/layout/search_list_document_item.xml @@ -20,8 +20,8 @@ + name="viewModel" + type="io.github.beomjo.search.ui.viewmodels.SearchDocumentViewModel" /> Date: Sun, 12 Sep 2021 00:16:07 +0900 Subject: [PATCH 243/273] chore: Naming correction --- .../search/ui/viewmodels/DetailViewModel.kt | 6 ++--- ...odel.kt => SearchDocumentItemViewModel.kt} | 12 +++------- .../io/github/beomjo/search/DataModule.kt | 6 ++--- .../search/datasource/local/AppDatabase.kt | 4 ++-- ...{VisitDao.kt => SearchDocumentVisitDao.kt} | 2 +- ...Mapper.kt => SearchDocumentVisitMapper.kt} | 0 .../search/repository/SearchRepositoryImpl.kt | 8 +++---- .../repository/SearchRepositoryImplSpec.kt | 22 +++++++++---------- ...ItemVisit.kt => GetSearchDocumentVisit.kt} | 2 +- ...ItemVisit.kt => SetSearchDocumentVisit.kt} | 6 ++--- ...tSpec.kt => GetSearchDocumentVisitSpec.kt} | 6 ++--- ...tSpec.kt => SetSearchDocumentVisitSpec.kt} | 4 ++-- 12 files changed, 36 insertions(+), 42 deletions(-) rename app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/{SearchDocumentViewModel.kt => SearchDocumentItemViewModel.kt} (65%) rename data/src/main/kotlin/io/github/beomjo/search/datasource/local/dao/{VisitDao.kt => SearchDocumentVisitDao.kt} (92%) rename data/src/main/kotlin/io/github/beomjo/search/mapper/{VisitMapper.kt => SearchDocumentVisitMapper.kt} (100%) rename domain/src/main/kotlin/io/github/beomjo/search/usecase/{GetSearchItemVisit.kt => GetSearchDocumentVisit.kt} (90%) rename domain/src/main/kotlin/io/github/beomjo/search/usecase/{SetSearchItemVisit.kt => SetSearchDocumentVisit.kt} (66%) rename domain/src/test/java/io/github/beomjo/search/usecase/{GetSearchItemVisitSpec.kt => GetSearchDocumentVisitSpec.kt} (84%) rename domain/src/test/java/io/github/beomjo/search/usecase/{SetSearchItemVisitSpec.kt => SetSearchDocumentVisitSpec.kt} (87%) diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/DetailViewModel.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/DetailViewModel.kt index 19a74e7..f4e3f09 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/DetailViewModel.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/DetailViewModel.kt @@ -6,13 +6,13 @@ import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import io.github.beomjo.search.base.BaseViewModel import io.github.beomjo.search.entity.SearchDocument -import io.github.beomjo.search.usecase.SetSearchItemVisit +import io.github.beomjo.search.usecase.SetSearchDocumentVisit import kotlinx.coroutines.launch import javax.inject.Inject @HiltViewModel class DetailViewModel @Inject constructor( - private val setSearchItemVisit: SetSearchItemVisit + private val setSearchDocumentVisit: SetSearchDocumentVisit ) : BaseViewModel() { private val _searchDocument = MutableLiveData() @@ -28,7 +28,7 @@ class DetailViewModel @Inject constructor( fun setVisit() { viewModelScope.launch { - setSearchItemVisit(searchDocument.value?.url ?: "") + setSearchDocumentVisit(searchDocument.value?.url ?: "") } } } \ No newline at end of file diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/SearchDocumentViewModel.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/SearchDocumentItemViewModel.kt similarity index 65% rename from app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/SearchDocumentViewModel.kt rename to app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/SearchDocumentItemViewModel.kt index 6498194..287cc1c 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/SearchDocumentViewModel.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/SearchDocumentItemViewModel.kt @@ -1,28 +1,22 @@ package io.github.beomjo.search.ui.viewmodels import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData import androidx.lifecycle.asLiveData import androidx.lifecycle.map import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject import io.github.beomjo.search.entity.SearchDocument -import io.github.beomjo.search.entity.Visit -import io.github.beomjo.search.usecase.GetSearchItemVisit -import kotlinx.coroutines.CoroutineScope +import io.github.beomjo.search.usecase.GetSearchDocumentVisit import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.InternalCoroutinesApi -import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flowOn -import kotlinx.coroutines.launch class SearchDocumentViewModel @AssistedInject constructor( @Assisted val searchDocument: SearchDocument, - getSearchItemVisit: GetSearchItemVisit + getSearchDocumentItemVisit: GetSearchDocumentVisit ) { - val isVisit: LiveData = getSearchItemVisit(searchDocument.url) + val isVisit: LiveData = getSearchDocumentItemVisit(searchDocument.url) .distinctUntilChanged() .flowOn(Dispatchers.Main) .asLiveData() diff --git a/data/src/main/kotlin/io/github/beomjo/search/DataModule.kt b/data/src/main/kotlin/io/github/beomjo/search/DataModule.kt index c78a2cc..d90b2a6 100644 --- a/data/src/main/kotlin/io/github/beomjo/search/DataModule.kt +++ b/data/src/main/kotlin/io/github/beomjo/search/DataModule.kt @@ -27,7 +27,7 @@ import io.github.beomjo.search.datasource.local.AppDatabase import io.github.beomjo.search.datasource.local.dao.SearchDocumentDao import io.github.beomjo.search.datasource.local.dao.RemoteKeyDao import io.github.beomjo.search.datasource.local.dao.SearchHistoryDao -import io.github.beomjo.search.datasource.local.dao.VisitDao +import io.github.beomjo.search.datasource.local.dao.SearchDocumentVisitDao import io.github.beomjo.search.datasource.remote.api.RetrofitAdapter import io.github.beomjo.search.datasource.remote.api.Urls import io.github.beomjo.search.datasource.remote.api.service.DocumentsApi @@ -74,8 +74,8 @@ internal object DataModule { @Singleton @Provides - fun provideVisitDao(database: AppDatabase): VisitDao { - return database.visitDao() + fun provideVisitDao(database: AppDatabase): SearchDocumentVisitDao { + return database.searchDocumentVisitDao() } @Module diff --git a/data/src/main/kotlin/io/github/beomjo/search/datasource/local/AppDatabase.kt b/data/src/main/kotlin/io/github/beomjo/search/datasource/local/AppDatabase.kt index 5423bfc..0998fd5 100644 --- a/data/src/main/kotlin/io/github/beomjo/search/datasource/local/AppDatabase.kt +++ b/data/src/main/kotlin/io/github/beomjo/search/datasource/local/AppDatabase.kt @@ -25,7 +25,7 @@ import io.github.beomjo.search.datasource.local.converter.DateConverter import io.github.beomjo.search.datasource.local.dao.SearchDocumentDao import io.github.beomjo.search.datasource.local.dao.RemoteKeyDao import io.github.beomjo.search.datasource.local.dao.SearchHistoryDao -import io.github.beomjo.search.datasource.local.dao.VisitDao +import io.github.beomjo.search.datasource.local.dao.SearchDocumentVisitDao import io.github.beomjo.search.datasource.local.table.SearchDocumentTable import io.github.beomjo.search.datasource.local.table.RemoteKeyTable import io.github.beomjo.search.datasource.local.table.SearchHistoryTable @@ -50,7 +50,7 @@ internal abstract class AppDatabase : RoomDatabase() { abstract fun searchHistoryDao(): SearchHistoryDao - abstract fun visitDao(): VisitDao + abstract fun searchDocumentVisitDao(): SearchDocumentVisitDao companion object { diff --git a/data/src/main/kotlin/io/github/beomjo/search/datasource/local/dao/VisitDao.kt b/data/src/main/kotlin/io/github/beomjo/search/datasource/local/dao/SearchDocumentVisitDao.kt similarity index 92% rename from data/src/main/kotlin/io/github/beomjo/search/datasource/local/dao/VisitDao.kt rename to data/src/main/kotlin/io/github/beomjo/search/datasource/local/dao/SearchDocumentVisitDao.kt index 352f845..c7f3d38 100644 --- a/data/src/main/kotlin/io/github/beomjo/search/datasource/local/dao/VisitDao.kt +++ b/data/src/main/kotlin/io/github/beomjo/search/datasource/local/dao/SearchDocumentVisitDao.kt @@ -9,7 +9,7 @@ import io.github.beomjo.search.entity.Visit import kotlinx.coroutines.flow.Flow @Dao -internal interface VisitDao { +internal interface SearchDocumentVisitDao { @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insertVisit(visit: VisitTable) diff --git a/data/src/main/kotlin/io/github/beomjo/search/mapper/VisitMapper.kt b/data/src/main/kotlin/io/github/beomjo/search/mapper/SearchDocumentVisitMapper.kt similarity index 100% rename from data/src/main/kotlin/io/github/beomjo/search/mapper/VisitMapper.kt rename to data/src/main/kotlin/io/github/beomjo/search/mapper/SearchDocumentVisitMapper.kt diff --git a/data/src/main/kotlin/io/github/beomjo/search/repository/SearchRepositoryImpl.kt b/data/src/main/kotlin/io/github/beomjo/search/repository/SearchRepositoryImpl.kt index 7410d0a..a8836f0 100644 --- a/data/src/main/kotlin/io/github/beomjo/search/repository/SearchRepositoryImpl.kt +++ b/data/src/main/kotlin/io/github/beomjo/search/repository/SearchRepositoryImpl.kt @@ -23,7 +23,7 @@ import androidx.paging.Pager import androidx.paging.PagingConfig import io.github.beomjo.search.datasource.local.dao.SearchDocumentDao import io.github.beomjo.search.datasource.local.dao.SearchHistoryDao -import io.github.beomjo.search.datasource.local.dao.VisitDao +import io.github.beomjo.search.datasource.local.dao.SearchDocumentVisitDao import io.github.beomjo.search.datasource.remote.api.paging.SearchRemoteMediator import io.github.beomjo.search.datasource.remote.api.paging.SearchRemoteMediatorFactory import io.github.beomjo.search.entity.SearchDocument @@ -43,7 +43,7 @@ internal class SearchRepositoryImpl @Inject constructor( private val searchRemoteMediatorFactory: SearchRemoteMediatorFactory, private val documentDao: SearchDocumentDao, private val searchHistoryDao: SearchHistoryDao, - private val visitDao: VisitDao + private val searchDocumentVisitDao: SearchDocumentVisitDao ) : SearchRepository { override fun getDocumentPagingData(param: SearchPagingParam): Flow> { @OptIn(ExperimentalPagingApi::class) @@ -76,10 +76,10 @@ internal class SearchRepositoryImpl @Inject constructor( } override suspend fun insertVisit(visit: Visit) { - visitDao.insertVisit(visit = visit.toTable()) + searchDocumentVisitDao.insertVisit(visit = visit.toTable()) } override fun getVisit(url: String): Flow { - return visitDao.getVisit(url).map { it?.toEntity() } + return searchDocumentVisitDao.getVisit(url).map { it?.toEntity() } } } diff --git a/data/src/test/java/io/github/beomjo/search/repository/SearchRepositoryImplSpec.kt b/data/src/test/java/io/github/beomjo/search/repository/SearchRepositoryImplSpec.kt index 8e87b08..55437ce 100644 --- a/data/src/test/java/io/github/beomjo/search/repository/SearchRepositoryImplSpec.kt +++ b/data/src/test/java/io/github/beomjo/search/repository/SearchRepositoryImplSpec.kt @@ -21,7 +21,7 @@ import androidx.paging.PagingData import androidx.paging.PagingSource import io.github.beomjo.search.datasource.local.dao.SearchDocumentDao import io.github.beomjo.search.datasource.local.dao.SearchHistoryDao -import io.github.beomjo.search.datasource.local.dao.VisitDao +import io.github.beomjo.search.datasource.local.dao.SearchDocumentVisitDao import io.github.beomjo.search.datasource.local.table.SearchDocumentTable import io.github.beomjo.search.datasource.local.table.SearchHistoryTable import io.github.beomjo.search.datasource.local.table.VisitTable @@ -51,7 +51,7 @@ internal class SearchRepositoryImplSpec : BehaviorSpec() { private val searchHistoryDao = mockk(relaxed = true) - private val visitDao = mockk(relaxed = true) + private val searchDocumentVisitDao = mockk(relaxed = true) init { @@ -71,7 +71,7 @@ internal class SearchRepositoryImplSpec : BehaviorSpec() { searchRemoteMediatorFactory, documentDao, searchHistoryDao, - visitDao + searchDocumentVisitDao ) When("invoke fetchPagingData") { @@ -102,7 +102,7 @@ internal class SearchRepositoryImplSpec : BehaviorSpec() { searchRemoteMediatorFactory, documentDao, searchHistoryDao, - visitDao + searchDocumentVisitDao ) When("invoke fetchPagingData") { @@ -127,7 +127,7 @@ internal class SearchRepositoryImplSpec : BehaviorSpec() { searchRemoteMediatorFactory, documentDao, searchHistoryDao, - visitDao + searchDocumentVisitDao ) When("When you call insert history to DB") { @@ -153,7 +153,7 @@ internal class SearchRepositoryImplSpec : BehaviorSpec() { searchRemoteMediatorFactory, documentDao, searchHistoryDao, - visitDao + searchDocumentVisitDao ) When("get historyList from DB") { @@ -176,14 +176,14 @@ internal class SearchRepositoryImplSpec : BehaviorSpec() { searchRemoteMediatorFactory, documentDao, searchHistoryDao, - visitDao + searchDocumentVisitDao ) When("insert visit to DB") { searchRepositoryImpl.insertVisit(visit) Then("Should be stored in DB") { - coVerify { visitDao.insertVisit(eq(visit.toTable())) } + coVerify { searchDocumentVisitDao.insertVisit(eq(visit.toTable())) } } } } @@ -196,20 +196,20 @@ internal class SearchRepositoryImplSpec : BehaviorSpec() { every { date } returns mockk() } - every { visitDao.getVisit(expectUrl) } returns flowOf(visitTable) + every { searchDocumentVisitDao.getVisit(expectUrl) } returns flowOf(visitTable) val searchRepositoryImpl = SearchRepositoryImpl( searchRemoteMediatorFactory, documentDao, searchHistoryDao, - visitDao + searchDocumentVisitDao ) When("get visit from DB") { val result = searchRepositoryImpl.getVisit(expectUrl) Then("Should bring on visit from DB") { - verify { visitDao.getVisit(eq(expectUrl)) } + verify { searchDocumentVisitDao.getVisit(eq(expectUrl)) } result.first() shouldBe visitTable.toEntity() } } diff --git a/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetSearchItemVisit.kt b/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetSearchDocumentVisit.kt similarity index 90% rename from domain/src/main/kotlin/io/github/beomjo/search/usecase/GetSearchItemVisit.kt rename to domain/src/main/kotlin/io/github/beomjo/search/usecase/GetSearchDocumentVisit.kt index 5016518..7e4dea0 100644 --- a/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetSearchItemVisit.kt +++ b/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetSearchDocumentVisit.kt @@ -6,7 +6,7 @@ import io.github.beomjo.search.usecase.base.FlowUseCase import kotlinx.coroutines.flow.Flow import javax.inject.Inject -class GetSearchItemVisit @Inject constructor( +class GetSearchDocumentVisit @Inject constructor( private val searchRepository: SearchRepository ) : FlowUseCase() { override fun execute(parameters: String): Flow { diff --git a/domain/src/main/kotlin/io/github/beomjo/search/usecase/SetSearchItemVisit.kt b/domain/src/main/kotlin/io/github/beomjo/search/usecase/SetSearchDocumentVisit.kt similarity index 66% rename from domain/src/main/kotlin/io/github/beomjo/search/usecase/SetSearchItemVisit.kt rename to domain/src/main/kotlin/io/github/beomjo/search/usecase/SetSearchDocumentVisit.kt index 49a18cf..4f08abd 100644 --- a/domain/src/main/kotlin/io/github/beomjo/search/usecase/SetSearchItemVisit.kt +++ b/domain/src/main/kotlin/io/github/beomjo/search/usecase/SetSearchDocumentVisit.kt @@ -6,10 +6,10 @@ import io.github.beomjo.search.usecase.base.UseCase import java.util.* import javax.inject.Inject -class SetSearchItemVisit @Inject constructor( +class SetSearchDocumentVisit @Inject constructor( private val searchRepository: SearchRepository ) : UseCase() { - override suspend fun execute(url: String) { - searchRepository.insertVisit(Visit(Date(), url)) + override suspend fun execute(parameters: String) { + searchRepository.insertVisit(Visit(Date(), parameters)) } } \ No newline at end of file diff --git a/domain/src/test/java/io/github/beomjo/search/usecase/GetSearchItemVisitSpec.kt b/domain/src/test/java/io/github/beomjo/search/usecase/GetSearchDocumentVisitSpec.kt similarity index 84% rename from domain/src/test/java/io/github/beomjo/search/usecase/GetSearchItemVisitSpec.kt rename to domain/src/test/java/io/github/beomjo/search/usecase/GetSearchDocumentVisitSpec.kt index b451a54..3817373 100644 --- a/domain/src/test/java/io/github/beomjo/search/usecase/GetSearchItemVisitSpec.kt +++ b/domain/src/test/java/io/github/beomjo/search/usecase/GetSearchDocumentVisitSpec.kt @@ -8,7 +8,7 @@ import io.mockk.* import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.flowOf -class GetSearchItemVisitSpec : BehaviorSpec() { +class GetSearchDocumentVisitSpec : BehaviorSpec() { private val searchRepository = mockk() @@ -18,7 +18,7 @@ class GetSearchItemVisitSpec : BehaviorSpec() { val visit = mockk { every { url } returns expectUrl } - val useCase = GetSearchItemVisit(searchRepository) + val useCase = GetSearchDocumentVisit(searchRepository) every { searchRepository.getVisit(expectUrl) } returns flowOf(visit) When("Invoke") { @@ -26,7 +26,7 @@ class GetSearchItemVisitSpec : BehaviorSpec() { Then("Should return a visit") { verify { searchRepository.getVisit(eq(expectUrl)) } - result.first().url shouldBe expectUrl + result.first()?.url shouldBe expectUrl } } } diff --git a/domain/src/test/java/io/github/beomjo/search/usecase/SetSearchItemVisitSpec.kt b/domain/src/test/java/io/github/beomjo/search/usecase/SetSearchDocumentVisitSpec.kt similarity index 87% rename from domain/src/test/java/io/github/beomjo/search/usecase/SetSearchItemVisitSpec.kt rename to domain/src/test/java/io/github/beomjo/search/usecase/SetSearchDocumentVisitSpec.kt index d20c43f..5523a3f 100644 --- a/domain/src/test/java/io/github/beomjo/search/usecase/SetSearchItemVisitSpec.kt +++ b/domain/src/test/java/io/github/beomjo/search/usecase/SetSearchDocumentVisitSpec.kt @@ -6,14 +6,14 @@ import io.kotest.core.spec.style.BehaviorSpec import io.kotest.matchers.shouldBe import io.mockk.* -class SetSearchItemVisitSpec : BehaviorSpec() { +class SetSearchDocumentVisitSpec : BehaviorSpec() { private val searchRepository = mockk() init { Given("Given a url") { val url = "http://..." - val useCase = SetSearchItemVisit(searchRepository) + val useCase = SetSearchDocumentVisit(searchRepository) val slot = slot() coEvery { searchRepository.insertVisit(capture(slot)) } just Runs From a7317c386de45c5627bf83e6133f4a33126e08e8 Mon Sep 17 00:00:00 2001 From: beomjo Date: Sun, 12 Sep 2021 00:22:22 +0900 Subject: [PATCH 244/273] chore: Add license comments --- .../io/github/beomjo/search/base/BaseFragment.kt | 16 ++++++++++++++++ .../github/beomjo/search/base/BaseViewModel.kt | 16 ++++++++++++++++ .../beomjo/search/binding/BindingAdapter.kt | 16 ++++++++++++++++ .../beomjo/search/navigator/CustomNavigator.kt | 16 ++++++++++++++++ .../io/github/beomjo/search/navigator/Tab.kt | 16 ++++++++++++++++ .../ui/viewmodels/SearchDocumentItemViewModel.kt | 16 ++++++++++++++++ .../local/dao/SearchDocumentVisitDao.kt | 16 ++++++++++++++++ .../datasource/local/dao/SearchHistoryDao.kt | 16 ++++++++++++++++ .../datasource/local/table/SearchHistoryTable.kt | 16 ++++++++++++++++ .../search/datasource/local/table/VisitTable.kt | 16 ++++++++++++++++ .../beomjo/search/mapper/SearchHistoryMapper.kt | 15 +++++++++++++++ .../io/github/beomjo/search/entity/Empty.kt | 16 ++++++++++++++++ .../io/github/beomjo/search/entity/Visit.kt | 16 ++++++++++++++++ .../search/usecase/GetSearchDocumentVisit.kt | 16 ++++++++++++++++ .../search/usecase/GetSearchHistoryList.kt | 16 ++++++++++++++++ .../search/usecase/SetSearchDocumentVisit.kt | 16 ++++++++++++++++ .../search/usecase/GetSearchDocumentVisitSpec.kt | 16 ++++++++++++++++ .../search/usecase/GetSearchHistoryListSpec.kt | 16 ++++++++++++++++ .../search/usecase/SetSearchDocumentVisitSpec.kt | 16 ++++++++++++++++ 19 files changed, 303 insertions(+) diff --git a/app/src/main/kotlin/io/github/beomjo/search/base/BaseFragment.kt b/app/src/main/kotlin/io/github/beomjo/search/base/BaseFragment.kt index 11ebb1f..2a5ccea 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/base/BaseFragment.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/base/BaseFragment.kt @@ -1,3 +1,19 @@ +/* + * Designed and developed by 2021 beomjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package io.github.beomjo.search.base import android.annotation.SuppressLint diff --git a/app/src/main/kotlin/io/github/beomjo/search/base/BaseViewModel.kt b/app/src/main/kotlin/io/github/beomjo/search/base/BaseViewModel.kt index 0dccca1..9948563 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/base/BaseViewModel.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/base/BaseViewModel.kt @@ -1,3 +1,19 @@ +/* + * Designed and developed by 2021 beomjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package io.github.beomjo.search.base import androidx.lifecycle.MutableLiveData diff --git a/app/src/main/kotlin/io/github/beomjo/search/binding/BindingAdapter.kt b/app/src/main/kotlin/io/github/beomjo/search/binding/BindingAdapter.kt index 3a1dc43..fafab5d 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/binding/BindingAdapter.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/binding/BindingAdapter.kt @@ -1,3 +1,19 @@ +/* + * Designed and developed by 2021 beomjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package io.github.beomjo.search.binding import android.text.Html diff --git a/app/src/main/kotlin/io/github/beomjo/search/navigator/CustomNavigator.kt b/app/src/main/kotlin/io/github/beomjo/search/navigator/CustomNavigator.kt index cd0b0a1..1478bbc 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/navigator/CustomNavigator.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/navigator/CustomNavigator.kt @@ -1,3 +1,19 @@ +/* + * Designed and developed by 2021 beomjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package io.github.beomjo.search.navigator import android.annotation.SuppressLint diff --git a/app/src/main/kotlin/io/github/beomjo/search/navigator/Tab.kt b/app/src/main/kotlin/io/github/beomjo/search/navigator/Tab.kt index 4ee7747..a816d39 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/navigator/Tab.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/navigator/Tab.kt @@ -1,3 +1,19 @@ +/* + * Designed and developed by 2021 beomjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package io.github.beomjo.search.navigator import io.github.beomjo.search.R diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/SearchDocumentItemViewModel.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/SearchDocumentItemViewModel.kt index 287cc1c..7cbb9f4 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/SearchDocumentItemViewModel.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/SearchDocumentItemViewModel.kt @@ -1,3 +1,19 @@ +/* + * Designed and developed by 2021 beomjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package io.github.beomjo.search.ui.viewmodels import androidx.lifecycle.LiveData diff --git a/data/src/main/kotlin/io/github/beomjo/search/datasource/local/dao/SearchDocumentVisitDao.kt b/data/src/main/kotlin/io/github/beomjo/search/datasource/local/dao/SearchDocumentVisitDao.kt index c7f3d38..8cc109b 100644 --- a/data/src/main/kotlin/io/github/beomjo/search/datasource/local/dao/SearchDocumentVisitDao.kt +++ b/data/src/main/kotlin/io/github/beomjo/search/datasource/local/dao/SearchDocumentVisitDao.kt @@ -1,3 +1,19 @@ +/* + * Designed and developed by 2021 beomjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package io.github.beomjo.search.datasource.local.dao import androidx.room.Dao diff --git a/data/src/main/kotlin/io/github/beomjo/search/datasource/local/dao/SearchHistoryDao.kt b/data/src/main/kotlin/io/github/beomjo/search/datasource/local/dao/SearchHistoryDao.kt index e4aa5cc..b96fbd3 100644 --- a/data/src/main/kotlin/io/github/beomjo/search/datasource/local/dao/SearchHistoryDao.kt +++ b/data/src/main/kotlin/io/github/beomjo/search/datasource/local/dao/SearchHistoryDao.kt @@ -1,3 +1,19 @@ +/* + * Designed and developed by 2021 beomjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package io.github.beomjo.search.datasource.local.dao import androidx.room.Dao diff --git a/data/src/main/kotlin/io/github/beomjo/search/datasource/local/table/SearchHistoryTable.kt b/data/src/main/kotlin/io/github/beomjo/search/datasource/local/table/SearchHistoryTable.kt index ff54c28..3f7f644 100644 --- a/data/src/main/kotlin/io/github/beomjo/search/datasource/local/table/SearchHistoryTable.kt +++ b/data/src/main/kotlin/io/github/beomjo/search/datasource/local/table/SearchHistoryTable.kt @@ -1,3 +1,19 @@ +/* + * Designed and developed by 2021 beomjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package io.github.beomjo.search.datasource.local.table import androidx.room.Entity diff --git a/data/src/main/kotlin/io/github/beomjo/search/datasource/local/table/VisitTable.kt b/data/src/main/kotlin/io/github/beomjo/search/datasource/local/table/VisitTable.kt index 96eb194..d52af33 100644 --- a/data/src/main/kotlin/io/github/beomjo/search/datasource/local/table/VisitTable.kt +++ b/data/src/main/kotlin/io/github/beomjo/search/datasource/local/table/VisitTable.kt @@ -1,3 +1,19 @@ +/* + * Designed and developed by 2021 beomjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package io.github.beomjo.search.datasource.local.table import androidx.room.Entity diff --git a/data/src/main/kotlin/io/github/beomjo/search/mapper/SearchHistoryMapper.kt b/data/src/main/kotlin/io/github/beomjo/search/mapper/SearchHistoryMapper.kt index 07d0b73..7dd1de0 100644 --- a/data/src/main/kotlin/io/github/beomjo/search/mapper/SearchHistoryMapper.kt +++ b/data/src/main/kotlin/io/github/beomjo/search/mapper/SearchHistoryMapper.kt @@ -1,3 +1,18 @@ +/* + * Designed and developed by 2021 beomjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package io.github.beomjo.search.mapper import io.github.beomjo.search.datasource.local.table.SearchHistoryTable diff --git a/domain/src/main/kotlin/io/github/beomjo/search/entity/Empty.kt b/domain/src/main/kotlin/io/github/beomjo/search/entity/Empty.kt index 2fd139e..6efaf40 100644 --- a/domain/src/main/kotlin/io/github/beomjo/search/entity/Empty.kt +++ b/domain/src/main/kotlin/io/github/beomjo/search/entity/Empty.kt @@ -1,3 +1,19 @@ +/* + * Designed and developed by 2021 beomjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package io.github.beomjo.search.entity object Empty diff --git a/domain/src/main/kotlin/io/github/beomjo/search/entity/Visit.kt b/domain/src/main/kotlin/io/github/beomjo/search/entity/Visit.kt index c044345..4ed7020 100644 --- a/domain/src/main/kotlin/io/github/beomjo/search/entity/Visit.kt +++ b/domain/src/main/kotlin/io/github/beomjo/search/entity/Visit.kt @@ -1,3 +1,19 @@ +/* + * Designed and developed by 2021 beomjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package io.github.beomjo.search.entity import java.util.* diff --git a/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetSearchDocumentVisit.kt b/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetSearchDocumentVisit.kt index 7e4dea0..b3581ba 100644 --- a/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetSearchDocumentVisit.kt +++ b/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetSearchDocumentVisit.kt @@ -1,3 +1,19 @@ +/* + * Designed and developed by 2021 beomjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package io.github.beomjo.search.usecase import io.github.beomjo.search.entity.Visit diff --git a/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetSearchHistoryList.kt b/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetSearchHistoryList.kt index 232bc8b..f9531f1 100644 --- a/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetSearchHistoryList.kt +++ b/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetSearchHistoryList.kt @@ -1,3 +1,19 @@ +/* + * Designed and developed by 2021 beomjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package io.github.beomjo.search.usecase import io.github.beomjo.search.entity.Empty diff --git a/domain/src/main/kotlin/io/github/beomjo/search/usecase/SetSearchDocumentVisit.kt b/domain/src/main/kotlin/io/github/beomjo/search/usecase/SetSearchDocumentVisit.kt index 4f08abd..3894934 100644 --- a/domain/src/main/kotlin/io/github/beomjo/search/usecase/SetSearchDocumentVisit.kt +++ b/domain/src/main/kotlin/io/github/beomjo/search/usecase/SetSearchDocumentVisit.kt @@ -1,3 +1,19 @@ +/* + * Designed and developed by 2021 beomjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package io.github.beomjo.search.usecase import io.github.beomjo.search.entity.Visit diff --git a/domain/src/test/java/io/github/beomjo/search/usecase/GetSearchDocumentVisitSpec.kt b/domain/src/test/java/io/github/beomjo/search/usecase/GetSearchDocumentVisitSpec.kt index 3817373..c61026d 100644 --- a/domain/src/test/java/io/github/beomjo/search/usecase/GetSearchDocumentVisitSpec.kt +++ b/domain/src/test/java/io/github/beomjo/search/usecase/GetSearchDocumentVisitSpec.kt @@ -1,3 +1,19 @@ +/* + * Designed and developed by 2021 beomjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package io.github.beomjo.search.usecase import io.github.beomjo.search.entity.Visit diff --git a/domain/src/test/java/io/github/beomjo/search/usecase/GetSearchHistoryListSpec.kt b/domain/src/test/java/io/github/beomjo/search/usecase/GetSearchHistoryListSpec.kt index e55c353..1bb74ce 100644 --- a/domain/src/test/java/io/github/beomjo/search/usecase/GetSearchHistoryListSpec.kt +++ b/domain/src/test/java/io/github/beomjo/search/usecase/GetSearchHistoryListSpec.kt @@ -1,3 +1,19 @@ +/* + * Designed and developed by 2021 beomjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package io.github.beomjo.search.usecase import io.github.beomjo.search.entity.Empty diff --git a/domain/src/test/java/io/github/beomjo/search/usecase/SetSearchDocumentVisitSpec.kt b/domain/src/test/java/io/github/beomjo/search/usecase/SetSearchDocumentVisitSpec.kt index 5523a3f..b78addb 100644 --- a/domain/src/test/java/io/github/beomjo/search/usecase/SetSearchDocumentVisitSpec.kt +++ b/domain/src/test/java/io/github/beomjo/search/usecase/SetSearchDocumentVisitSpec.kt @@ -1,3 +1,19 @@ +/* + * Designed and developed by 2021 beomjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package io.github.beomjo.search.usecase import io.github.beomjo.search.entity.Visit From d0045b0a75c059d5c78e03ecc8e4036b7b3a2ec2 Mon Sep 17 00:00:00 2001 From: beomjo Date: Sun, 12 Sep 2021 00:23:51 +0900 Subject: [PATCH 245/273] chore: Fix detekt error --- .../main/kotlin/io/github/beomjo/search/base/BaseActivity.kt | 2 +- .../io/github/beomjo/search/navigator/CustomNavigator.kt | 2 +- .../io/github/beomjo/search/ui/activity/DetailActivity.kt | 3 +-- .../io/github/beomjo/search/ui/adapter/SearchPagingAdapter.kt | 2 +- .../io/github/beomjo/search/ui/fragment/SearchFragment.kt | 1 - .../io/github/beomjo/search/ui/viewmodels/DetailViewModel.kt | 2 +- .../beomjo/search/ui/viewmodels/SearchDocumentItemViewModel.kt | 1 - .../search/datasource/local/dao/SearchDocumentVisitDao.kt | 3 +-- detekt.yml | 2 ++ domain/src/main/kotlin/io/github/beomjo/search/entity/Visit.kt | 2 +- .../io/github/beomjo/search/repository/SearchRepository.kt | 2 +- .../io/github/beomjo/search/usecase/GetSearchDocumentVisit.kt | 2 +- .../io/github/beomjo/search/usecase/SetSearchDocumentVisit.kt | 2 +- .../github/beomjo/search/usecase/GetSearchDocumentVisitSpec.kt | 2 +- .../github/beomjo/search/usecase/SetSearchDocumentVisitSpec.kt | 2 +- 15 files changed, 14 insertions(+), 16 deletions(-) diff --git a/app/src/main/kotlin/io/github/beomjo/search/base/BaseActivity.kt b/app/src/main/kotlin/io/github/beomjo/search/base/BaseActivity.kt index 0601d89..fc664c6 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/base/BaseActivity.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/base/BaseActivity.kt @@ -59,4 +59,4 @@ abstract class BaseActivity( } } } -} \ No newline at end of file +} diff --git a/app/src/main/kotlin/io/github/beomjo/search/navigator/CustomNavigator.kt b/app/src/main/kotlin/io/github/beomjo/search/navigator/CustomNavigator.kt index 1478bbc..fad2593 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/navigator/CustomNavigator.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/navigator/CustomNavigator.kt @@ -121,7 +121,7 @@ class CustomNavigator( } private fun popTabBackStack(): Boolean { - val tabTag = tabBackStack.pollLast() ?: return true + tabBackStack.pollLast() ?: return true val newCurrentTag = tabBackStack.peekLast() ?: return true fragmentManager.commit { getFragmentByTag(newCurrentTag)?.let { diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/activity/DetailActivity.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/activity/DetailActivity.kt index 7bed0c4..0d67f2a 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/activity/DetailActivity.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/activity/DetailActivity.kt @@ -56,7 +56,6 @@ class DetailActivity : BaseActivity(R.layout.activity_det ) ) } - } favoriteBtn.setOnClickListener { favoriteBtn.isSelected = !favoriteBtn.isSelected @@ -72,4 +71,4 @@ class DetailActivity : BaseActivity(R.layout.activity_det .let { context.startActivity(it) } } } -} \ No newline at end of file +} diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/SearchPagingAdapter.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/SearchPagingAdapter.kt index 36708d2..ac40743 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/SearchPagingAdapter.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/SearchPagingAdapter.kt @@ -72,4 +72,4 @@ interface SearchPagingAdapterFactory { lifeCycleOwner: LifecycleOwner, onClickItem: (SearchDocument) -> Unit ): SearchPagingAdapter -} \ No newline at end of file +} diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/fragment/SearchFragment.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/fragment/SearchFragment.kt index a132dce..5005638 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/fragment/SearchFragment.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/fragment/SearchFragment.kt @@ -22,7 +22,6 @@ import android.view.inputmethod.EditorInfo import androidx.core.view.isVisible import androidx.lifecycle.ViewModelStoreOwner import androidx.lifecycle.lifecycleScope -import androidx.navigation.fragment.findNavController import androidx.paging.LoadState import androidx.recyclerview.widget.ConcatAdapter import dagger.hilt.android.AndroidEntryPoint diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/DetailViewModel.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/DetailViewModel.kt index f4e3f09..d0e28d2 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/DetailViewModel.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/DetailViewModel.kt @@ -31,4 +31,4 @@ class DetailViewModel @Inject constructor( setSearchDocumentVisit(searchDocument.value?.url ?: "") } } -} \ No newline at end of file +} diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/SearchDocumentItemViewModel.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/SearchDocumentItemViewModel.kt index 7cbb9f4..db81ff9 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/SearchDocumentItemViewModel.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/SearchDocumentItemViewModel.kt @@ -43,4 +43,3 @@ class SearchDocumentViewModel @AssistedInject constructor( interface SearchDocumentViewModelFactory { fun create(searchDocument: SearchDocument): SearchDocumentViewModel } - diff --git a/data/src/main/kotlin/io/github/beomjo/search/datasource/local/dao/SearchDocumentVisitDao.kt b/data/src/main/kotlin/io/github/beomjo/search/datasource/local/dao/SearchDocumentVisitDao.kt index 8cc109b..3e53f50 100644 --- a/data/src/main/kotlin/io/github/beomjo/search/datasource/local/dao/SearchDocumentVisitDao.kt +++ b/data/src/main/kotlin/io/github/beomjo/search/datasource/local/dao/SearchDocumentVisitDao.kt @@ -21,7 +21,6 @@ import androidx.room.Insert import androidx.room.OnConflictStrategy import androidx.room.Query import io.github.beomjo.search.datasource.local.table.VisitTable -import io.github.beomjo.search.entity.Visit import kotlinx.coroutines.flow.Flow @Dao @@ -31,4 +30,4 @@ internal interface SearchDocumentVisitDao { @Query("SELECT * FROM visit WHERE url == :url") fun getVisit(url: String): Flow -} \ No newline at end of file +} diff --git a/detekt.yml b/detekt.yml index 5d84e0d..e2501d1 100644 --- a/detekt.yml +++ b/detekt.yml @@ -9,6 +9,8 @@ style: complexity: LargeClass: excludes: [ '**/test/**' ] + TooManyFunctions: + active: false formatting: NoWildcardImports: active: false diff --git a/domain/src/main/kotlin/io/github/beomjo/search/entity/Visit.kt b/domain/src/main/kotlin/io/github/beomjo/search/entity/Visit.kt index 4ed7020..02196ba 100644 --- a/domain/src/main/kotlin/io/github/beomjo/search/entity/Visit.kt +++ b/domain/src/main/kotlin/io/github/beomjo/search/entity/Visit.kt @@ -21,4 +21,4 @@ import java.util.* data class Visit( val date: Date?, val url: String, -) \ No newline at end of file +) diff --git a/domain/src/main/kotlin/io/github/beomjo/search/repository/SearchRepository.kt b/domain/src/main/kotlin/io/github/beomjo/search/repository/SearchRepository.kt index 46f5b97..39c6826 100644 --- a/domain/src/main/kotlin/io/github/beomjo/search/repository/SearchRepository.kt +++ b/domain/src/main/kotlin/io/github/beomjo/search/repository/SearchRepository.kt @@ -33,5 +33,5 @@ interface SearchRepository { suspend fun insertVisit(visit: Visit) - fun getVisit(url:String) :Flow + fun getVisit(url: String): Flow } diff --git a/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetSearchDocumentVisit.kt b/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetSearchDocumentVisit.kt index b3581ba..1afcb13 100644 --- a/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetSearchDocumentVisit.kt +++ b/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetSearchDocumentVisit.kt @@ -28,4 +28,4 @@ class GetSearchDocumentVisit @Inject constructor( override fun execute(parameters: String): Flow { return searchRepository.getVisit(parameters) } -} \ No newline at end of file +} diff --git a/domain/src/main/kotlin/io/github/beomjo/search/usecase/SetSearchDocumentVisit.kt b/domain/src/main/kotlin/io/github/beomjo/search/usecase/SetSearchDocumentVisit.kt index 3894934..8890da2 100644 --- a/domain/src/main/kotlin/io/github/beomjo/search/usecase/SetSearchDocumentVisit.kt +++ b/domain/src/main/kotlin/io/github/beomjo/search/usecase/SetSearchDocumentVisit.kt @@ -28,4 +28,4 @@ class SetSearchDocumentVisit @Inject constructor( override suspend fun execute(parameters: String) { searchRepository.insertVisit(Visit(Date(), parameters)) } -} \ No newline at end of file +} diff --git a/domain/src/test/java/io/github/beomjo/search/usecase/GetSearchDocumentVisitSpec.kt b/domain/src/test/java/io/github/beomjo/search/usecase/GetSearchDocumentVisitSpec.kt index c61026d..4ad482a 100644 --- a/domain/src/test/java/io/github/beomjo/search/usecase/GetSearchDocumentVisitSpec.kt +++ b/domain/src/test/java/io/github/beomjo/search/usecase/GetSearchDocumentVisitSpec.kt @@ -51,4 +51,4 @@ class GetSearchDocumentVisitSpec : BehaviorSpec() { unmockkAll() } } -} \ No newline at end of file +} diff --git a/domain/src/test/java/io/github/beomjo/search/usecase/SetSearchDocumentVisitSpec.kt b/domain/src/test/java/io/github/beomjo/search/usecase/SetSearchDocumentVisitSpec.kt index b78addb..db3b279 100644 --- a/domain/src/test/java/io/github/beomjo/search/usecase/SetSearchDocumentVisitSpec.kt +++ b/domain/src/test/java/io/github/beomjo/search/usecase/SetSearchDocumentVisitSpec.kt @@ -47,4 +47,4 @@ class SetSearchDocumentVisitSpec : BehaviorSpec() { unmockkAll() } } -} \ No newline at end of file +} From f6c7a46d70a4927e0d5980bec7879d4a706b9fc7 Mon Sep 17 00:00:00 2001 From: beomjo Date: Sun, 12 Sep 2021 02:01:33 +0900 Subject: [PATCH 246/273] test: test: Write the SearchDocumentViewModel test --- ...iewModel.kt => SearchDocumentViewModel.kt} | 4 +- .../viewmodels/SearchDocumentViewModelSpec.kt | 90 +++++++++++++++++++ .../ui/viewmodels/SearchViewModelSpec.kt | 11 ++- 3 files changed, 97 insertions(+), 8 deletions(-) rename app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/{SearchDocumentItemViewModel.kt => SearchDocumentViewModel.kt} (91%) create mode 100644 app/src/test/kotlin/io/github/beomjo/search/ui/viewmodels/SearchDocumentViewModelSpec.kt diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/SearchDocumentItemViewModel.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/SearchDocumentViewModel.kt similarity index 91% rename from app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/SearchDocumentItemViewModel.kt rename to app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/SearchDocumentViewModel.kt index db81ff9..6e624b0 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/SearchDocumentItemViewModel.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/SearchDocumentViewModel.kt @@ -30,9 +30,9 @@ import kotlinx.coroutines.flow.flowOn class SearchDocumentViewModel @AssistedInject constructor( @Assisted val searchDocument: SearchDocument, - getSearchDocumentItemVisit: GetSearchDocumentVisit + getSearchDocumentVisit: GetSearchDocumentVisit ) { - val isVisit: LiveData = getSearchDocumentItemVisit(searchDocument.url) + val isVisit: LiveData = getSearchDocumentVisit(searchDocument.url) .distinctUntilChanged() .flowOn(Dispatchers.Main) .asLiveData() diff --git a/app/src/test/kotlin/io/github/beomjo/search/ui/viewmodels/SearchDocumentViewModelSpec.kt b/app/src/test/kotlin/io/github/beomjo/search/ui/viewmodels/SearchDocumentViewModelSpec.kt new file mode 100644 index 0000000..8c0796b --- /dev/null +++ b/app/src/test/kotlin/io/github/beomjo/search/ui/viewmodels/SearchDocumentViewModelSpec.kt @@ -0,0 +1,90 @@ +/* + * Designed and developed by 2021 beomjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.github.beomjo.search.ui.viewmodels + +import androidx.lifecycle.Observer +import io.github.beomjo.search.entity.SearchDocument +import io.github.beomjo.search.entity.Visit +import io.github.beomjo.search.usecase.GetSearchDocumentVisit +import io.kotest.core.spec.style.BehaviorSpec +import io.mockk.* +import kotlinx.coroutines.flow.flowOf + +class SearchDocumentViewModelSpec : BehaviorSpec() { + + private val getSearchDocumentVisit = mockk(relaxed = true) + + private val isVisitObserver = mockk>(relaxed = true) + + init { + Given("Give a SearchDocument") { + val documentUrl = "http://" + val searchDocument = mockk { + every { url } returns documentUrl + every { date } returns mockk() + } + val visit = Visit( + mockk(), + documentUrl + ) + every { getSearchDocumentVisit.invoke(documentUrl) } returns flowOf(visit) + + When("Create a ViewModel") { + val viewModel = SearchDocumentViewModel( + searchDocument, + getSearchDocumentVisit + ) + viewModel.isVisit.observeForever(isVisitObserver) + + Then("isVisit value needs to be updated, true") { + verify { + getSearchDocumentVisit.invoke(eq(documentUrl)) + isVisitObserver.onChanged(eq(true)) + } + } + } + } + + Given("There is no search document") { + val documentUrl = "http://" + val searchDocument = mockk { + every { url } returns documentUrl + every { date } returns mockk() + } + every { getSearchDocumentVisit.invoke(any()) } returns flowOf(null) + + When("Create a ViewModel") { + val viewModel = SearchDocumentViewModel( + searchDocument, + getSearchDocumentVisit + ) + viewModel.isVisit.observeForever(isVisitObserver) + + Then("isVisit value needs to be updated, false") { + verify { + getSearchDocumentVisit.invoke(eq(documentUrl)) + isVisitObserver.onChanged(eq(false)) + } + } + } + } + + afterTest { + unmockkAll() + } + } +} \ No newline at end of file diff --git a/app/src/test/kotlin/io/github/beomjo/search/ui/viewmodels/SearchViewModelSpec.kt b/app/src/test/kotlin/io/github/beomjo/search/ui/viewmodels/SearchViewModelSpec.kt index 18c7a19..d73b1b2 100644 --- a/app/src/test/kotlin/io/github/beomjo/search/ui/viewmodels/SearchViewModelSpec.kt +++ b/app/src/test/kotlin/io/github/beomjo/search/ui/viewmodels/SearchViewModelSpec.kt @@ -28,12 +28,7 @@ import io.github.beomjo.search.usecase.SearchPagingParam import io.kotest.core.spec.style.BehaviorSpec import io.kotest.matchers.collections.shouldContainAll import io.kotest.matchers.shouldBe -import io.mockk.mockk -import io.mockk.every -import io.mockk.slot -import io.mockk.just -import io.mockk.Runs -import io.mockk.verify +import io.mockk.* import kotlinx.coroutines.flow.flowOf class SearchViewModelSpec : BehaviorSpec() { @@ -172,5 +167,9 @@ class SearchViewModelSpec : BehaviorSpec() { } } } + + afterTest { + unmockkAll() + } } } From 55f7be3f878baa2f28a9612f8622609f53a9c216 Mon Sep 17 00:00:00 2001 From: beomjo Date: Sun, 12 Sep 2021 14:54:04 +0900 Subject: [PATCH 247/273] feat: Add BaseViewModel Finish Event --- .../io/github/beomjo/search/base/BaseActivity.kt | 12 ++++++++---- .../io/github/beomjo/search/base/BaseFragment.kt | 12 ++++++++---- .../io/github/beomjo/search/base/BaseViewModel.kt | 6 ++++++ 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/app/src/main/kotlin/io/github/beomjo/search/base/BaseActivity.kt b/app/src/main/kotlin/io/github/beomjo/search/base/BaseActivity.kt index fc664c6..437c0ea 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/base/BaseActivity.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/base/BaseActivity.kt @@ -23,6 +23,7 @@ import androidx.annotation.LayoutRes import androidx.databinding.ViewDataBinding import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.ViewModelProvider +import com.beomjo.compilation.util.EventObserver import com.skydoves.bindables.BindingActivity abstract class BaseActivity( @@ -53,10 +54,13 @@ abstract class BaseActivity( } private fun observeToast(vm: BaseViewModel) { - vm.toast.observe(this) { event -> - event.getContentIfNotHandled()?.let { msg -> - Toast.makeText(this, msg, Toast.LENGTH_SHORT).show() + vm.toast.observe(this, EventObserver { msg -> + Toast.makeText(this, msg, Toast.LENGTH_SHORT).show() + }) + vm.event.observe(this, EventObserver { + when (it) { + is BaseViewModel.Action.Finish -> onBackPressed() } - } + }) } } diff --git a/app/src/main/kotlin/io/github/beomjo/search/base/BaseFragment.kt b/app/src/main/kotlin/io/github/beomjo/search/base/BaseFragment.kt index 2a5ccea..cf74a25 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/base/BaseFragment.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/base/BaseFragment.kt @@ -26,6 +26,7 @@ import androidx.annotation.LayoutRes import androidx.databinding.ViewDataBinding import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelStoreOwner +import com.beomjo.compilation.util.EventObserver import com.skydoves.bindables.BindingFragment abstract class BaseFragment( @@ -64,10 +65,13 @@ abstract class BaseFragment( } private fun observeToast(vm: BaseViewModel) { - vm.toast.observe(viewLifecycleOwner) { event -> - event.getContentIfNotHandled()?.let { msg -> - Toast.makeText(context, msg, Toast.LENGTH_SHORT).show() + vm.toast.observe(viewLifecycleOwner, EventObserver { msg -> + Toast.makeText(context, msg, Toast.LENGTH_SHORT).show() + }) + vm.event.observe(this, EventObserver { + when (it) { + is BaseViewModel.Action.Finish -> requireActivity().onBackPressed() } - } + }) } } diff --git a/app/src/main/kotlin/io/github/beomjo/search/base/BaseViewModel.kt b/app/src/main/kotlin/io/github/beomjo/search/base/BaseViewModel.kt index 9948563..eea4110 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/base/BaseViewModel.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/base/BaseViewModel.kt @@ -27,6 +27,8 @@ import kotlinx.coroutines.launch abstract class BaseViewModel : BindingViewModel() { val toast = MutableLiveData>() + val event = MutableLiveData>() + fun launch( block: suspend () -> Unit, ): Job { @@ -53,4 +55,8 @@ abstract class BaseViewModel : BindingViewModel() { } } } + + sealed class Action { + object Finish : Action() + } } From 64fb082dadda49b02459214628a06a1bcdbf887e Mon Sep 17 00:00:00 2001 From: beomjo Date: Sun, 12 Sep 2021 15:17:07 +0900 Subject: [PATCH 248/273] test: Write the DetailViewModel test --- .../beomjo/search/base/BaseViewModel.kt | 4 + .../search/ui/viewmodels/DetailViewModel.kt | 4 +- .../ui/viewmodels/DetailViewModelSpec.kt | 99 +++++++++++++++++++ 3 files changed, 105 insertions(+), 2 deletions(-) create mode 100644 app/src/test/kotlin/io/github/beomjo/search/ui/viewmodels/DetailViewModelSpec.kt diff --git a/app/src/main/kotlin/io/github/beomjo/search/base/BaseViewModel.kt b/app/src/main/kotlin/io/github/beomjo/search/base/BaseViewModel.kt index eea4110..6daf813 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/base/BaseViewModel.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/base/BaseViewModel.kt @@ -56,6 +56,10 @@ abstract class BaseViewModel : BindingViewModel() { } } + fun finish() { + event.value = Event(Action.Finish) + } + sealed class Action { object Finish : Action() } diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/DetailViewModel.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/DetailViewModel.kt index d0e28d2..f0d72d8 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/DetailViewModel.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/DetailViewModel.kt @@ -22,13 +22,13 @@ class DetailViewModel @Inject constructor( searchDocument?.let { _searchDocument.value = it } ?: kotlin.run { - // TODO DO Back Activity + finish() } } fun setVisit() { viewModelScope.launch { - setSearchDocumentVisit(searchDocument.value?.url ?: "") + setSearchDocumentVisit(searchDocument.value?.url ?: return@launch) } } } diff --git a/app/src/test/kotlin/io/github/beomjo/search/ui/viewmodels/DetailViewModelSpec.kt b/app/src/test/kotlin/io/github/beomjo/search/ui/viewmodels/DetailViewModelSpec.kt new file mode 100644 index 0000000..24bc287 --- /dev/null +++ b/app/src/test/kotlin/io/github/beomjo/search/ui/viewmodels/DetailViewModelSpec.kt @@ -0,0 +1,99 @@ +/* + * Designed and developed by 2021 beomjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.github.beomjo.search.ui.viewmodels + +import androidx.lifecycle.Observer +import com.beomjo.compilation.util.Event +import io.github.beomjo.search.base.BaseViewModel +import io.github.beomjo.search.entity.SearchDocument +import io.github.beomjo.search.usecase.SetSearchDocumentVisit +import io.kotest.core.spec.style.BehaviorSpec + +import io.mockk.* + +class DetailViewModelSpec : BehaviorSpec() { + + private val setSearchDocumentVisit = mockk(relaxed = true) + + private val searchDocumentObserver = mockk>(relaxed = true) + + init { + + Given("Given a searchDocument") { + val searchDocument = mockk() + val detailViewModel = DetailViewModel(setSearchDocumentVisit) + detailViewModel.searchDocument.observeForever(searchDocumentObserver) + + When("Call init") { + detailViewModel.init(searchDocument) + + Then("Should to update searchDocument") { + verify { searchDocumentObserver.onChanged(eq(searchDocument)) } + } + } + } + + Given("Search document given as null") { + val detailViewModel = DetailViewModel(setSearchDocumentVisit) + val eventObserver = mockk>>(relaxed = true) + detailViewModel.event.observeForever(eventObserver) + + When("Call init") { + detailViewModel.init(null) + + Then("Should to update searchDocument") { + verify(inverse = true) { searchDocumentObserver.onChanged(any()) } + verify { eventObserver.onChanged(any>()) } + + } + } + } + + Given("Given a search document") { + val documentUrl = "http://.." + val searchDocument = mockk { + every { url } returns documentUrl + } + val detailViewModel = DetailViewModel(setSearchDocumentVisit) + detailViewModel.init(searchDocument) + + When("Set visit search document") { + detailViewModel.setVisit() + + Then("Should call setVisit to save whether searchDocument is visited or not") { + coVerify { setSearchDocumentVisit.invoke(eq(documentUrl)) } + } + } + } + + Given("Given Search document is null") { + val detailViewModel = DetailViewModel(setSearchDocumentVisit) + + When("Set visit search document") { + detailViewModel.setVisit() + + Then("Should not call setSearchDocumentVisit") { + coVerify(inverse = true) { setSearchDocumentVisit.invoke(any()) } + } + } + } + + afterTest { + unmockkAll() + } + } +} \ No newline at end of file From 0c5cae40f90dbd43a5098d3967c600c5cdf36e82 Mon Sep 17 00:00:00 2001 From: beomjo Date: Sun, 12 Sep 2021 15:17:50 +0900 Subject: [PATCH 249/273] chore: Fix detekt error --- .../github/beomjo/search/ui/viewmodels/DetailViewModelSpec.kt | 3 +-- .../beomjo/search/ui/viewmodels/SearchDocumentViewModelSpec.kt | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/app/src/test/kotlin/io/github/beomjo/search/ui/viewmodels/DetailViewModelSpec.kt b/app/src/test/kotlin/io/github/beomjo/search/ui/viewmodels/DetailViewModelSpec.kt index 24bc287..eefa868 100644 --- a/app/src/test/kotlin/io/github/beomjo/search/ui/viewmodels/DetailViewModelSpec.kt +++ b/app/src/test/kotlin/io/github/beomjo/search/ui/viewmodels/DetailViewModelSpec.kt @@ -58,7 +58,6 @@ class DetailViewModelSpec : BehaviorSpec() { Then("Should to update searchDocument") { verify(inverse = true) { searchDocumentObserver.onChanged(any()) } verify { eventObserver.onChanged(any>()) } - } } } @@ -96,4 +95,4 @@ class DetailViewModelSpec : BehaviorSpec() { unmockkAll() } } -} \ No newline at end of file +} diff --git a/app/src/test/kotlin/io/github/beomjo/search/ui/viewmodels/SearchDocumentViewModelSpec.kt b/app/src/test/kotlin/io/github/beomjo/search/ui/viewmodels/SearchDocumentViewModelSpec.kt index 8c0796b..fee60cc 100644 --- a/app/src/test/kotlin/io/github/beomjo/search/ui/viewmodels/SearchDocumentViewModelSpec.kt +++ b/app/src/test/kotlin/io/github/beomjo/search/ui/viewmodels/SearchDocumentViewModelSpec.kt @@ -87,4 +87,4 @@ class SearchDocumentViewModelSpec : BehaviorSpec() { unmockkAll() } } -} \ No newline at end of file +} From 046a5b7b5339520189c4fed5ce882f70a56df458 Mon Sep 17 00:00:00 2001 From: beomjo Date: Sun, 12 Sep 2021 15:55:24 +0900 Subject: [PATCH 250/273] feat: Change tab name --- .../main/kotlin/io/github/beomjo/search/navigator/Tab.kt | 4 ++-- .../io/github/beomjo/search/ui/activity/MainActivity.kt | 2 +- .../fragment/{FavoriteFragment.kt => BookmarkFragment.kt} | 8 ++++---- app/src/main/res/drawable/ic_bookmark.xml | 5 +++++ .../{ic_favorite_fill.xml => ic_bookmark_fill.xml} | 2 +- app/src/main/res/drawable/ic_favorite.xml | 5 ----- .../{selector_favorite.xml => selector_bookmark.xml} | 4 ++-- app/src/main/res/layout/activity_detail.xml | 2 +- .../{fragment_favorite.xml => fragment_bookmark.xml} | 4 ++-- app/src/main/res/layout/search_list_document_item.xml | 4 ++-- app/src/main/res/menu/bottom_nav_menu.xml | 6 +++--- app/src/main/res/menu/nav_drawer_menu.xml | 6 +++--- app/src/main/res/navigation/main_graph.xml | 6 +++--- app/src/main/res/values-ko/strings.xml | 4 ++-- app/src/main/res/values/strings.xml | 4 ++-- 15 files changed, 33 insertions(+), 33 deletions(-) rename app/src/main/kotlin/io/github/beomjo/search/ui/fragment/{FavoriteFragment.kt => BookmarkFragment.kt} (82%) create mode 100644 app/src/main/res/drawable/ic_bookmark.xml rename app/src/main/res/drawable/{ic_favorite_fill.xml => ic_bookmark_fill.xml} (57%) delete mode 100644 app/src/main/res/drawable/ic_favorite.xml rename app/src/main/res/drawable/{selector_favorite.xml => selector_bookmark.xml} (56%) rename app/src/main/res/layout/{fragment_favorite.xml => fragment_bookmark.xml} (92%) diff --git a/app/src/main/kotlin/io/github/beomjo/search/navigator/Tab.kt b/app/src/main/kotlin/io/github/beomjo/search/navigator/Tab.kt index a816d39..cb82a27 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/navigator/Tab.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/navigator/Tab.kt @@ -17,7 +17,7 @@ package io.github.beomjo.search.navigator import io.github.beomjo.search.R -import io.github.beomjo.search.ui.fragment.FavoriteFragment +import io.github.beomjo.search.ui.fragment.BookmarkFragment import io.github.beomjo.search.ui.fragment.SearchFragment enum class Tab( @@ -25,7 +25,7 @@ enum class Tab( val tag: String ) { SEARCH(R.id.search_dest, SearchFragment.TAG), - FAVORITE(R.id.favorite, FavoriteFragment.TAG); + BOOKMARK(R.id.bookmark_dest, BookmarkFragment.TAG); companion object } diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/activity/MainActivity.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/activity/MainActivity.kt index 40ff733..fc29d16 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/activity/MainActivity.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/activity/MainActivity.kt @@ -42,7 +42,7 @@ class MainActivity : BaseActivity(R.layout.activity_main) { private val appBarConfiguration: AppBarConfiguration by lazy { AppBarConfiguration( - setOf(R.id.favorite, R.id.search_dest), + setOf(R.id.bookmark_dest, R.id.search_dest), binding.drawerLayout ) } diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/fragment/FavoriteFragment.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/fragment/BookmarkFragment.kt similarity index 82% rename from app/src/main/kotlin/io/github/beomjo/search/ui/fragment/FavoriteFragment.kt rename to app/src/main/kotlin/io/github/beomjo/search/ui/fragment/BookmarkFragment.kt index 8289a8f..2103fe6 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/fragment/FavoriteFragment.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/fragment/BookmarkFragment.kt @@ -21,19 +21,19 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment -import io.github.beomjo.search.databinding.FragmentFavoriteBinding +import io.github.beomjo.search.databinding.FragmentBookmarkBinding -class FavoriteFragment : Fragment() { +class BookmarkFragment : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { - val binding = FragmentFavoriteBinding.inflate(layoutInflater) + val binding = FragmentBookmarkBinding.inflate(layoutInflater) return binding.root } companion object { - val TAG = FavoriteFragment::class.java.simpleName + val TAG = BookmarkFragment::class.java.simpleName } } diff --git a/app/src/main/res/drawable/ic_bookmark.xml b/app/src/main/res/drawable/ic_bookmark.xml new file mode 100644 index 0000000..7b2915b --- /dev/null +++ b/app/src/main/res/drawable/ic_bookmark.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_favorite_fill.xml b/app/src/main/res/drawable/ic_bookmark_fill.xml similarity index 57% rename from app/src/main/res/drawable/ic_favorite_fill.xml rename to app/src/main/res/drawable/ic_bookmark_fill.xml index 0e42ffc..5e7f0c8 100644 --- a/app/src/main/res/drawable/ic_favorite_fill.xml +++ b/app/src/main/res/drawable/ic_bookmark_fill.xml @@ -6,5 +6,5 @@ android:viewportHeight="24"> + android:pathData="M17,3H7c-1.1,0 -1.99,0.9 -1.99,2L5,21l7,-3 7,3V5c0,-1.1 -0.9,-2 -2,-2z" /> diff --git a/app/src/main/res/drawable/ic_favorite.xml b/app/src/main/res/drawable/ic_favorite.xml deleted file mode 100644 index 83a924b..0000000 --- a/app/src/main/res/drawable/ic_favorite.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/selector_favorite.xml b/app/src/main/res/drawable/selector_bookmark.xml similarity index 56% rename from app/src/main/res/drawable/selector_favorite.xml rename to app/src/main/res/drawable/selector_bookmark.xml index 8f8dc33..1474ca8 100644 --- a/app/src/main/res/drawable/selector_favorite.xml +++ b/app/src/main/res/drawable/selector_bookmark.xml @@ -1,5 +1,5 @@ - - + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_detail.xml b/app/src/main/res/layout/activity_detail.xml index 7165e0c..a736c60 100644 --- a/app/src/main/res/layout/activity_detail.xml +++ b/app/src/main/res/layout/activity_detail.xml @@ -149,7 +149,7 @@ android:layout_height="50dp" android:layout_marginStart="10dp" android:layout_marginBottom="10dp" - android:src="@drawable/selector_favorite" + android:src="@drawable/selector_bookmark" android:textAppearance="?attr/textAppearanceListItem" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toStartOf="@id/move_webview_btn" diff --git a/app/src/main/res/layout/fragment_favorite.xml b/app/src/main/res/layout/fragment_bookmark.xml similarity index 92% rename from app/src/main/res/layout/fragment_favorite.xml rename to app/src/main/res/layout/fragment_bookmark.xml index c178bcb..c99f002 100644 --- a/app/src/main/res/layout/fragment_favorite.xml +++ b/app/src/main/res/layout/fragment_bookmark.xml @@ -18,14 +18,14 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - tools:context="io.github.beomjo.search.ui.fragment.FavoriteFragment"> + tools:context="io.github.beomjo.search.ui.fragment.BookmarkFragment"> diff --git a/app/src/main/res/menu/bottom_nav_menu.xml b/app/src/main/res/menu/bottom_nav_menu.xml index 0fbe843..851a191 100644 --- a/app/src/main/res/menu/bottom_nav_menu.xml +++ b/app/src/main/res/menu/bottom_nav_menu.xml @@ -20,7 +20,7 @@ android:title="@string/search" /> + android:id="@id/bookmark_dest" + android:icon="@drawable/ic_bookmark " + android:title="@string/bookmark" /> \ No newline at end of file diff --git a/app/src/main/res/menu/nav_drawer_menu.xml b/app/src/main/res/menu/nav_drawer_menu.xml index e2a9cf6..7270aa9 100644 --- a/app/src/main/res/menu/nav_drawer_menu.xml +++ b/app/src/main/res/menu/nav_drawer_menu.xml @@ -21,8 +21,8 @@ android:title="@string/search_fragment_title" /> + android:id="@id/bookmark_dest" + android:icon="@drawable/ic_bookmark" + android:title="@string/bookmark" /> diff --git a/app/src/main/res/navigation/main_graph.xml b/app/src/main/res/navigation/main_graph.xml index 372eee6..4f32591 100644 --- a/app/src/main/res/navigation/main_graph.xml +++ b/app/src/main/res/navigation/main_graph.xml @@ -26,9 +26,9 @@ + android:id="@+id/bookmark_dest" + android:name="io.github.beomjo.search.ui.fragment.BookmarkFragment" + tools:layout="@layout/fragment_bookmark"> Kakao Search - Favorite Fragment + Bookmark Fragment Search Fragment Detail Fragment - 좋아하는 + 북마크 검색 검색어를 입력하세요. 재시도 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 449ea03..c64f962 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -15,10 +15,10 @@ limitations under the License. --> Kakao Search - Favorite Fragment + Bookmark Fragment Search Fragment Detail Fragment - Favorite + Bookmark Search Input Search Keyword RETRY From 08803bc0f25131371df6417594e3a639dfc5f2fc Mon Sep 17 00:00:00 2001 From: beomjo Date: Sun, 12 Sep 2021 15:31:10 +0900 Subject: [PATCH 251/273] feat: Change parameter naming --- .../beomjo/search/usecase/GetSearchDocumentVisit.kt | 4 ++-- .../github/beomjo/search/usecase/GetSearchHistoryList.kt | 2 +- .../github/beomjo/search/usecase/GetSearchPagingData.kt | 8 ++++---- .../beomjo/search/usecase/SetSearchDocumentVisit.kt | 4 ++-- .../io/github/beomjo/search/usecase/base/FlowUseCase.kt | 6 +++--- .../io/github/beomjo/search/usecase/base/PagingUseCase.kt | 6 +++--- .../io/github/beomjo/search/usecase/base/UseCase.kt | 6 +++--- 7 files changed, 18 insertions(+), 18 deletions(-) diff --git a/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetSearchDocumentVisit.kt b/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetSearchDocumentVisit.kt index 1afcb13..643e77c 100644 --- a/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetSearchDocumentVisit.kt +++ b/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetSearchDocumentVisit.kt @@ -25,7 +25,7 @@ import javax.inject.Inject class GetSearchDocumentVisit @Inject constructor( private val searchRepository: SearchRepository ) : FlowUseCase() { - override fun execute(parameters: String): Flow { - return searchRepository.getVisit(parameters) + override fun execute(param: String): Flow { + return searchRepository.getVisit(param) } } diff --git a/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetSearchHistoryList.kt b/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetSearchHistoryList.kt index f9531f1..ea741f6 100644 --- a/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetSearchHistoryList.kt +++ b/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetSearchHistoryList.kt @@ -26,7 +26,7 @@ import javax.inject.Inject class GetSearchHistoryList @Inject constructor( private val searchRepository: SearchRepository ) : FlowUseCase>() { - override fun execute(parameters: Empty): Flow> { + override fun execute(param: Empty): Flow> { return searchRepository.getSearchHistoryList() } } diff --git a/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetSearchPagingData.kt b/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetSearchPagingData.kt index 1133529..878a974 100644 --- a/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetSearchPagingData.kt +++ b/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetSearchPagingData.kt @@ -36,13 +36,13 @@ data class SearchPagingParam( class GetSearchPagingData @Inject constructor( private val searchRepository: SearchRepository ) : PagingUseCase() { - override fun execute(parameters: SearchPagingParam): Flow> { - return searchRepository.getDocumentPagingData(parameters) + override fun execute(param: SearchPagingParam): Flow> { + return searchRepository.getDocumentPagingData(param) .onStart { searchRepository.insertSearchHistory( History( - query = parameters.query, - date = parameters.date + query = param.query, + date = param.date ) ) } diff --git a/domain/src/main/kotlin/io/github/beomjo/search/usecase/SetSearchDocumentVisit.kt b/domain/src/main/kotlin/io/github/beomjo/search/usecase/SetSearchDocumentVisit.kt index 8890da2..c2fc1f6 100644 --- a/domain/src/main/kotlin/io/github/beomjo/search/usecase/SetSearchDocumentVisit.kt +++ b/domain/src/main/kotlin/io/github/beomjo/search/usecase/SetSearchDocumentVisit.kt @@ -25,7 +25,7 @@ import javax.inject.Inject class SetSearchDocumentVisit @Inject constructor( private val searchRepository: SearchRepository ) : UseCase() { - override suspend fun execute(parameters: String) { - searchRepository.insertVisit(Visit(Date(), parameters)) + override suspend fun execute(param: String) { + searchRepository.insertVisit(Visit(Date(), param)) } } diff --git a/domain/src/main/kotlin/io/github/beomjo/search/usecase/base/FlowUseCase.kt b/domain/src/main/kotlin/io/github/beomjo/search/usecase/base/FlowUseCase.kt index 92687ba..5a86e4e 100644 --- a/domain/src/main/kotlin/io/github/beomjo/search/usecase/base/FlowUseCase.kt +++ b/domain/src/main/kotlin/io/github/beomjo/search/usecase/base/FlowUseCase.kt @@ -20,9 +20,9 @@ import kotlinx.coroutines.flow.Flow abstract class FlowUseCase { - operator fun invoke(parameters: P): Flow { - return execute(parameters) + operator fun invoke(param: P): Flow { + return execute(param) } - protected abstract fun execute(parameters: P): Flow + protected abstract fun execute(param: P): Flow } diff --git a/domain/src/main/kotlin/io/github/beomjo/search/usecase/base/PagingUseCase.kt b/domain/src/main/kotlin/io/github/beomjo/search/usecase/base/PagingUseCase.kt index 3ed19d3..772f34a 100644 --- a/domain/src/main/kotlin/io/github/beomjo/search/usecase/base/PagingUseCase.kt +++ b/domain/src/main/kotlin/io/github/beomjo/search/usecase/base/PagingUseCase.kt @@ -21,9 +21,9 @@ import kotlinx.coroutines.flow.Flow abstract class PagingUseCase { - operator fun invoke(parameters: P): Flow> { - return execute(parameters) + operator fun invoke(param: P): Flow> { + return execute(param) } - protected abstract fun execute(parameters: P): Flow> + protected abstract fun execute(param: P): Flow> } diff --git a/domain/src/main/kotlin/io/github/beomjo/search/usecase/base/UseCase.kt b/domain/src/main/kotlin/io/github/beomjo/search/usecase/base/UseCase.kt index 963fb57..c865b3c 100644 --- a/domain/src/main/kotlin/io/github/beomjo/search/usecase/base/UseCase.kt +++ b/domain/src/main/kotlin/io/github/beomjo/search/usecase/base/UseCase.kt @@ -18,9 +18,9 @@ package io.github.beomjo.search.usecase.base abstract class UseCase { - suspend operator fun invoke(parameters: P): R { - return execute(parameters) + suspend operator fun invoke(param: P): R { + return execute(param) } - protected abstract suspend fun execute(parameters: P): R + protected abstract suspend fun execute(param: P): R } From 052ac318852ce0dea9a057a0c52edc8b2950db66 Mon Sep 17 00:00:00 2001 From: beomjo Date: Sun, 12 Sep 2021 16:12:36 +0900 Subject: [PATCH 252/273] feat: Implements Bookmark UseCase --- .../search/repository/BookmarkRepository.kt | 14 +++++ .../beomjo/search/usecase/GetBookmark.kt | 31 +++++++++++ .../beomjo/search/usecase/GetBookmarkList.kt | 32 ++++++++++++ .../beomjo/search/usecase/RemoveBookmark.kt | 30 +++++++++++ .../beomjo/search/usecase/SetBookmark.kt | 30 +++++++++++ .../search/usecase/GetBookmarkListSpec.kt | 52 +++++++++++++++++++ .../beomjo/search/usecase/GetBookmarkSpec.kt | 42 +++++++++++++++ .../search/usecase/RemoveBookmarkSpec.kt | 47 +++++++++++++++++ .../beomjo/search/usecase/SetFavoriteSpec.kt | 47 +++++++++++++++++ 9 files changed, 325 insertions(+) create mode 100644 domain/src/main/kotlin/io/github/beomjo/search/repository/BookmarkRepository.kt create mode 100644 domain/src/main/kotlin/io/github/beomjo/search/usecase/GetBookmark.kt create mode 100644 domain/src/main/kotlin/io/github/beomjo/search/usecase/GetBookmarkList.kt create mode 100644 domain/src/main/kotlin/io/github/beomjo/search/usecase/RemoveBookmark.kt create mode 100644 domain/src/main/kotlin/io/github/beomjo/search/usecase/SetBookmark.kt create mode 100644 domain/src/test/java/io/github/beomjo/search/usecase/GetBookmarkListSpec.kt create mode 100644 domain/src/test/java/io/github/beomjo/search/usecase/GetBookmarkSpec.kt create mode 100644 domain/src/test/java/io/github/beomjo/search/usecase/RemoveBookmarkSpec.kt create mode 100644 domain/src/test/java/io/github/beomjo/search/usecase/SetFavoriteSpec.kt diff --git a/domain/src/main/kotlin/io/github/beomjo/search/repository/BookmarkRepository.kt b/domain/src/main/kotlin/io/github/beomjo/search/repository/BookmarkRepository.kt new file mode 100644 index 0000000..7011b3c --- /dev/null +++ b/domain/src/main/kotlin/io/github/beomjo/search/repository/BookmarkRepository.kt @@ -0,0 +1,14 @@ +package io.github.beomjo.search.repository + +import io.github.beomjo.search.entity.SearchDocument +import kotlinx.coroutines.flow.Flow + +interface BookmarkRepository { + suspend fun setBookmark(searchDocument: SearchDocument) + + suspend fun removeBookmark(searchDocument: SearchDocument) + + fun isBookmarked(searchDocument: SearchDocument): Flow + + fun getBookmarkList(): Flow> +} \ No newline at end of file diff --git a/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetBookmark.kt b/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetBookmark.kt new file mode 100644 index 0000000..ebd16fd --- /dev/null +++ b/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetBookmark.kt @@ -0,0 +1,31 @@ +/* + * Designed and developed by 2021 beomjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.github.beomjo.search.usecase + +import io.github.beomjo.search.entity.SearchDocument +import io.github.beomjo.search.repository.BookmarkRepository +import io.github.beomjo.search.usecase.base.FlowUseCase +import kotlinx.coroutines.flow.Flow +import javax.inject.Inject + +class GetBookmark @Inject constructor( + private val bookmarkRepository: BookmarkRepository +) : FlowUseCase() { + override fun execute(param: SearchDocument): Flow { + return bookmarkRepository.isBookmarked(param) + } +} \ No newline at end of file diff --git a/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetBookmarkList.kt b/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetBookmarkList.kt new file mode 100644 index 0000000..c7b08e6 --- /dev/null +++ b/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetBookmarkList.kt @@ -0,0 +1,32 @@ +/* + * Designed and developed by 2021 beomjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.github.beomjo.search.usecase + +import io.github.beomjo.search.entity.Empty +import io.github.beomjo.search.entity.SearchDocument +import io.github.beomjo.search.repository.BookmarkRepository +import io.github.beomjo.search.usecase.base.FlowUseCase +import kotlinx.coroutines.flow.Flow +import javax.inject.Inject + +class GetBookmarkList @Inject constructor( + private val bookmarkRepository: BookmarkRepository +) : FlowUseCase>() { + override fun execute(param: Empty): Flow> { + return bookmarkRepository.getBookmarkList() + } +} \ No newline at end of file diff --git a/domain/src/main/kotlin/io/github/beomjo/search/usecase/RemoveBookmark.kt b/domain/src/main/kotlin/io/github/beomjo/search/usecase/RemoveBookmark.kt new file mode 100644 index 0000000..37c8970 --- /dev/null +++ b/domain/src/main/kotlin/io/github/beomjo/search/usecase/RemoveBookmark.kt @@ -0,0 +1,30 @@ +/* + * Designed and developed by 2021 beomjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.github.beomjo.search.usecase + +import io.github.beomjo.search.entity.SearchDocument +import io.github.beomjo.search.repository.BookmarkRepository +import io.github.beomjo.search.usecase.base.UseCase +import javax.inject.Inject + +class RemoveBookmark @Inject constructor( + private val bookmarkRepository: BookmarkRepository +) : UseCase() { + override suspend fun execute(param: SearchDocument) { + bookmarkRepository.removeBookmark(param) + } +} \ No newline at end of file diff --git a/domain/src/main/kotlin/io/github/beomjo/search/usecase/SetBookmark.kt b/domain/src/main/kotlin/io/github/beomjo/search/usecase/SetBookmark.kt new file mode 100644 index 0000000..fdb980e --- /dev/null +++ b/domain/src/main/kotlin/io/github/beomjo/search/usecase/SetBookmark.kt @@ -0,0 +1,30 @@ +/* + * Designed and developed by 2021 beomjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.github.beomjo.search.usecase + +import io.github.beomjo.search.entity.SearchDocument +import io.github.beomjo.search.repository.BookmarkRepository +import io.github.beomjo.search.usecase.base.UseCase +import javax.inject.Inject + +class SetBookmark @Inject constructor( + private val bookmarkRepository: BookmarkRepository +) : UseCase() { + override suspend fun execute(param: SearchDocument) { + bookmarkRepository.setBookmark(param) + } +} \ No newline at end of file diff --git a/domain/src/test/java/io/github/beomjo/search/usecase/GetBookmarkListSpec.kt b/domain/src/test/java/io/github/beomjo/search/usecase/GetBookmarkListSpec.kt new file mode 100644 index 0000000..7153a93 --- /dev/null +++ b/domain/src/test/java/io/github/beomjo/search/usecase/GetBookmarkListSpec.kt @@ -0,0 +1,52 @@ +/* + * Designed and developed by 2021 beomjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.github.beomjo.search.usecase + +import io.github.beomjo.search.entity.Empty +import io.github.beomjo.search.entity.SearchDocument +import io.github.beomjo.search.repository.BookmarkRepository +import io.kotest.core.spec.style.BehaviorSpec +import io.kotest.matchers.shouldBe +import io.mockk.* +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.flowOf + +class GetBookmarkListSpec : BehaviorSpec() { + + private val bookmarkRepository = mockk() + + init { + Given("Given a Empty") { + val searchDocumentList = listOf(mockk(), mockk()) + val getBookmarkListUseCase = GetBookmarkList(bookmarkRepository) + every { bookmarkRepository.getBookmarkList() } returns flowOf(searchDocumentList) + + When("Call invoke") { + val bookmarkListFlow = getBookmarkListUseCase.invoke(Empty) + + Then("Should return a bookmark list flow") { + verify { bookmarkRepository.getBookmarkList() } + bookmarkListFlow.first() shouldBe searchDocumentList + } + } + } + + afterTest { + unmockkAll() + } + } +} \ No newline at end of file diff --git a/domain/src/test/java/io/github/beomjo/search/usecase/GetBookmarkSpec.kt b/domain/src/test/java/io/github/beomjo/search/usecase/GetBookmarkSpec.kt new file mode 100644 index 0000000..a892bf9 --- /dev/null +++ b/domain/src/test/java/io/github/beomjo/search/usecase/GetBookmarkSpec.kt @@ -0,0 +1,42 @@ +/* + * Designed and developed by 2021 beomjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.github.beomjo.search.usecase + +import io.github.beomjo.search.entity.SearchDocument +import io.github.beomjo.search.repository.BookmarkRepository +import io.kotest.core.spec.style.BehaviorSpec +import io.mockk.mockk + +class GetBookmarkSpec : BehaviorSpec() { + + private val bookmarkRepository = mockk() + + init { + Given("Given a searchDocument") { + val searchDocument = mockk() + val getBookmarkUseCase = GetBookmark(bookmarkRepository) + + When("Call invoke") { + getBookmarkUseCase.invoke(searchDocument) + + Then("Should return whether or not it has been bookmarked") { + + } + } + } + } +} \ No newline at end of file diff --git a/domain/src/test/java/io/github/beomjo/search/usecase/RemoveBookmarkSpec.kt b/domain/src/test/java/io/github/beomjo/search/usecase/RemoveBookmarkSpec.kt new file mode 100644 index 0000000..8821308 --- /dev/null +++ b/domain/src/test/java/io/github/beomjo/search/usecase/RemoveBookmarkSpec.kt @@ -0,0 +1,47 @@ +/* + * Designed and developed by 2021 beomjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.github.beomjo.search.usecase + +import io.github.beomjo.search.entity.SearchDocument +import io.github.beomjo.search.repository.BookmarkRepository +import io.kotest.core.spec.style.BehaviorSpec +import io.mockk.* + +class RemoveBookmarkSpec : BehaviorSpec() { + + private val bookmarkRepository = mockk() + + init { + Given("Given a searchDocument") { + val searchDocument = mockk() + val removeBookmarkUseCase = RemoveBookmark(bookmarkRepository) + coEvery { bookmarkRepository.removeBookmark(searchDocument) } just Runs + + When("Call invoke") { + removeBookmarkUseCase.invoke(searchDocument) + + Then("Should call removeBookmark to release the bookmark state.") { + coVerify { bookmarkRepository.removeBookmark(eq(searchDocument)) } + } + } + } + + afterTest { + unmockkAll() + } + } +} \ No newline at end of file diff --git a/domain/src/test/java/io/github/beomjo/search/usecase/SetFavoriteSpec.kt b/domain/src/test/java/io/github/beomjo/search/usecase/SetFavoriteSpec.kt new file mode 100644 index 0000000..c61cdc5 --- /dev/null +++ b/domain/src/test/java/io/github/beomjo/search/usecase/SetFavoriteSpec.kt @@ -0,0 +1,47 @@ +/* + * Designed and developed by 2021 beomjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.github.beomjo.search.usecase + +import io.github.beomjo.search.entity.SearchDocument +import io.github.beomjo.search.repository.BookmarkRepository +import io.kotest.core.spec.style.BehaviorSpec +import io.mockk.* + +class SetFavoriteSpec : BehaviorSpec() { + + private val bookmarkRepository = mockk() + + init { + Given("Given a searchDocument") { + val searchDocument = mockk() + val setBookmarkUseCase = SetBookmark(bookmarkRepository) + coEvery { bookmarkRepository.setBookmark(searchDocument) } just Runs + + When("Call invoke") { + setBookmarkUseCase.invoke(searchDocument) + + Then("Should call the setBookmark function to save whether you like it or not.") { + coVerify { bookmarkRepository.setBookmark(eq(searchDocument)) } + } + } + } + + afterTest { + unmockkAll() + } + } +} \ No newline at end of file From 73e1f13dac884b5e9f1f5c172372bc32bf93fe43 Mon Sep 17 00:00:00 2001 From: beomjo Date: Mon, 13 Sep 2021 00:07:27 +0900 Subject: [PATCH 253/273] feat: feat: Implementing local bookmarks in data moudle --- .../io/github/beomjo/search/DataModule.kt | 19 ++++++-- .../search/datasource/local/AppDatabase.kt | 14 ++++-- .../datasource/local/dao/BookmarkDao.kt | 41 +++++++++++++++++ .../datasource/local/table/BookmarkTable.kt | 42 ++++++++++++++++++ .../remote/api/paging/SearchRemoteMediator.kt | 4 +- .../search/mapper/SearchDocumentMapper.kt | 27 +++++++++++- .../mapper/SearchDocumentVisitMapper.kt | 2 +- .../search/mapper/SearchHistoryMapper.kt | 2 +- .../repository/BookmarkRepositoryImpl.kt | 44 +++++++++++++++++++ .../search/repository/SearchRepositoryImpl.kt | 6 +-- .../repository/SearchRepositoryImplSpec.kt | 6 +-- 11 files changed, 189 insertions(+), 18 deletions(-) create mode 100644 data/src/main/kotlin/io/github/beomjo/search/datasource/local/dao/BookmarkDao.kt create mode 100644 data/src/main/kotlin/io/github/beomjo/search/datasource/local/table/BookmarkTable.kt create mode 100644 data/src/main/kotlin/io/github/beomjo/search/repository/BookmarkRepositoryImpl.kt diff --git a/data/src/main/kotlin/io/github/beomjo/search/DataModule.kt b/data/src/main/kotlin/io/github/beomjo/search/DataModule.kt index d90b2a6..fc59d4b 100644 --- a/data/src/main/kotlin/io/github/beomjo/search/DataModule.kt +++ b/data/src/main/kotlin/io/github/beomjo/search/DataModule.kt @@ -24,13 +24,17 @@ import dagger.hilt.InstallIn import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent import io.github.beomjo.search.datasource.local.AppDatabase -import io.github.beomjo.search.datasource.local.dao.SearchDocumentDao +import io.github.beomjo.search.datasource.local.dao.* +import io.github.beomjo.search.datasource.local.dao.BookmarkDao import io.github.beomjo.search.datasource.local.dao.RemoteKeyDao -import io.github.beomjo.search.datasource.local.dao.SearchHistoryDao +import io.github.beomjo.search.datasource.local.dao.SearchDocumentDao import io.github.beomjo.search.datasource.local.dao.SearchDocumentVisitDao +import io.github.beomjo.search.datasource.local.dao.SearchHistoryDao import io.github.beomjo.search.datasource.remote.api.RetrofitAdapter import io.github.beomjo.search.datasource.remote.api.Urls import io.github.beomjo.search.datasource.remote.api.service.DocumentsApi +import io.github.beomjo.search.repository.BookmarkRepository +import io.github.beomjo.search.repository.BookmarkRepositoryImpl import io.github.beomjo.search.repository.SearchRepository import io.github.beomjo.search.repository.SearchRepositoryImpl import javax.inject.Singleton @@ -78,10 +82,19 @@ internal object DataModule { return database.searchDocumentVisitDao() } + @Singleton + @Provides + fun provideBookmarkDao(database: AppDatabase): BookmarkDao { + return database.bookmarkDao() + } + @Module @InstallIn(SingletonComponent::class) abstract class DataBindModule { @Binds - abstract fun provideDocumentRepository(repository: SearchRepositoryImpl): SearchRepository + abstract fun provideSearchRepository(repository: SearchRepositoryImpl): SearchRepository + + @Binds + abstract fun provideBookmarkRepository(repository: BookmarkRepositoryImpl): BookmarkRepository } } diff --git a/data/src/main/kotlin/io/github/beomjo/search/datasource/local/AppDatabase.kt b/data/src/main/kotlin/io/github/beomjo/search/datasource/local/AppDatabase.kt index 0998fd5..d8c971a 100644 --- a/data/src/main/kotlin/io/github/beomjo/search/datasource/local/AppDatabase.kt +++ b/data/src/main/kotlin/io/github/beomjo/search/datasource/local/AppDatabase.kt @@ -22,12 +22,15 @@ import androidx.room.Room import androidx.room.RoomDatabase import androidx.room.TypeConverters import io.github.beomjo.search.datasource.local.converter.DateConverter -import io.github.beomjo.search.datasource.local.dao.SearchDocumentDao +import io.github.beomjo.search.datasource.local.dao.* +import io.github.beomjo.search.datasource.local.dao.BookmarkDao import io.github.beomjo.search.datasource.local.dao.RemoteKeyDao -import io.github.beomjo.search.datasource.local.dao.SearchHistoryDao +import io.github.beomjo.search.datasource.local.dao.SearchDocumentDao import io.github.beomjo.search.datasource.local.dao.SearchDocumentVisitDao +import io.github.beomjo.search.datasource.local.dao.SearchHistoryDao +import io.github.beomjo.search.datasource.local.table.* +import io.github.beomjo.search.datasource.local.table.BookmarkTable import io.github.beomjo.search.datasource.local.table.SearchDocumentTable -import io.github.beomjo.search.datasource.local.table.RemoteKeyTable import io.github.beomjo.search.datasource.local.table.SearchHistoryTable import io.github.beomjo.search.datasource.local.table.VisitTable @@ -36,7 +39,8 @@ import io.github.beomjo.search.datasource.local.table.VisitTable SearchDocumentTable::class, RemoteKeyTable::class, SearchHistoryTable::class, - VisitTable::class + VisitTable::class, + BookmarkTable::class, ], version = 1, exportSchema = false @@ -52,6 +56,8 @@ internal abstract class AppDatabase : RoomDatabase() { abstract fun searchDocumentVisitDao(): SearchDocumentVisitDao + abstract fun bookmarkDao(): BookmarkDao + companion object { private const val NAME = "app_database" diff --git a/data/src/main/kotlin/io/github/beomjo/search/datasource/local/dao/BookmarkDao.kt b/data/src/main/kotlin/io/github/beomjo/search/datasource/local/dao/BookmarkDao.kt new file mode 100644 index 0000000..b9b385c --- /dev/null +++ b/data/src/main/kotlin/io/github/beomjo/search/datasource/local/dao/BookmarkDao.kt @@ -0,0 +1,41 @@ +/* + * Designed and developed by 2021 beomjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.github.beomjo.search.datasource.local.dao + +import androidx.paging.PagingSource +import androidx.room.Dao +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Query +import io.github.beomjo.search.datasource.local.table.BookmarkTable +import io.github.beomjo.search.datasource.local.table.SearchDocumentTable +import kotlinx.coroutines.flow.Flow + +@Dao +internal interface BookmarkDao { + @Insert(onConflict = OnConflictStrategy.REPLACE) + suspend fun insertBookmark(bookmark: BookmarkTable) + + @Query("DELETE FROM bookmark_table WHERE url == :url") + fun deleteBookmark(url: String) + + @Query("SELECT * FROM bookmark_table WHERE url == :url") + fun isBookmarked(url: String) : Flow + +// @Query("SELECT * FROM bookmark_table") +// fun getDocumentByDate(query: String): PagingSource +} diff --git a/data/src/main/kotlin/io/github/beomjo/search/datasource/local/table/BookmarkTable.kt b/data/src/main/kotlin/io/github/beomjo/search/datasource/local/table/BookmarkTable.kt new file mode 100644 index 0000000..7c5aff2 --- /dev/null +++ b/data/src/main/kotlin/io/github/beomjo/search/datasource/local/table/BookmarkTable.kt @@ -0,0 +1,42 @@ +/* + * Designed and developed by 2021 beomjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.github.beomjo.search.datasource.local.table + +import androidx.room.Entity +import androidx.room.PrimaryKey +import com.google.gson.annotations.SerializedName +import io.github.beomjo.search.entity.DocumentType +import java.util.* + +@Entity(tableName = "bookmark_table") +internal data class BookmarkTable( + @field:SerializedName("type") + val type: DocumentType, + @PrimaryKey + @field:SerializedName("url") + val url: String, + @field:SerializedName("thumbnail") + val thumbnail: String, + @field:SerializedName("title") + val title: String, + @field:SerializedName("content") + val content: String, + @field:SerializedName("date") + val writeDate: Date?, + @field:SerializedName("bookmark_date") + val bookmarkedDate: Date?, +) diff --git a/data/src/main/kotlin/io/github/beomjo/search/datasource/remote/api/paging/SearchRemoteMediator.kt b/data/src/main/kotlin/io/github/beomjo/search/datasource/remote/api/paging/SearchRemoteMediator.kt index 5c4d002..3405061 100644 --- a/data/src/main/kotlin/io/github/beomjo/search/datasource/remote/api/paging/SearchRemoteMediator.kt +++ b/data/src/main/kotlin/io/github/beomjo/search/datasource/remote/api/paging/SearchRemoteMediator.kt @@ -31,7 +31,7 @@ import io.github.beomjo.search.datasource.remote.api.service.DocumentsApi import io.github.beomjo.search.entity.SearchDocumentList import io.github.beomjo.search.entity.DocumentType import io.github.beomjo.search.mapper.toEntity -import io.github.beomjo.search.mapper.toTable +import io.github.beomjo.search.mapper.toDocumentTable import io.github.beomjo.search.usecase.SearchPagingParam import retrofit2.HttpException import java.io.IOException @@ -73,7 +73,7 @@ internal class SearchRemoteMediator @AssistedInject constructor( val nextKey = if (documentList.hasMore) position + 1 else null val keys = RemoteKeyTable(position = position, prevKey = prevKey, nextKey = nextKey) - database.documentDao().insertDocuments(documentList.searchDocuments.map { it.toTable() }) + database.documentDao().insertDocuments(documentList.searchDocuments.map { it.toDocumentTable() }) database.remoteKeyDao().insertKey(keys) } diff --git a/data/src/main/kotlin/io/github/beomjo/search/mapper/SearchDocumentMapper.kt b/data/src/main/kotlin/io/github/beomjo/search/mapper/SearchDocumentMapper.kt index 1803bb4..f5fbada 100644 --- a/data/src/main/kotlin/io/github/beomjo/search/mapper/SearchDocumentMapper.kt +++ b/data/src/main/kotlin/io/github/beomjo/search/mapper/SearchDocumentMapper.kt @@ -16,6 +16,7 @@ package io.github.beomjo.search.mapper +import io.github.beomjo.search.datasource.local.table.BookmarkTable import io.github.beomjo.search.datasource.local.table.SearchDocumentTable import io.github.beomjo.search.entity.SearchDocument import io.github.beomjo.search.entity.SearchDocumentList @@ -27,6 +28,7 @@ import io.github.beomjo.search.model.DocumentListResponse import io.github.beomjo.search.model.ImageResponse import io.github.beomjo.search.model.WebResponse import java.lang.IllegalStateException +import java.util.* internal fun DocumentListResponse.toEntity(): SearchDocumentList { return SearchDocumentList( @@ -89,7 +91,7 @@ internal fun BookResponse.toEntity(): SearchDocument = SearchDocument( date = datetime, ) -internal fun SearchDocument.toTable(): SearchDocumentTable { +internal fun SearchDocument.toDocumentTable(): SearchDocumentTable { return SearchDocumentTable( type = this.type, url = this.url, @@ -110,3 +112,26 @@ internal fun SearchDocumentTable.toEntity(): SearchDocument { date = this.date ) } + +internal fun SearchDocument.toBookmarkTable(): BookmarkTable { + return BookmarkTable( + type = this.type, + url = this.url, + thumbnail = this.thumbnail, + title = this.title, + content = this.content, + writeDate = this.date, + bookmarkedDate = Date() + ) +} + +internal fun BookmarkTable.toEntity(): SearchDocument { + return SearchDocument( + type = this.type, + url = this.url, + thumbnail = this.thumbnail, + title = this.title, + content = this.content, + date = this.writeDate + ) +} diff --git a/data/src/main/kotlin/io/github/beomjo/search/mapper/SearchDocumentVisitMapper.kt b/data/src/main/kotlin/io/github/beomjo/search/mapper/SearchDocumentVisitMapper.kt index b53653f..02371ab 100644 --- a/data/src/main/kotlin/io/github/beomjo/search/mapper/SearchDocumentVisitMapper.kt +++ b/data/src/main/kotlin/io/github/beomjo/search/mapper/SearchDocumentVisitMapper.kt @@ -10,7 +10,7 @@ internal fun VisitTable.toEntity(): Visit { ) } -internal fun Visit.toTable(): VisitTable { +internal fun Visit.toDocumentTable(): VisitTable { return VisitTable( url = url, date = date, diff --git a/data/src/main/kotlin/io/github/beomjo/search/mapper/SearchHistoryMapper.kt b/data/src/main/kotlin/io/github/beomjo/search/mapper/SearchHistoryMapper.kt index 7dd1de0..7e17ddd 100644 --- a/data/src/main/kotlin/io/github/beomjo/search/mapper/SearchHistoryMapper.kt +++ b/data/src/main/kotlin/io/github/beomjo/search/mapper/SearchHistoryMapper.kt @@ -25,7 +25,7 @@ internal fun SearchHistoryTable.toEntity(): History { ) } -internal fun History.toTable(): SearchHistoryTable { +internal fun History.toDocumentTable(): SearchHistoryTable { return SearchHistoryTable( query = query, date = date diff --git a/data/src/main/kotlin/io/github/beomjo/search/repository/BookmarkRepositoryImpl.kt b/data/src/main/kotlin/io/github/beomjo/search/repository/BookmarkRepositoryImpl.kt new file mode 100644 index 0000000..de0093b --- /dev/null +++ b/data/src/main/kotlin/io/github/beomjo/search/repository/BookmarkRepositoryImpl.kt @@ -0,0 +1,44 @@ +/* + * Designed and developed by 2021 beomjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.github.beomjo.search.repository + +import io.github.beomjo.search.datasource.local.dao.BookmarkDao +import io.github.beomjo.search.entity.SearchDocument +import io.github.beomjo.search.mapper.toBookmarkTable +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map +import javax.inject.Inject + +internal class BookmarkRepositoryImpl @Inject constructor( + private val bookmarkDao: BookmarkDao +) : BookmarkRepository { + override suspend fun setBookmark(searchDocument: SearchDocument) { + bookmarkDao.insertBookmark(searchDocument.toBookmarkTable()) + } + + override suspend fun removeBookmark(searchDocument: SearchDocument) { + bookmarkDao.deleteBookmark(searchDocument.url) + } + + override fun isBookmarked(searchDocument: SearchDocument): Flow { + return bookmarkDao.isBookmarked(searchDocument.url).map { it?.url != null } + } + + override fun getBookmarkList(): Flow> { + TODO("Not yet implemented") + } +} \ No newline at end of file diff --git a/data/src/main/kotlin/io/github/beomjo/search/repository/SearchRepositoryImpl.kt b/data/src/main/kotlin/io/github/beomjo/search/repository/SearchRepositoryImpl.kt index a8836f0..4fcca47 100644 --- a/data/src/main/kotlin/io/github/beomjo/search/repository/SearchRepositoryImpl.kt +++ b/data/src/main/kotlin/io/github/beomjo/search/repository/SearchRepositoryImpl.kt @@ -31,7 +31,7 @@ import io.github.beomjo.search.entity.History import io.github.beomjo.search.entity.SortType import io.github.beomjo.search.entity.Visit import io.github.beomjo.search.mapper.toEntity -import io.github.beomjo.search.mapper.toTable +import io.github.beomjo.search.mapper.toDocumentTable import io.github.beomjo.search.usecase.SearchPagingParam import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map @@ -66,7 +66,7 @@ internal class SearchRepositoryImpl @Inject constructor( } override suspend fun insertSearchHistory(history: History) { - return searchHistoryDao.insertHistory(history.toTable()) + return searchHistoryDao.insertHistory(history.toDocumentTable()) } override fun getSearchHistoryList(): Flow> { @@ -76,7 +76,7 @@ internal class SearchRepositoryImpl @Inject constructor( } override suspend fun insertVisit(visit: Visit) { - searchDocumentVisitDao.insertVisit(visit = visit.toTable()) + searchDocumentVisitDao.insertVisit(visit = visit.toDocumentTable()) } override fun getVisit(url: String): Flow { diff --git a/data/src/test/java/io/github/beomjo/search/repository/SearchRepositoryImplSpec.kt b/data/src/test/java/io/github/beomjo/search/repository/SearchRepositoryImplSpec.kt index 55437ce..e8cd434 100644 --- a/data/src/test/java/io/github/beomjo/search/repository/SearchRepositoryImplSpec.kt +++ b/data/src/test/java/io/github/beomjo/search/repository/SearchRepositoryImplSpec.kt @@ -29,7 +29,7 @@ import io.github.beomjo.search.datasource.remote.api.paging.SearchRemoteMediator import io.github.beomjo.search.datasource.remote.api.paging.SearchRemoteMediatorFactory import io.github.beomjo.search.entity.* import io.github.beomjo.search.mapper.toEntity -import io.github.beomjo.search.mapper.toTable +import io.github.beomjo.search.mapper.toDocumentTable import io.github.beomjo.search.usecase.SearchPagingParam import io.kotest.core.spec.style.BehaviorSpec import io.kotest.matchers.shouldBe @@ -134,7 +134,7 @@ internal class SearchRepositoryImplSpec : BehaviorSpec() { searchRepositoryImpl.insertSearchHistory(history) Then("Should be stored in DB") { - coVerify { searchHistoryDao.insertHistory(eq(history.toTable())) } + coVerify { searchHistoryDao.insertHistory(eq(history.toDocumentTable())) } } } } @@ -183,7 +183,7 @@ internal class SearchRepositoryImplSpec : BehaviorSpec() { searchRepositoryImpl.insertVisit(visit) Then("Should be stored in DB") { - coVerify { searchDocumentVisitDao.insertVisit(eq(visit.toTable())) } + coVerify { searchDocumentVisitDao.insertVisit(eq(visit.toDocumentTable())) } } } } From aaa6b9512497338ce3effd73d8edb47b35e4af5a Mon Sep 17 00:00:00 2001 From: beomjo Date: Tue, 14 Sep 2021 00:28:17 +0900 Subject: [PATCH 254/273] test: Write BookmarkRepositoryImpl Test --- .../repository/BookmarkRepositoryImplSpec.kt | 128 ++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 data/src/test/java/io/github/beomjo/search/repository/BookmarkRepositoryImplSpec.kt diff --git a/data/src/test/java/io/github/beomjo/search/repository/BookmarkRepositoryImplSpec.kt b/data/src/test/java/io/github/beomjo/search/repository/BookmarkRepositoryImplSpec.kt new file mode 100644 index 0000000..b0740c7 --- /dev/null +++ b/data/src/test/java/io/github/beomjo/search/repository/BookmarkRepositoryImplSpec.kt @@ -0,0 +1,128 @@ +/* + * Designed and developed by 2021 beomjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.github.beomjo.search.repository + +import io.github.beomjo.search.datasource.local.dao.BookmarkDao +import io.github.beomjo.search.datasource.local.table.BookmarkTable +import io.github.beomjo.search.entity.DocumentType +import io.github.beomjo.search.entity.SearchDocument +import io.github.beomjo.search.mapper.toBookmarkTable +import io.kotest.core.spec.style.BehaviorSpec +import io.kotest.matchers.shouldBe +import io.mockk.* +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.flowOf + +class BookmarkRepositoryImplSpec : BehaviorSpec() { + + private val bookmarkDao = mockk(relaxed = true) + + init { + Given("Given a SearchDocument for insertBookmark") { + val searchDocument = SearchDocument( + type = DocumentType.ALL, + url = "http://", + thumbnail = "http://..", + title = "title", + content = "content", + date = mockk() + ) + + val repositoryImpl = BookmarkRepositoryImpl(bookmarkDao) + + val slot = slot() + coEvery { bookmarkDao.insertBookmark(capture(slot)) } just Runs + + When("insert bookmark") { + repositoryImpl.setBookmark(searchDocument) + + Then("Should convert SearchDocument to table and store it in db") { + coVerify { bookmarkDao.insertBookmark(any()) } + searchDocument.toBookmarkTable().url shouldBe slot.captured.url + searchDocument.toBookmarkTable().type shouldBe slot.captured.type + searchDocument.toBookmarkTable().thumbnail shouldBe slot.captured.thumbnail + searchDocument.toBookmarkTable().title shouldBe slot.captured.title + searchDocument.toBookmarkTable().content shouldBe slot.captured.content + searchDocument.toBookmarkTable().writeDate shouldBe slot.captured.writeDate + } + } + } + + Given("Given a SearchDocument for deleteBookmark") { + val searchDocument = SearchDocument( + type = DocumentType.ALL, + url = "http://", + thumbnail = "http://..", + title = "title", + content = "content", + date = mockk() + ) + + val repositoryImpl = BookmarkRepositoryImpl(bookmarkDao) + + When("delete bookmark") { + repositoryImpl.removeBookmark(searchDocument) + + Then("Should delete SearchDocumentTable from db") { + coVerify { bookmarkDao.deleteBookmark(eq(searchDocument.url)) } + } + } + } + + Given("Given a SearchDocument for isBookmark") { + val searchDocument = SearchDocument( + type = DocumentType.ALL, + url = "http://", + thumbnail = "http://..", + title = "title", + content = "content", + date = mockk() + ) + + val repositoryImpl = BookmarkRepositoryImpl(bookmarkDao) + + When("delete bookmark") { + + And("It is saved as a bookmark in the DB") { + every { bookmarkDao.isBookmarked(searchDocument.url) } returns flowOf(searchDocument.toBookmarkTable()) + + val result = repositoryImpl.isBookmarked(searchDocument) + + Then("Should return bookmarked") { + verify { bookmarkDao.isBookmarked(eq(searchDocument.url)) } + result.first() shouldBe true + } + } + + And("It is not saved as a bookmark in the DB") { + every { bookmarkDao.isBookmarked(searchDocument.url) } returns flowOf(null) + + val result = repositoryImpl.isBookmarked(searchDocument) + + Then("Should return bookmarked") { + verify { bookmarkDao.isBookmarked(eq(searchDocument.url)) } + result.first() shouldBe false + } + } + } + } + + afterTest { + unmockkAll() + } + } +} \ No newline at end of file From d7a4619ae2c95bc4c67a67193d3e80e0d0d4df9b Mon Sep 17 00:00:00 2001 From: beomjo Date: Tue, 14 Sep 2021 05:10:18 +0900 Subject: [PATCH 255/273] feat: Implement BookmarkDataSource and BookmarkRepository --- .../datasource/local/dao/BookmarkDao.kt | 10 +- .../remote/api/paging/BookmarkPagingSource.kt | 51 +++++++ .../repository/BookmarkRepositoryImpl.kt | 16 ++- .../local/BookmarkPagingSourceSpec.kt | 132 ++++++++++++++++++ .../repository/BookmarkRepositoryImplSpec.kt | 27 +++- .../search/repository/BookmarkRepository.kt | 3 +- ...okmarkList.kt => GetBookmarkPagingData.kt} | 8 +- ...stSpec.kt => GetBookmarkPagingDataSpec.kt} | 12 +- 8 files changed, 237 insertions(+), 22 deletions(-) create mode 100644 data/src/main/kotlin/io/github/beomjo/search/datasource/remote/api/paging/BookmarkPagingSource.kt create mode 100644 data/src/test/java/io/github/beomjo/search/datasource/local/BookmarkPagingSourceSpec.kt rename domain/src/main/kotlin/io/github/beomjo/search/usecase/{GetBookmarkList.kt => GetBookmarkPagingData.kt} (79%) rename domain/src/test/java/io/github/beomjo/search/usecase/{GetBookmarkListSpec.kt => GetBookmarkPagingDataSpec.kt} (78%) diff --git a/data/src/main/kotlin/io/github/beomjo/search/datasource/local/dao/BookmarkDao.kt b/data/src/main/kotlin/io/github/beomjo/search/datasource/local/dao/BookmarkDao.kt index b9b385c..100176a 100644 --- a/data/src/main/kotlin/io/github/beomjo/search/datasource/local/dao/BookmarkDao.kt +++ b/data/src/main/kotlin/io/github/beomjo/search/datasource/local/dao/BookmarkDao.kt @@ -16,13 +16,11 @@ package io.github.beomjo.search.datasource.local.dao -import androidx.paging.PagingSource import androidx.room.Dao import androidx.room.Insert import androidx.room.OnConflictStrategy import androidx.room.Query import io.github.beomjo.search.datasource.local.table.BookmarkTable -import io.github.beomjo.search.datasource.local.table.SearchDocumentTable import kotlinx.coroutines.flow.Flow @Dao @@ -31,11 +29,11 @@ internal interface BookmarkDao { suspend fun insertBookmark(bookmark: BookmarkTable) @Query("DELETE FROM bookmark_table WHERE url == :url") - fun deleteBookmark(url: String) + suspend fun deleteBookmark(url: String) @Query("SELECT * FROM bookmark_table WHERE url == :url") - fun isBookmarked(url: String) : Flow + fun isBookmarked(url: String): Flow -// @Query("SELECT * FROM bookmark_table") -// fun getDocumentByDate(query: String): PagingSource + @Query("SELECT * FROM bookmark_table ORDER BY bookmarkedDate DESC LIMIT :limit OFFSET :offset") + suspend fun getBookmarks(offset: Int, limit: Int): List } diff --git a/data/src/main/kotlin/io/github/beomjo/search/datasource/remote/api/paging/BookmarkPagingSource.kt b/data/src/main/kotlin/io/github/beomjo/search/datasource/remote/api/paging/BookmarkPagingSource.kt new file mode 100644 index 0000000..2f60cab --- /dev/null +++ b/data/src/main/kotlin/io/github/beomjo/search/datasource/remote/api/paging/BookmarkPagingSource.kt @@ -0,0 +1,51 @@ +/* + * Designed and developed by 2021 beomjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.github.beomjo.search.datasource.remote.api.paging + +import androidx.paging.PagingSource +import androidx.paging.PagingState +import io.github.beomjo.search.datasource.local.dao.BookmarkDao +import io.github.beomjo.search.entity.SearchDocument +import io.github.beomjo.search.mapper.toEntity +import javax.inject.Inject + +internal class BookmarkPagingSource @Inject constructor( + private val bookmarkDao: BookmarkDao, +) : PagingSource() { + override suspend fun load(params: LoadParams): LoadResult { + return try { + val offset = params.key ?: DEFAULT_OFFSET + val bookmarkList = bookmarkDao.getBookmarks(offset = offset, limit = LIMIT) + LoadResult.Page( + data = bookmarkList.map { it.toEntity() }, + prevKey = null, + nextKey = if (bookmarkList.isEmpty() || bookmarkList.size < LIMIT) null else offset + LIMIT + ) + } catch (e: Exception) { + LoadResult.Error(e) + } + } + + override fun getRefreshKey(state: PagingState): Int? { + return null + } + + companion object { + const val DEFAULT_OFFSET = 0 + const val LIMIT = 10 + } +} \ No newline at end of file diff --git a/data/src/main/kotlin/io/github/beomjo/search/repository/BookmarkRepositoryImpl.kt b/data/src/main/kotlin/io/github/beomjo/search/repository/BookmarkRepositoryImpl.kt index de0093b..799d129 100644 --- a/data/src/main/kotlin/io/github/beomjo/search/repository/BookmarkRepositoryImpl.kt +++ b/data/src/main/kotlin/io/github/beomjo/search/repository/BookmarkRepositoryImpl.kt @@ -16,7 +16,11 @@ package io.github.beomjo.search.repository +import androidx.paging.Pager +import androidx.paging.PagingConfig +import androidx.paging.PagingData import io.github.beomjo.search.datasource.local.dao.BookmarkDao +import io.github.beomjo.search.datasource.remote.api.paging.BookmarkPagingSource import io.github.beomjo.search.entity.SearchDocument import io.github.beomjo.search.mapper.toBookmarkTable import kotlinx.coroutines.flow.Flow @@ -24,7 +28,8 @@ import kotlinx.coroutines.flow.map import javax.inject.Inject internal class BookmarkRepositoryImpl @Inject constructor( - private val bookmarkDao: BookmarkDao + private val bookmarkDao: BookmarkDao, + private val bookmarkPagingSource: BookmarkPagingSource ) : BookmarkRepository { override suspend fun setBookmark(searchDocument: SearchDocument) { bookmarkDao.insertBookmark(searchDocument.toBookmarkTable()) @@ -38,7 +43,12 @@ internal class BookmarkRepositoryImpl @Inject constructor( return bookmarkDao.isBookmarked(searchDocument.url).map { it?.url != null } } - override fun getBookmarkList(): Flow> { - TODO("Not yet implemented") + override fun getBookmarkList(): Flow> { + return Pager( + config = PagingConfig( + pageSize = BookmarkPagingSource.LIMIT, + enablePlaceholders = false + ) + ) { bookmarkPagingSource }.flow } } \ No newline at end of file diff --git a/data/src/test/java/io/github/beomjo/search/datasource/local/BookmarkPagingSourceSpec.kt b/data/src/test/java/io/github/beomjo/search/datasource/local/BookmarkPagingSourceSpec.kt new file mode 100644 index 0000000..2089a0e --- /dev/null +++ b/data/src/test/java/io/github/beomjo/search/datasource/local/BookmarkPagingSourceSpec.kt @@ -0,0 +1,132 @@ +/* + * Designed and developed by 2021 beomjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.github.beomjo.search.datasource.local + +import androidx.paging.PagingSource +import io.github.beomjo.search.datasource.local.dao.BookmarkDao +import io.github.beomjo.search.datasource.local.table.BookmarkTable +import io.github.beomjo.search.datasource.remote.api.paging.BookmarkPagingSource +import io.github.beomjo.search.entity.SearchDocument +import io.github.beomjo.search.mapper.toEntity +import io.kotest.core.spec.style.BehaviorSpec +import io.kotest.matchers.shouldBe +import io.kotest.matchers.types.shouldBeTypeOf +import io.mockk.coEvery +import io.mockk.coVerify +import io.mockk.every +import io.mockk.mockk + +class BookmarkPagingSourceSpec : BehaviorSpec() { + + private val bookmarkDao = mockk() + + init { + Given("LoadPram's key is not given") { + val loadParam = mockk> { + every { key } returns null + } + val bookmarkList = listOf(mockk(relaxed = true)) + coEvery { + bookmarkDao.getBookmarks( + BookmarkPagingSource.DEFAULT_OFFSET, + BookmarkPagingSource.LIMIT + ) + } returns bookmarkList + + val pagingSource = BookmarkPagingSource(bookmarkDao) + + When("Call load") { + val result = pagingSource.load(loadParam) + + Then("Should load the bookmark list from the database with the default key offset.") { + coVerify { + bookmarkDao.getBookmarks( + eq(BookmarkPagingSource.DEFAULT_OFFSET), + eq(BookmarkPagingSource.LIMIT) + ) + } + result.shouldBeTypeOf>() + result.data shouldBe bookmarkList.map { it.toEntity() } + result.nextKey shouldBe null + } + } + } + + Given("LoadPram's key is given") { + val beforeOffset = 10 + val loadParam = mockk> { + every { key } returns beforeOffset + } + val bookmarkList = (0 until 10).map { mockk(relaxed = true) }.toList() + coEvery { + bookmarkDao.getBookmarks( + beforeOffset, + BookmarkPagingSource.LIMIT + ) + } returns bookmarkList + + val pagingSource = BookmarkPagingSource(bookmarkDao) + + When("Call load") { + val result = pagingSource.load(loadParam) + + Then("Should load the bookmark list from the database with offset.") { + coVerify { + bookmarkDao.getBookmarks( + eq(beforeOffset), + eq(BookmarkPagingSource.LIMIT) + ) + } + result.shouldBeTypeOf>() + result.data shouldBe bookmarkList.map { it.toEntity() } + result.nextKey shouldBe beforeOffset + BookmarkPagingSource.LIMIT + } + } + } + + Given("LoadPram's key is given and bookmarks error") { + val beforeOffset = 10 + val loadParam = mockk> { + every { key } returns beforeOffset + } + val exception = Exception() + coEvery { + bookmarkDao.getBookmarks( + beforeOffset, + BookmarkPagingSource.LIMIT + ) + } throws exception + + val pagingSource = BookmarkPagingSource(bookmarkDao) + + When("Call load") { + val result = pagingSource.load(loadParam) + + Then("LoadResult should be an error") { + coVerify { + bookmarkDao.getBookmarks( + eq(beforeOffset), + eq(BookmarkPagingSource.LIMIT) + ) + } + result.shouldBeTypeOf>() + result.throwable shouldBe exception + } + } + } + } +} \ No newline at end of file diff --git a/data/src/test/java/io/github/beomjo/search/repository/BookmarkRepositoryImplSpec.kt b/data/src/test/java/io/github/beomjo/search/repository/BookmarkRepositoryImplSpec.kt index b0740c7..6ebc1b2 100644 --- a/data/src/test/java/io/github/beomjo/search/repository/BookmarkRepositoryImplSpec.kt +++ b/data/src/test/java/io/github/beomjo/search/repository/BookmarkRepositoryImplSpec.kt @@ -16,13 +16,16 @@ package io.github.beomjo.search.repository +import androidx.paging.PagingData import io.github.beomjo.search.datasource.local.dao.BookmarkDao import io.github.beomjo.search.datasource.local.table.BookmarkTable +import io.github.beomjo.search.datasource.remote.api.paging.BookmarkPagingSource import io.github.beomjo.search.entity.DocumentType import io.github.beomjo.search.entity.SearchDocument import io.github.beomjo.search.mapper.toBookmarkTable import io.kotest.core.spec.style.BehaviorSpec import io.kotest.matchers.shouldBe +import io.kotest.matchers.types.shouldBeTypeOf import io.mockk.* import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.flowOf @@ -31,6 +34,8 @@ class BookmarkRepositoryImplSpec : BehaviorSpec() { private val bookmarkDao = mockk(relaxed = true) + private val bookmarkPagingSource = mockk(relaxed = true) + init { Given("Given a SearchDocument for insertBookmark") { val searchDocument = SearchDocument( @@ -42,7 +47,7 @@ class BookmarkRepositoryImplSpec : BehaviorSpec() { date = mockk() ) - val repositoryImpl = BookmarkRepositoryImpl(bookmarkDao) + val repositoryImpl = BookmarkRepositoryImpl(bookmarkDao, bookmarkPagingSource) val slot = slot() coEvery { bookmarkDao.insertBookmark(capture(slot)) } just Runs @@ -72,7 +77,7 @@ class BookmarkRepositoryImplSpec : BehaviorSpec() { date = mockk() ) - val repositoryImpl = BookmarkRepositoryImpl(bookmarkDao) + val repositoryImpl = BookmarkRepositoryImpl(bookmarkDao, bookmarkPagingSource) When("delete bookmark") { repositoryImpl.removeBookmark(searchDocument) @@ -93,12 +98,14 @@ class BookmarkRepositoryImplSpec : BehaviorSpec() { date = mockk() ) - val repositoryImpl = BookmarkRepositoryImpl(bookmarkDao) + val repositoryImpl = BookmarkRepositoryImpl(bookmarkDao, bookmarkPagingSource) When("delete bookmark") { And("It is saved as a bookmark in the DB") { - every { bookmarkDao.isBookmarked(searchDocument.url) } returns flowOf(searchDocument.toBookmarkTable()) + every { bookmarkDao.isBookmarked(searchDocument.url) } returns flowOf( + searchDocument.toBookmarkTable() + ) val result = repositoryImpl.isBookmarked(searchDocument) @@ -121,6 +128,18 @@ class BookmarkRepositoryImplSpec : BehaviorSpec() { } } + Given("Given a bookmarkPagingSource") { + val repositoryImpl = BookmarkRepositoryImpl(bookmarkDao, bookmarkPagingSource) + + When("Call getBookmarkList") { + val result = repositoryImpl.getBookmarkList() + + Then("Should return PagingData flow") { + result.first().shouldBeTypeOf>() + } + } + } + afterTest { unmockkAll() } diff --git a/domain/src/main/kotlin/io/github/beomjo/search/repository/BookmarkRepository.kt b/domain/src/main/kotlin/io/github/beomjo/search/repository/BookmarkRepository.kt index 7011b3c..b668b92 100644 --- a/domain/src/main/kotlin/io/github/beomjo/search/repository/BookmarkRepository.kt +++ b/domain/src/main/kotlin/io/github/beomjo/search/repository/BookmarkRepository.kt @@ -1,5 +1,6 @@ package io.github.beomjo.search.repository +import androidx.paging.PagingData import io.github.beomjo.search.entity.SearchDocument import kotlinx.coroutines.flow.Flow @@ -10,5 +11,5 @@ interface BookmarkRepository { fun isBookmarked(searchDocument: SearchDocument): Flow - fun getBookmarkList(): Flow> + fun getBookmarkList(): Flow> } \ No newline at end of file diff --git a/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetBookmarkList.kt b/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetBookmarkPagingData.kt similarity index 79% rename from domain/src/main/kotlin/io/github/beomjo/search/usecase/GetBookmarkList.kt rename to domain/src/main/kotlin/io/github/beomjo/search/usecase/GetBookmarkPagingData.kt index c7b08e6..51855cd 100644 --- a/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetBookmarkList.kt +++ b/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetBookmarkPagingData.kt @@ -16,17 +16,19 @@ package io.github.beomjo.search.usecase +import androidx.paging.PagingData import io.github.beomjo.search.entity.Empty import io.github.beomjo.search.entity.SearchDocument import io.github.beomjo.search.repository.BookmarkRepository import io.github.beomjo.search.usecase.base.FlowUseCase +import io.github.beomjo.search.usecase.base.PagingUseCase import kotlinx.coroutines.flow.Flow import javax.inject.Inject -class GetBookmarkList @Inject constructor( +class GetBookmarkPagingData @Inject constructor( private val bookmarkRepository: BookmarkRepository -) : FlowUseCase>() { - override fun execute(param: Empty): Flow> { +) : PagingUseCase() { + override fun execute(param: Empty): Flow> { return bookmarkRepository.getBookmarkList() } } \ No newline at end of file diff --git a/domain/src/test/java/io/github/beomjo/search/usecase/GetBookmarkListSpec.kt b/domain/src/test/java/io/github/beomjo/search/usecase/GetBookmarkPagingDataSpec.kt similarity index 78% rename from domain/src/test/java/io/github/beomjo/search/usecase/GetBookmarkListSpec.kt rename to domain/src/test/java/io/github/beomjo/search/usecase/GetBookmarkPagingDataSpec.kt index 7153a93..66c5977 100644 --- a/domain/src/test/java/io/github/beomjo/search/usecase/GetBookmarkListSpec.kt +++ b/domain/src/test/java/io/github/beomjo/search/usecase/GetBookmarkPagingDataSpec.kt @@ -16,6 +16,7 @@ package io.github.beomjo.search.usecase +import androidx.paging.PagingData import io.github.beomjo.search.entity.Empty import io.github.beomjo.search.entity.SearchDocument import io.github.beomjo.search.repository.BookmarkRepository @@ -25,22 +26,23 @@ import io.mockk.* import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.flowOf -class GetBookmarkListSpec : BehaviorSpec() { +class GetBookmarkPagingDataSpec : BehaviorSpec() { private val bookmarkRepository = mockk() init { Given("Given a Empty") { val searchDocumentList = listOf(mockk(), mockk()) - val getBookmarkListUseCase = GetBookmarkList(bookmarkRepository) - every { bookmarkRepository.getBookmarkList() } returns flowOf(searchDocumentList) + val pagingData = PagingData.from(searchDocumentList) + val getBookmarkPagingDataUseCase = GetBookmarkPagingData(bookmarkRepository) + every { bookmarkRepository.getBookmarkList() } returns flowOf(pagingData) When("Call invoke") { - val bookmarkListFlow = getBookmarkListUseCase.invoke(Empty) + val bookmarkListFlow = getBookmarkPagingDataUseCase.invoke(Empty) Then("Should return a bookmark list flow") { + bookmarkListFlow.first() shouldBe pagingData verify { bookmarkRepository.getBookmarkList() } - bookmarkListFlow.first() shouldBe searchDocumentList } } } From 4150ed1e00d9ffd6f158fd847abb2a740557b802 Mon Sep 17 00:00:00 2001 From: beomjo Date: Wed, 15 Sep 2021 20:26:48 +0900 Subject: [PATCH 256/273] feat: Modifying.. --- .../ui/adapter/BookmarkPagingAdapter.kt | 68 +++++++++++++++++++ .../search/ui/adapter/SearchPagingAdapter.kt | 4 +- .../ui/adapter/diff/DocumentDiffUtil.kt | 37 +++------- .../ui/adapter/diff/SearchUiItemDiffUtil.kt | 43 ++++++++++++ 4 files changed, 121 insertions(+), 31 deletions(-) create mode 100644 app/src/main/kotlin/io/github/beomjo/search/ui/adapter/BookmarkPagingAdapter.kt create mode 100644 app/src/main/kotlin/io/github/beomjo/search/ui/adapter/diff/SearchUiItemDiffUtil.kt diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/BookmarkPagingAdapter.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/BookmarkPagingAdapter.kt new file mode 100644 index 0000000..5ea5dd7 --- /dev/null +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/BookmarkPagingAdapter.kt @@ -0,0 +1,68 @@ +/* + * Designed and developed by 2021 beomjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.github.beomjo.search.ui.adapter + +import android.view.ViewGroup +import androidx.lifecycle.LifecycleOwner +import androidx.paging.PagingDataAdapter +import androidx.recyclerview.widget.RecyclerView +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject +import io.github.beomjo.search.R +import io.github.beomjo.search.entity.SearchDocument +import io.github.beomjo.search.ui.adapter.diff.SearchDocumentDiffUtil +import io.github.beomjo.search.ui.adapter.diff.SearchUiItemDiffUtil +import io.github.beomjo.search.ui.adapter.viewholders.SearchDocumentViewHolder +import io.github.beomjo.search.ui.adapter.viewholders.SearchSeparatorViewHolder +import io.github.beomjo.search.ui.viewmodels.SearchDocumentViewModelFactory +import io.github.beomjo.search.ui.viewmodels.SearchViewModel +import javax.inject.Provider + +class BookmarkPagingAdapter @AssistedInject constructor( + @Assisted + private val lifeCycleOwner: LifecycleOwner, + @Assisted + private val onClickItem: (SearchDocument) -> Unit, + private val factory: BookmarkPagingAdapterFactory +) : PagingDataAdapter(SearchDocumentDiffUtil()) { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { + return when (viewType) { + R.layout.search_list_document_item -> SearchDocumentViewHolder.create(parent) + else -> SearchSeparatorViewHolder.create(parent) + } + } + + override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { + getItem(position)?.let { + (holder as SearchDocumentViewHolder).bind( + lifeCycleOwner, + factory.create(it), + onClickItem + ) + } + } +} + +@AssistedFactory +interface BookmarkPagingAdapterFactory { + fun create( + lifeCycleOwner: LifecycleOwner, + onClickItem: (SearchDocument) -> Unit + ): BookmarkPagingAdapter +} \ No newline at end of file diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/SearchPagingAdapter.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/SearchPagingAdapter.kt index ac40743..a9c364d 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/SearchPagingAdapter.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/SearchPagingAdapter.kt @@ -25,7 +25,7 @@ import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject import io.github.beomjo.search.R import io.github.beomjo.search.entity.SearchDocument -import io.github.beomjo.search.ui.adapter.diff.DocumentDiffUtil +import io.github.beomjo.search.ui.adapter.diff.SearchUiItemDiffUtil import io.github.beomjo.search.ui.adapter.viewholders.SearchDocumentViewHolder import io.github.beomjo.search.ui.adapter.viewholders.SearchSeparatorViewHolder import io.github.beomjo.search.ui.viewmodels.SearchDocumentViewModelFactory @@ -36,7 +36,7 @@ class SearchPagingAdapter @AssistedInject constructor( @Assisted private val lifeCycleOwner: LifecycleOwner, @Assisted private val onClickItem: (SearchDocument) -> Unit, private val searchDocumentViewModelProvider: Provider -) : PagingDataAdapter(DocumentDiffUtil()) { +) : PagingDataAdapter(SearchUiItemDiffUtil()) { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { return when (viewType) { diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/diff/DocumentDiffUtil.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/diff/DocumentDiffUtil.kt index 7c08b31..0163348 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/diff/DocumentDiffUtil.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/diff/DocumentDiffUtil.kt @@ -1,42 +1,21 @@ -/* - * Designed and developed by 2021 beomjo - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package io.github.beomjo.search.ui.adapter.diff import androidx.recyclerview.widget.DiffUtil -import io.github.beomjo.search.ui.viewmodels.SearchViewModel.SearchUiItem +import io.github.beomjo.search.entity.SearchDocument -class DocumentDiffUtil : DiffUtil.ItemCallback() { +class SearchDocumentDiffUtil : DiffUtil.ItemCallback() { override fun areItemsTheSame( - oldItem: SearchUiItem, - newItem: SearchUiItem + oldItem: SearchDocument, + newItem: SearchDocument ): Boolean { - val isSameDocumentItem = - oldItem is SearchUiItem.DocumentItem && newItem is SearchUiItem.DocumentItem && - oldItem.searchDocument.title == newItem.searchDocument.title && - oldItem.searchDocument.date == newItem.searchDocument.date - val isSameSeparatorItem = - oldItem is SearchUiItem.SeparatorItem && newItem is SearchUiItem.SeparatorItem && - oldItem.description == newItem.description + val isSameDocumentItem = oldItem.title == newItem.title && oldItem.date == newItem.date + val isSameSeparatorItem = oldItem == newItem return isSameDocumentItem || isSameSeparatorItem } override fun areContentsTheSame( - oldItem: SearchUiItem, - newItem: SearchUiItem + oldItem: SearchDocument, + newItem: SearchDocument ): Boolean { return oldItem.hashCode() == newItem.hashCode() } diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/diff/SearchUiItemDiffUtil.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/diff/SearchUiItemDiffUtil.kt new file mode 100644 index 0000000..1cabde7 --- /dev/null +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/diff/SearchUiItemDiffUtil.kt @@ -0,0 +1,43 @@ +/* + * Designed and developed by 2021 beomjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.github.beomjo.search.ui.adapter.diff + +import androidx.recyclerview.widget.DiffUtil +import io.github.beomjo.search.ui.viewmodels.SearchViewModel.SearchUiItem + +class SearchUiItemDiffUtil : DiffUtil.ItemCallback() { + override fun areItemsTheSame( + oldItem: SearchUiItem, + newItem: SearchUiItem + ): Boolean { + val isSameDocumentItem = + oldItem is SearchUiItem.DocumentItem && newItem is SearchUiItem.DocumentItem && + oldItem.searchDocument.title == newItem.searchDocument.title && + oldItem.searchDocument.date == newItem.searchDocument.date + val isSameSeparatorItem = + oldItem is SearchUiItem.SeparatorItem && newItem is SearchUiItem.SeparatorItem && + oldItem.description == newItem.description + return isSameDocumentItem || isSameSeparatorItem + } + + override fun areContentsTheSame( + oldItem: SearchUiItem, + newItem: SearchUiItem + ): Boolean { + return oldItem.hashCode() == newItem.hashCode() + } +} From 0e8c25cb14d5b609ae13c74a449797ace8d7512a Mon Sep 17 00:00:00 2001 From: beomjo Date: Fri, 17 Sep 2021 18:34:42 +0900 Subject: [PATCH 257/273] feat: feat: Bookmark settings, temporary implementation of bookmark list --- .../search/ui/activity/DetailActivity.kt | 6 +- .../ui/adapter/BookmarkPagingAdapter.kt | 18 +++--- .../adapter/viewholders/BookmarkViewHolder.kt | 55 ++++++++++++++++++ .../search/ui/fragment/BookmarkFragment.kt | 57 +++++++++++++++---- .../search/ui/viewmodels/BookmarkViewModel.kt | 38 +++++++++++++ .../search/ui/viewmodels/DetailViewModel.kt | 16 +++++- app/src/main/res/layout/activity_detail.xml | 4 +- app/src/main/res/layout/fragment_bookmark.xml | 52 +++++++++++------ 8 files changed, 202 insertions(+), 44 deletions(-) create mode 100644 app/src/main/kotlin/io/github/beomjo/search/ui/adapter/viewholders/BookmarkViewHolder.kt create mode 100644 app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/BookmarkViewModel.kt diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/activity/DetailActivity.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/activity/DetailActivity.kt index 0d67f2a..0553b89 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/activity/DetailActivity.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/activity/DetailActivity.kt @@ -57,8 +57,10 @@ class DetailActivity : BaseActivity(R.layout.activity_det ) } } - favoriteBtn.setOnClickListener { - favoriteBtn.isSelected = !favoriteBtn.isSelected + + bookmarkBtn.setOnClickListener { + bookmarkBtn.isSelected = !bookmarkBtn.isSelected + this@DetailActivity.detailViewModel.onClickBookmark(bookmarkBtn.isSelected) } } } diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/BookmarkPagingAdapter.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/BookmarkPagingAdapter.kt index 5ea5dd7..12cf500 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/BookmarkPagingAdapter.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/BookmarkPagingAdapter.kt @@ -27,6 +27,7 @@ import io.github.beomjo.search.R import io.github.beomjo.search.entity.SearchDocument import io.github.beomjo.search.ui.adapter.diff.SearchDocumentDiffUtil import io.github.beomjo.search.ui.adapter.diff.SearchUiItemDiffUtil +import io.github.beomjo.search.ui.adapter.viewholders.BookmarkViewHolder import io.github.beomjo.search.ui.adapter.viewholders.SearchDocumentViewHolder import io.github.beomjo.search.ui.adapter.viewholders.SearchSeparatorViewHolder import io.github.beomjo.search.ui.viewmodels.SearchDocumentViewModelFactory @@ -38,21 +39,18 @@ class BookmarkPagingAdapter @AssistedInject constructor( private val lifeCycleOwner: LifecycleOwner, @Assisted private val onClickItem: (SearchDocument) -> Unit, - private val factory: BookmarkPagingAdapterFactory -) : PagingDataAdapter(SearchDocumentDiffUtil()) { + private val factory: Provider +) : PagingDataAdapter(SearchDocumentDiffUtil()) { - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { - return when (viewType) { - R.layout.search_list_document_item -> SearchDocumentViewHolder.create(parent) - else -> SearchSeparatorViewHolder.create(parent) - } + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BookmarkViewHolder { + return BookmarkViewHolder.create(parent) } - override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { + override fun onBindViewHolder(holder: BookmarkViewHolder, position: Int) { getItem(position)?.let { - (holder as SearchDocumentViewHolder).bind( + holder.bind( lifeCycleOwner, - factory.create(it), + factory.get().create(it), onClickItem ) } diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/viewholders/BookmarkViewHolder.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/viewholders/BookmarkViewHolder.kt new file mode 100644 index 0000000..54df0e9 --- /dev/null +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/viewholders/BookmarkViewHolder.kt @@ -0,0 +1,55 @@ +/* + * Designed and developed by 2021 beomjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.github.beomjo.search.ui.adapter.viewholders + +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.lifecycle.LifecycleOwner +import androidx.recyclerview.widget.RecyclerView +import io.github.beomjo.search.databinding.SearchListDocumentItemBinding +import io.github.beomjo.search.entity.SearchDocument +import io.github.beomjo.search.ui.viewmodels.SearchDocumentViewModel + +class BookmarkViewHolder( + private val binding: SearchListDocumentItemBinding, +) : RecyclerView.ViewHolder(binding.root) { + + fun bind( + lifecycleOwner: LifecycleOwner, + searchDocumentViewModel: SearchDocumentViewModel, + onClickItem: (SearchDocument) -> Unit + ) { + binding.run { + this.lifecycleOwner = lifecycleOwner + viewModel = searchDocumentViewModel + documentContainer.setOnClickListener { onClickItem(searchDocumentViewModel.searchDocument) } + executePendingBindings() + } + } + + companion object { + fun create(parent: ViewGroup): BookmarkViewHolder { + return BookmarkViewHolder( + SearchListDocumentItemBinding.inflate( + LayoutInflater.from(parent.context), + parent, + false + ) + ) + } + } +} \ No newline at end of file diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/fragment/BookmarkFragment.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/fragment/BookmarkFragment.kt index 2103fe6..364d184 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/fragment/BookmarkFragment.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/fragment/BookmarkFragment.kt @@ -17,20 +17,55 @@ package io.github.beomjo.search.ui.fragment import android.os.Bundle -import android.view.LayoutInflater import android.view.View -import android.view.ViewGroup -import androidx.fragment.app.Fragment +import androidx.lifecycle.ViewModelStoreOwner +import androidx.lifecycle.lifecycleScope +import dagger.hilt.android.AndroidEntryPoint +import io.github.beomjo.search.R +import io.github.beomjo.search.base.BaseFragment import io.github.beomjo.search.databinding.FragmentBookmarkBinding +import io.github.beomjo.search.ui.adapter.BookmarkPagingAdapter +import io.github.beomjo.search.ui.adapter.BookmarkPagingAdapterFactory +import io.github.beomjo.search.ui.viewmodels.BookmarkViewModel +import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.launch +import javax.inject.Inject -class BookmarkFragment : Fragment() { - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ): View { - val binding = FragmentBookmarkBinding.inflate(layoutInflater) - return binding.root +@AndroidEntryPoint +class BookmarkFragment : BaseFragment(R.layout.fragment_bookmark) { + + private val bookmarkViewModel: BookmarkViewModel by getViewModel() + + @Inject + lateinit var bookmarkPagingAdapterFactory: BookmarkPagingAdapterFactory + + private val bookmarkAdapter: BookmarkPagingAdapter by lazy { + bookmarkPagingAdapterFactory.create(this) { + } + } + + override val viewModelProvideOwner: ViewModelStoreOwner + get() = this.requireActivity() + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + bindLayout() + observeViewModel() + } + + private fun bindLayout() { + binding { + viewModel = bookmarkViewModel + bookmarkAdapter = this@BookmarkFragment.bookmarkAdapter + } + } + + private fun observeViewModel() { + lifecycleScope.launch { + bookmarkViewModel.pager.collect { + bookmarkAdapter.submitData(it) + } + } } companion object { diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/BookmarkViewModel.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/BookmarkViewModel.kt new file mode 100644 index 0000000..50fa548 --- /dev/null +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/BookmarkViewModel.kt @@ -0,0 +1,38 @@ +/* + * Designed and developed by 2021 beomjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.github.beomjo.search.ui.viewmodels + +import androidx.lifecycle.viewModelScope +import androidx.paging.PagingData +import androidx.paging.cachedIn +import dagger.hilt.android.lifecycle.HiltViewModel +import io.github.beomjo.search.base.BaseViewModel +import io.github.beomjo.search.entity.Empty +import io.github.beomjo.search.entity.SearchDocument +import io.github.beomjo.search.usecase.GetBookmarkPagingData +import kotlinx.coroutines.flow.Flow +import javax.inject.Inject + +@HiltViewModel +class BookmarkViewModel @Inject constructor( + private val getBookmarkPagingData: GetBookmarkPagingData +) : BaseViewModel() { + + val pager: Flow> = getBookmarkPagingData(Empty) + .cachedIn(viewModelScope) + +} \ No newline at end of file diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/DetailViewModel.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/DetailViewModel.kt index f0d72d8..362ffbf 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/DetailViewModel.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/DetailViewModel.kt @@ -6,13 +6,17 @@ import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import io.github.beomjo.search.base.BaseViewModel import io.github.beomjo.search.entity.SearchDocument +import io.github.beomjo.search.usecase.RemoveBookmark +import io.github.beomjo.search.usecase.SetBookmark import io.github.beomjo.search.usecase.SetSearchDocumentVisit import kotlinx.coroutines.launch import javax.inject.Inject @HiltViewModel class DetailViewModel @Inject constructor( - private val setSearchDocumentVisit: SetSearchDocumentVisit + private val setSearchDocumentVisit: SetSearchDocumentVisit, + private val removeBookmark: RemoveBookmark, + private val setBookmark: SetBookmark ) : BaseViewModel() { private val _searchDocument = MutableLiveData() @@ -31,4 +35,14 @@ class DetailViewModel @Inject constructor( setSearchDocumentVisit(searchDocument.value?.url ?: return@launch) } } + + fun onClickBookmark(isBookmarked: Boolean) { + viewModelScope.launch { + if (!isBookmarked) { + removeBookmark.invoke(searchDocument.value ?: return@launch) + } else { + setBookmark.invoke(searchDocument.value ?: return@launch) + } + } + } } diff --git a/app/src/main/res/layout/activity_detail.xml b/app/src/main/res/layout/activity_detail.xml index a736c60..c128ba0 100644 --- a/app/src/main/res/layout/activity_detail.xml +++ b/app/src/main/res/layout/activity_detail.xml @@ -144,7 +144,7 @@ tools:text="Url" /> + app:layout_constraintStart_toEndOf="@id/bookmark_btn" /> diff --git a/app/src/main/res/layout/fragment_bookmark.xml b/app/src/main/res/layout/fragment_bookmark.xml index c99f002..e85a0af 100644 --- a/app/src/main/res/layout/fragment_bookmark.xml +++ b/app/src/main/res/layout/fragment_bookmark.xml @@ -13,22 +13,38 @@ See the License for the specific language governing permissions and limitations under the License. --> - - - - - \ No newline at end of file + xmlns:tools="http://schemas.android.com/tools"> + + + + + + + + + + + + + + \ No newline at end of file From 5e62678e3a39155631cfcd41e71665773519ef9a Mon Sep 17 00:00:00 2001 From: beomjo Date: Fri, 17 Sep 2021 18:41:48 +0900 Subject: [PATCH 258/273] feat: Display whether or not the detail screen is bookmarked --- .../search/ui/activity/DetailActivity.kt | 10 +++++++-- .../search/ui/viewmodels/DetailViewModel.kt | 21 ++++++++++++------- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/activity/DetailActivity.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/activity/DetailActivity.kt index 0553b89..91e77e0 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/activity/DetailActivity.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/activity/DetailActivity.kt @@ -35,6 +35,7 @@ class DetailActivity : BaseActivity(R.layout.activity_det override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) bindLayout() + observeViewModel() } private fun bindLayout() { @@ -59,12 +60,17 @@ class DetailActivity : BaseActivity(R.layout.activity_det } bookmarkBtn.setOnClickListener { - bookmarkBtn.isSelected = !bookmarkBtn.isSelected - this@DetailActivity.detailViewModel.onClickBookmark(bookmarkBtn.isSelected) + this@DetailActivity.detailViewModel.onClickBookmark() } } } + private fun observeViewModel() { + detailViewModel.isBookmark.observe(this) { isBookmarked -> + binding.bookmarkBtn.isSelected = isBookmarked + } + } + companion object { private const val KEY_DOCUMENT = "DetailActivity.Document" fun action(context: Context, searchDocument: SearchDocument) { diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/DetailViewModel.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/DetailViewModel.kt index 362ffbf..67fa846 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/DetailViewModel.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/DetailViewModel.kt @@ -1,20 +1,21 @@ package io.github.beomjo.search.ui.viewmodels -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.viewModelScope +import androidx.lifecycle.* import dagger.hilt.android.lifecycle.HiltViewModel import io.github.beomjo.search.base.BaseViewModel import io.github.beomjo.search.entity.SearchDocument +import io.github.beomjo.search.usecase.GetBookmark import io.github.beomjo.search.usecase.RemoveBookmark import io.github.beomjo.search.usecase.SetBookmark import io.github.beomjo.search.usecase.SetSearchDocumentVisit +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.launch import javax.inject.Inject @HiltViewModel class DetailViewModel @Inject constructor( private val setSearchDocumentVisit: SetSearchDocumentVisit, + private val getBookmark: GetBookmark, private val removeBookmark: RemoveBookmark, private val setBookmark: SetBookmark ) : BaseViewModel() { @@ -22,9 +23,15 @@ class DetailViewModel @Inject constructor( private val _searchDocument = MutableLiveData() val searchDocument: LiveData = _searchDocument + private val _isBookmark = MutableLiveData() + val isBookmark = _isBookmark.switchMap { searchDocument -> + getBookmark(searchDocument).asLiveData() + } + fun init(searchDocument: SearchDocument?) { searchDocument?.let { _searchDocument.value = it + _isBookmark.value = it } ?: kotlin.run { finish() } @@ -36,12 +43,12 @@ class DetailViewModel @Inject constructor( } } - fun onClickBookmark(isBookmarked: Boolean) { + fun onClickBookmark() { viewModelScope.launch { - if (!isBookmarked) { - removeBookmark.invoke(searchDocument.value ?: return@launch) - } else { + if (isBookmark.value == false) { setBookmark.invoke(searchDocument.value ?: return@launch) + } else { + removeBookmark.invoke(searchDocument.value ?: return@launch) } } } From 5153e073184e07ac98f08f7d085dff5eebe27e89 Mon Sep 17 00:00:00 2001 From: beomjo Date: Fri, 17 Sep 2021 18:44:26 +0900 Subject: [PATCH 259/273] =?UTF-8?q?feat:=20Show=20bookmarked=20values=20?= =?UTF-8?q?=E2=80=8B=E2=80=8Bin=20search=20list?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../search/ui/viewmodels/SearchDocumentViewModel.kt | 8 +++++++- app/src/main/res/layout/search_list_document_item.xml | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/SearchDocumentViewModel.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/SearchDocumentViewModel.kt index 6e624b0..66d2826 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/SearchDocumentViewModel.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/SearchDocumentViewModel.kt @@ -23,6 +23,7 @@ import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject import io.github.beomjo.search.entity.SearchDocument +import io.github.beomjo.search.usecase.GetBookmark import io.github.beomjo.search.usecase.GetSearchDocumentVisit import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.distinctUntilChanged @@ -30,13 +31,18 @@ import kotlinx.coroutines.flow.flowOn class SearchDocumentViewModel @AssistedInject constructor( @Assisted val searchDocument: SearchDocument, - getSearchDocumentVisit: GetSearchDocumentVisit + getSearchDocumentVisit: GetSearchDocumentVisit, + getBookmark: GetBookmark, ) { val isVisit: LiveData = getSearchDocumentVisit(searchDocument.url) .distinctUntilChanged() .flowOn(Dispatchers.Main) .asLiveData() .map { it?.url != null } + + val isBookmarked: LiveData = getBookmark(searchDocument) + .flowOn(Dispatchers.Main) + .asLiveData() } @AssistedFactory diff --git a/app/src/main/res/layout/search_list_document_item.xml b/app/src/main/res/layout/search_list_document_item.xml index 4928970..9c03439 100644 --- a/app/src/main/res/layout/search_list_document_item.xml +++ b/app/src/main/res/layout/search_list_document_item.xml @@ -111,6 +111,7 @@ Date: Sat, 18 Sep 2021 16:13:24 +0900 Subject: [PATCH 260/273] feat: Implement bookmark screen refresh --- app/build.gradle.kts | 1 + .../adapter/viewholders/BookmarkViewHolder.kt | 6 +- .../search/ui/fragment/BookmarkFragment.kt | 12 +- .../search/ui/viewmodels/BookmarkViewModel.kt | 27 +++- .../main/res/layout/bookmark_list_item.xml | 130 ++++++++++++++++++ app/src/main/res/layout/fragment_bookmark.xml | 27 +++- 6 files changed, 186 insertions(+), 17 deletions(-) create mode 100644 app/src/main/res/layout/bookmark_list_item.xml diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 7ab9e49..8ec0d11 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -105,6 +105,7 @@ dependencies { implementation(Dependency.AndroidX.MATERIAL) implementation(Dependency.AndroidX.APP_COMPAT) implementation(Dependency.AndroidX.CONSTRAINT_LAYOUT) + implementation(Dependency.AndroidX.SWIPE_REFRESH_LAYOUT) implementation(Dependency.KTX.CORE) implementation(Dependency.KTX.LIFECYCLE_LIVEDATA) diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/viewholders/BookmarkViewHolder.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/viewholders/BookmarkViewHolder.kt index 54df0e9..85341d3 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/viewholders/BookmarkViewHolder.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/viewholders/BookmarkViewHolder.kt @@ -20,12 +20,14 @@ import android.view.LayoutInflater import android.view.ViewGroup import androidx.lifecycle.LifecycleOwner import androidx.recyclerview.widget.RecyclerView +import io.github.beomjo.search.databinding.BookmarkListItemBinding +import io.github.beomjo.search.databinding.BookmarkListItemBindingImpl import io.github.beomjo.search.databinding.SearchListDocumentItemBinding import io.github.beomjo.search.entity.SearchDocument import io.github.beomjo.search.ui.viewmodels.SearchDocumentViewModel class BookmarkViewHolder( - private val binding: SearchListDocumentItemBinding, + private val binding: BookmarkListItemBinding, ) : RecyclerView.ViewHolder(binding.root) { fun bind( @@ -44,7 +46,7 @@ class BookmarkViewHolder( companion object { fun create(parent: ViewGroup): BookmarkViewHolder { return BookmarkViewHolder( - SearchListDocumentItemBinding.inflate( + BookmarkListItemBinding.inflate( LayoutInflater.from(parent.context), parent, false diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/fragment/BookmarkFragment.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/fragment/BookmarkFragment.kt index 364d184..68098ef 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/fragment/BookmarkFragment.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/fragment/BookmarkFragment.kt @@ -24,6 +24,7 @@ import dagger.hilt.android.AndroidEntryPoint import io.github.beomjo.search.R import io.github.beomjo.search.base.BaseFragment import io.github.beomjo.search.databinding.FragmentBookmarkBinding +import io.github.beomjo.search.ui.activity.DetailActivity import io.github.beomjo.search.ui.adapter.BookmarkPagingAdapter import io.github.beomjo.search.ui.adapter.BookmarkPagingAdapterFactory import io.github.beomjo.search.ui.viewmodels.BookmarkViewModel @@ -40,7 +41,8 @@ class BookmarkFragment : BaseFragment(R.layout.fragment lateinit var bookmarkPagingAdapterFactory: BookmarkPagingAdapterFactory private val bookmarkAdapter: BookmarkPagingAdapter by lazy { - bookmarkPagingAdapterFactory.create(this) { + bookmarkPagingAdapterFactory.create(this) { document -> + DetailActivity.action(requireActivity(), document) } } @@ -55,15 +57,15 @@ class BookmarkFragment : BaseFragment(R.layout.fragment private fun bindLayout() { binding { - viewModel = bookmarkViewModel + viewModel = bookmarkViewModel.apply { init() } bookmarkAdapter = this@BookmarkFragment.bookmarkAdapter } } private fun observeViewModel() { - lifecycleScope.launch { - bookmarkViewModel.pager.collect { - bookmarkAdapter.submitData(it) + bookmarkViewModel.pager.observe(viewLifecycleOwner) { + lifecycleScope.launch { + bookmarkAdapter.submitData(it ?: return@launch) } } } diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/BookmarkViewModel.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/BookmarkViewModel.kt index 50fa548..39e3863 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/BookmarkViewModel.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/BookmarkViewModel.kt @@ -16,6 +16,9 @@ package io.github.beomjo.search.ui.viewmodels +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.asLiveData import androidx.lifecycle.viewModelScope import androidx.paging.PagingData import androidx.paging.cachedIn @@ -25,14 +28,32 @@ import io.github.beomjo.search.entity.Empty import io.github.beomjo.search.entity.SearchDocument import io.github.beomjo.search.usecase.GetBookmarkPagingData import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.launch import javax.inject.Inject @HiltViewModel class BookmarkViewModel @Inject constructor( - private val getBookmarkPagingData: GetBookmarkPagingData + private val getBookmarkPagingData: GetBookmarkPagingData, ) : BaseViewModel() { - val pager: Flow> = getBookmarkPagingData(Empty) - .cachedIn(viewModelScope) + private val _pager = MutableLiveData>() + val pager: LiveData> get() = _pager + private val _isRefresh = MutableLiveData(false) + val isRefresh: LiveData get() = _isRefresh + + fun init() { + viewModelScope.launch { + getBookmarkPagingData(Empty) + .onEach { _isRefresh.value = false } + .cachedIn(viewModelScope) + .collect { _pager.value = it } + } + } + + fun refresh() { + init() + } } \ No newline at end of file diff --git a/app/src/main/res/layout/bookmark_list_item.xml b/app/src/main/res/layout/bookmark_list_item.xml new file mode 100644 index 0000000..541aea1 --- /dev/null +++ b/app/src/main/res/layout/bookmark_list_item.xml @@ -0,0 +1,130 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_bookmark.xml b/app/src/main/res/layout/fragment_bookmark.xml index e85a0af..10d16a6 100644 --- a/app/src/main/res/layout/fragment_bookmark.xml +++ b/app/src/main/res/layout/fragment_bookmark.xml @@ -33,18 +33,31 @@ android:layout_height="match_parent" tools:context="io.github.beomjo.search.ui.fragment.BookmarkFragment"> - + app:onRefreshListener="@{() -> viewModel.refresh()}" + app:refreshing="@{viewModel.isRefresh}"> + + + + + \ No newline at end of file From 495f45cf7c59d2affa5c86e50a773dcb056ee9c6 Mon Sep 17 00:00:00 2001 From: beomjo Date: Sat, 18 Sep 2021 17:07:53 +0900 Subject: [PATCH 261/273] feat: Implement Delete and Add to bookmark list --- .../ui/adapter/BookmarkPagingAdapter.kt | 10 ++---- .../adapter/viewholders/BookmarkViewHolder.kt | 7 ++-- .../viewholders/SearchDocumentViewHolder.kt | 3 ++ .../search/ui/fragment/BookmarkFragment.kt | 16 +++++++--- .../search/ui/viewmodels/BookmarkViewModel.kt | 12 ++++++- .../ui/viewmodels/SearchDocumentViewModel.kt | 17 ++++++++++ .../main/res/layout/bookmark_list_item.xml | 4 +-- app/src/main/res/layout/fragment_bookmark.xml | 1 - .../res/layout/search_list_document_item.xml | 2 +- .../datasource/local/dao/BookmarkDao.kt | 3 ++ .../repository/BookmarkRepositoryImpl.kt | 9 +++++- .../repository/BookmarkRepositoryImplSpec.kt | 2 +- .../search/repository/BookmarkRepository.kt | 4 ++- .../beomjo/search/usecase/GetBookmarkList.kt | 32 +++++++++++++++++++ .../search/usecase/GetBookmarkPagingData.kt | 3 +- .../usecase/GetBookmarkPagingDataSpec.kt | 4 +-- 16 files changed, 102 insertions(+), 27 deletions(-) create mode 100644 domain/src/main/kotlin/io/github/beomjo/search/usecase/GetBookmarkList.kt diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/BookmarkPagingAdapter.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/BookmarkPagingAdapter.kt index 12cf500..b4d1a19 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/BookmarkPagingAdapter.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/BookmarkPagingAdapter.kt @@ -19,19 +19,13 @@ package io.github.beomjo.search.ui.adapter import android.view.ViewGroup import androidx.lifecycle.LifecycleOwner import androidx.paging.PagingDataAdapter -import androidx.recyclerview.widget.RecyclerView import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -import io.github.beomjo.search.R import io.github.beomjo.search.entity.SearchDocument import io.github.beomjo.search.ui.adapter.diff.SearchDocumentDiffUtil -import io.github.beomjo.search.ui.adapter.diff.SearchUiItemDiffUtil import io.github.beomjo.search.ui.adapter.viewholders.BookmarkViewHolder -import io.github.beomjo.search.ui.adapter.viewholders.SearchDocumentViewHolder -import io.github.beomjo.search.ui.adapter.viewholders.SearchSeparatorViewHolder import io.github.beomjo.search.ui.viewmodels.SearchDocumentViewModelFactory -import io.github.beomjo.search.ui.viewmodels.SearchViewModel import javax.inject.Provider class BookmarkPagingAdapter @AssistedInject constructor( @@ -51,7 +45,7 @@ class BookmarkPagingAdapter @AssistedInject constructor( holder.bind( lifeCycleOwner, factory.get().create(it), - onClickItem + onClickItem, ) } } @@ -61,6 +55,6 @@ class BookmarkPagingAdapter @AssistedInject constructor( interface BookmarkPagingAdapterFactory { fun create( lifeCycleOwner: LifecycleOwner, - onClickItem: (SearchDocument) -> Unit + onClickItem: (SearchDocument) -> Unit, ): BookmarkPagingAdapter } \ No newline at end of file diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/viewholders/BookmarkViewHolder.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/viewholders/BookmarkViewHolder.kt index 85341d3..055fd48 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/viewholders/BookmarkViewHolder.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/viewholders/BookmarkViewHolder.kt @@ -21,8 +21,6 @@ import android.view.ViewGroup import androidx.lifecycle.LifecycleOwner import androidx.recyclerview.widget.RecyclerView import io.github.beomjo.search.databinding.BookmarkListItemBinding -import io.github.beomjo.search.databinding.BookmarkListItemBindingImpl -import io.github.beomjo.search.databinding.SearchListDocumentItemBinding import io.github.beomjo.search.entity.SearchDocument import io.github.beomjo.search.ui.viewmodels.SearchDocumentViewModel @@ -33,12 +31,15 @@ class BookmarkViewHolder( fun bind( lifecycleOwner: LifecycleOwner, searchDocumentViewModel: SearchDocumentViewModel, - onClickItem: (SearchDocument) -> Unit + onClickItem: (SearchDocument) -> Unit, ) { binding.run { this.lifecycleOwner = lifecycleOwner viewModel = searchDocumentViewModel documentContainer.setOnClickListener { onClickItem(searchDocumentViewModel.searchDocument) } + bookmarkBtn.setOnClickListener { + searchDocumentViewModel.onClickBookmark() + } executePendingBindings() } } diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/viewholders/SearchDocumentViewHolder.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/viewholders/SearchDocumentViewHolder.kt index 92c3035..7973f1c 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/viewholders/SearchDocumentViewHolder.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/viewholders/SearchDocumentViewHolder.kt @@ -37,6 +37,9 @@ class SearchDocumentViewHolder( this.lifecycleOwner = lifecycleOwner viewModel = searchDocumentViewModel documentContainer.setOnClickListener { onClickItem(searchDocumentViewModel.searchDocument) } + bookmarkBtn.setOnClickListener { + searchDocumentViewModel.onClickBookmark() + } executePendingBindings() } } diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/fragment/BookmarkFragment.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/fragment/BookmarkFragment.kt index 68098ef..b64e7c6 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/fragment/BookmarkFragment.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/fragment/BookmarkFragment.kt @@ -28,7 +28,6 @@ import io.github.beomjo.search.ui.activity.DetailActivity import io.github.beomjo.search.ui.adapter.BookmarkPagingAdapter import io.github.beomjo.search.ui.adapter.BookmarkPagingAdapterFactory import io.github.beomjo.search.ui.viewmodels.BookmarkViewModel -import kotlinx.coroutines.flow.collect import kotlinx.coroutines.launch import javax.inject.Inject @@ -41,9 +40,12 @@ class BookmarkFragment : BaseFragment(R.layout.fragment lateinit var bookmarkPagingAdapterFactory: BookmarkPagingAdapterFactory private val bookmarkAdapter: BookmarkPagingAdapter by lazy { - bookmarkPagingAdapterFactory.create(this) { document -> - DetailActivity.action(requireActivity(), document) - } + bookmarkPagingAdapterFactory.create( + this, + onClickItem = { searchDocument -> + DetailActivity.action(requireActivity(), searchDocument) + }, + ) } override val viewModelProvideOwner: ViewModelStoreOwner @@ -68,6 +70,12 @@ class BookmarkFragment : BaseFragment(R.layout.fragment bookmarkAdapter.submitData(it ?: return@launch) } } + bookmarkViewModel.bookmarkList.observe(viewLifecycleOwner) { bookmarkList -> + bookmarkViewModel.removeBookmarkFromPagingData(bookmarkList) + if (bookmarkAdapter.itemCount < bookmarkList.size) { + bookmarkViewModel.refresh() + } + } } companion object { diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/BookmarkViewModel.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/BookmarkViewModel.kt index 39e3863..1f6c2e0 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/BookmarkViewModel.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/BookmarkViewModel.kt @@ -22,12 +22,13 @@ import androidx.lifecycle.asLiveData import androidx.lifecycle.viewModelScope import androidx.paging.PagingData import androidx.paging.cachedIn +import androidx.paging.filter import dagger.hilt.android.lifecycle.HiltViewModel import io.github.beomjo.search.base.BaseViewModel import io.github.beomjo.search.entity.Empty import io.github.beomjo.search.entity.SearchDocument +import io.github.beomjo.search.usecase.GetBookmarkList import io.github.beomjo.search.usecase.GetBookmarkPagingData -import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch @@ -36,6 +37,7 @@ import javax.inject.Inject @HiltViewModel class BookmarkViewModel @Inject constructor( private val getBookmarkPagingData: GetBookmarkPagingData, + private val getBookmarkList: GetBookmarkList, ) : BaseViewModel() { private val _pager = MutableLiveData>() @@ -44,6 +46,8 @@ class BookmarkViewModel @Inject constructor( private val _isRefresh = MutableLiveData(false) val isRefresh: LiveData get() = _isRefresh + val bookmarkList: LiveData> = getBookmarkList(Empty).asLiveData() + fun init() { viewModelScope.launch { getBookmarkPagingData(Empty) @@ -56,4 +60,10 @@ class BookmarkViewModel @Inject constructor( fun refresh() { init() } + + fun removeBookmarkFromPagingData(bookmarkList: List) { + pager.value + ?.filter { bookmarkList.contains(it) } + ?.let { _pager.value = it } + } } \ No newline at end of file diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/SearchDocumentViewModel.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/SearchDocumentViewModel.kt index 66d2826..ed418d6 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/SearchDocumentViewModel.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/SearchDocumentViewModel.kt @@ -19,20 +19,27 @@ package io.github.beomjo.search.ui.viewmodels import androidx.lifecycle.LiveData import androidx.lifecycle.asLiveData import androidx.lifecycle.map +import androidx.lifecycle.viewModelScope import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject import io.github.beomjo.search.entity.SearchDocument import io.github.beomjo.search.usecase.GetBookmark import io.github.beomjo.search.usecase.GetSearchDocumentVisit +import io.github.beomjo.search.usecase.RemoveBookmark +import io.github.beomjo.search.usecase.SetBookmark +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flowOn +import kotlinx.coroutines.launch class SearchDocumentViewModel @AssistedInject constructor( @Assisted val searchDocument: SearchDocument, getSearchDocumentVisit: GetSearchDocumentVisit, getBookmark: GetBookmark, + private val setBookmark: SetBookmark, + private val removeBookmark: RemoveBookmark ) { val isVisit: LiveData = getSearchDocumentVisit(searchDocument.url) .distinctUntilChanged() @@ -43,6 +50,16 @@ class SearchDocumentViewModel @AssistedInject constructor( val isBookmarked: LiveData = getBookmark(searchDocument) .flowOn(Dispatchers.Main) .asLiveData() + + fun onClickBookmark() { + CoroutineScope(Dispatchers.Main).launch { + if (isBookmarked.value == false) { + setBookmark(searchDocument) + } else { + removeBookmark(searchDocument) + } + } + } } @AssistedFactory diff --git a/app/src/main/res/layout/bookmark_list_item.xml b/app/src/main/res/layout/bookmark_list_item.xml index 541aea1..a8ba4da 100644 --- a/app/src/main/res/layout/bookmark_list_item.xml +++ b/app/src/main/res/layout/bookmark_list_item.xml @@ -111,8 +111,8 @@ tools:text="2021년 12월 30일" /> - \ No newline at end of file diff --git a/app/src/main/res/layout/search_list_document_item.xml b/app/src/main/res/layout/search_list_document_item.xml index 9c03439..f59c54e 100644 --- a/app/src/main/res/layout/search_list_document_item.xml +++ b/app/src/main/res/layout/search_list_document_item.xml @@ -110,7 +110,7 @@ tools:text="2021년 12월 30일" /> + + @Query("SELECT * FROM bookmark_table ORDER BY bookmarkedDate DESC") + fun getBookmarks(): Flow> } diff --git a/data/src/main/kotlin/io/github/beomjo/search/repository/BookmarkRepositoryImpl.kt b/data/src/main/kotlin/io/github/beomjo/search/repository/BookmarkRepositoryImpl.kt index 799d129..7c5593c 100644 --- a/data/src/main/kotlin/io/github/beomjo/search/repository/BookmarkRepositoryImpl.kt +++ b/data/src/main/kotlin/io/github/beomjo/search/repository/BookmarkRepositoryImpl.kt @@ -23,6 +23,7 @@ import io.github.beomjo.search.datasource.local.dao.BookmarkDao import io.github.beomjo.search.datasource.remote.api.paging.BookmarkPagingSource import io.github.beomjo.search.entity.SearchDocument import io.github.beomjo.search.mapper.toBookmarkTable +import io.github.beomjo.search.mapper.toEntity import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map import javax.inject.Inject @@ -43,7 +44,7 @@ internal class BookmarkRepositoryImpl @Inject constructor( return bookmarkDao.isBookmarked(searchDocument.url).map { it?.url != null } } - override fun getBookmarkList(): Flow> { + override fun getBookmarkPagingData(): Flow> { return Pager( config = PagingConfig( pageSize = BookmarkPagingSource.LIMIT, @@ -51,4 +52,10 @@ internal class BookmarkRepositoryImpl @Inject constructor( ) ) { bookmarkPagingSource }.flow } + + override fun getBookmarkList(): Flow> { + return bookmarkDao.getBookmarks().map { bookmarkTable -> + bookmarkTable.map { it.toEntity() } + } + } } \ No newline at end of file diff --git a/data/src/test/java/io/github/beomjo/search/repository/BookmarkRepositoryImplSpec.kt b/data/src/test/java/io/github/beomjo/search/repository/BookmarkRepositoryImplSpec.kt index 6ebc1b2..a1637e6 100644 --- a/data/src/test/java/io/github/beomjo/search/repository/BookmarkRepositoryImplSpec.kt +++ b/data/src/test/java/io/github/beomjo/search/repository/BookmarkRepositoryImplSpec.kt @@ -132,7 +132,7 @@ class BookmarkRepositoryImplSpec : BehaviorSpec() { val repositoryImpl = BookmarkRepositoryImpl(bookmarkDao, bookmarkPagingSource) When("Call getBookmarkList") { - val result = repositoryImpl.getBookmarkList() + val result = repositoryImpl.getBookmarkPagingData() Then("Should return PagingData flow") { result.first().shouldBeTypeOf>() diff --git a/domain/src/main/kotlin/io/github/beomjo/search/repository/BookmarkRepository.kt b/domain/src/main/kotlin/io/github/beomjo/search/repository/BookmarkRepository.kt index b668b92..d1f04fb 100644 --- a/domain/src/main/kotlin/io/github/beomjo/search/repository/BookmarkRepository.kt +++ b/domain/src/main/kotlin/io/github/beomjo/search/repository/BookmarkRepository.kt @@ -11,5 +11,7 @@ interface BookmarkRepository { fun isBookmarked(searchDocument: SearchDocument): Flow - fun getBookmarkList(): Flow> + fun getBookmarkPagingData(): Flow> + + fun getBookmarkList(): Flow> } \ No newline at end of file diff --git a/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetBookmarkList.kt b/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetBookmarkList.kt new file mode 100644 index 0000000..71bfd83 --- /dev/null +++ b/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetBookmarkList.kt @@ -0,0 +1,32 @@ +/* + * Designed and developed by 2021 beomjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.github.beomjo.search.usecase + +import io.github.beomjo.search.entity.Empty +import io.github.beomjo.search.entity.SearchDocument +import io.github.beomjo.search.repository.BookmarkRepository +import io.github.beomjo.search.usecase.base.FlowUseCase +import kotlinx.coroutines.flow.Flow +import javax.inject.Inject + +class GetBookmarkList @Inject constructor( + private val bookmarkRepository: BookmarkRepository, +) : FlowUseCase>() { + override fun execute(param: Empty): Flow> { + return bookmarkRepository.getBookmarkList() + } +} \ No newline at end of file diff --git a/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetBookmarkPagingData.kt b/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetBookmarkPagingData.kt index 51855cd..0d72798 100644 --- a/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetBookmarkPagingData.kt +++ b/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetBookmarkPagingData.kt @@ -20,7 +20,6 @@ import androidx.paging.PagingData import io.github.beomjo.search.entity.Empty import io.github.beomjo.search.entity.SearchDocument import io.github.beomjo.search.repository.BookmarkRepository -import io.github.beomjo.search.usecase.base.FlowUseCase import io.github.beomjo.search.usecase.base.PagingUseCase import kotlinx.coroutines.flow.Flow import javax.inject.Inject @@ -29,6 +28,6 @@ class GetBookmarkPagingData @Inject constructor( private val bookmarkRepository: BookmarkRepository ) : PagingUseCase() { override fun execute(param: Empty): Flow> { - return bookmarkRepository.getBookmarkList() + return bookmarkRepository.getBookmarkPagingData() } } \ No newline at end of file diff --git a/domain/src/test/java/io/github/beomjo/search/usecase/GetBookmarkPagingDataSpec.kt b/domain/src/test/java/io/github/beomjo/search/usecase/GetBookmarkPagingDataSpec.kt index 66c5977..9920ef6 100644 --- a/domain/src/test/java/io/github/beomjo/search/usecase/GetBookmarkPagingDataSpec.kt +++ b/domain/src/test/java/io/github/beomjo/search/usecase/GetBookmarkPagingDataSpec.kt @@ -35,14 +35,14 @@ class GetBookmarkPagingDataSpec : BehaviorSpec() { val searchDocumentList = listOf(mockk(), mockk()) val pagingData = PagingData.from(searchDocumentList) val getBookmarkPagingDataUseCase = GetBookmarkPagingData(bookmarkRepository) - every { bookmarkRepository.getBookmarkList() } returns flowOf(pagingData) + every { bookmarkRepository.getBookmarkPagingData() } returns flowOf(pagingData) When("Call invoke") { val bookmarkListFlow = getBookmarkPagingDataUseCase.invoke(Empty) Then("Should return a bookmark list flow") { bookmarkListFlow.first() shouldBe pagingData - verify { bookmarkRepository.getBookmarkList() } + verify { bookmarkRepository.getBookmarkPagingData() } } } } From 5ba84449eff2811e528355981c5d500a2370a212 Mon Sep 17 00:00:00 2001 From: beomjo Date: Sun, 19 Sep 2021 16:30:28 +0900 Subject: [PATCH 262/273] test: Add GookmarkList, ViewModels Test --- .../search/ui/viewmodels/DetailViewModel.kt | 11 +- .../ui/viewmodels/SearchDocumentViewModel.kt | 7 +- .../ui/viewmodels/DetailViewModelSpec.kt | 97 ++++++++++++- .../viewmodels/SearchDocumentViewModelSpec.kt | 137 +++++++++++++++++- .../repository/BookmarkRepositoryImplSpec.kt | 31 +++- .../{GetBookmark.kt => GetBookmarkState.kt} | 2 +- .../search/usecase/GetBookmarkListSpec.kt | 55 +++++++ .../beomjo/search/usecase/GetBookmarkSpec.kt | 2 +- 8 files changed, 320 insertions(+), 22 deletions(-) rename domain/src/main/kotlin/io/github/beomjo/search/usecase/{GetBookmark.kt => GetBookmarkState.kt} (96%) create mode 100644 domain/src/test/java/io/github/beomjo/search/usecase/GetBookmarkListSpec.kt diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/DetailViewModel.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/DetailViewModel.kt index 67fa846..e714914 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/DetailViewModel.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/DetailViewModel.kt @@ -4,18 +4,17 @@ import androidx.lifecycle.* import dagger.hilt.android.lifecycle.HiltViewModel import io.github.beomjo.search.base.BaseViewModel import io.github.beomjo.search.entity.SearchDocument -import io.github.beomjo.search.usecase.GetBookmark +import io.github.beomjo.search.usecase.GetBookmarkState import io.github.beomjo.search.usecase.RemoveBookmark import io.github.beomjo.search.usecase.SetBookmark import io.github.beomjo.search.usecase.SetSearchDocumentVisit -import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.launch import javax.inject.Inject @HiltViewModel class DetailViewModel @Inject constructor( private val setSearchDocumentVisit: SetSearchDocumentVisit, - private val getBookmark: GetBookmark, + private val getBookmarkState: GetBookmarkState, private val removeBookmark: RemoveBookmark, private val setBookmark: SetBookmark ) : BaseViewModel() { @@ -25,7 +24,7 @@ class DetailViewModel @Inject constructor( private val _isBookmark = MutableLiveData() val isBookmark = _isBookmark.switchMap { searchDocument -> - getBookmark(searchDocument).asLiveData() + getBookmarkState(searchDocument).asLiveData() } fun init(searchDocument: SearchDocument?) { @@ -46,9 +45,9 @@ class DetailViewModel @Inject constructor( fun onClickBookmark() { viewModelScope.launch { if (isBookmark.value == false) { - setBookmark.invoke(searchDocument.value ?: return@launch) + setBookmark(searchDocument.value ?: return@launch) } else { - removeBookmark.invoke(searchDocument.value ?: return@launch) + removeBookmark(searchDocument.value ?: return@launch) } } } diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/SearchDocumentViewModel.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/SearchDocumentViewModel.kt index ed418d6..b67fb66 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/SearchDocumentViewModel.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/SearchDocumentViewModel.kt @@ -19,12 +19,11 @@ package io.github.beomjo.search.ui.viewmodels import androidx.lifecycle.LiveData import androidx.lifecycle.asLiveData import androidx.lifecycle.map -import androidx.lifecycle.viewModelScope import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject import io.github.beomjo.search.entity.SearchDocument -import io.github.beomjo.search.usecase.GetBookmark +import io.github.beomjo.search.usecase.GetBookmarkState import io.github.beomjo.search.usecase.GetSearchDocumentVisit import io.github.beomjo.search.usecase.RemoveBookmark import io.github.beomjo.search.usecase.SetBookmark @@ -37,7 +36,7 @@ import kotlinx.coroutines.launch class SearchDocumentViewModel @AssistedInject constructor( @Assisted val searchDocument: SearchDocument, getSearchDocumentVisit: GetSearchDocumentVisit, - getBookmark: GetBookmark, + getBookmarkState: GetBookmarkState, private val setBookmark: SetBookmark, private val removeBookmark: RemoveBookmark ) { @@ -47,7 +46,7 @@ class SearchDocumentViewModel @AssistedInject constructor( .asLiveData() .map { it?.url != null } - val isBookmarked: LiveData = getBookmark(searchDocument) + val isBookmarked: LiveData = getBookmarkState(searchDocument) .flowOn(Dispatchers.Main) .asLiveData() diff --git a/app/src/test/kotlin/io/github/beomjo/search/ui/viewmodels/DetailViewModelSpec.kt b/app/src/test/kotlin/io/github/beomjo/search/ui/viewmodels/DetailViewModelSpec.kt index eefa868..a7845cc 100644 --- a/app/src/test/kotlin/io/github/beomjo/search/ui/viewmodels/DetailViewModelSpec.kt +++ b/app/src/test/kotlin/io/github/beomjo/search/ui/viewmodels/DetailViewModelSpec.kt @@ -20,22 +20,39 @@ import androidx.lifecycle.Observer import com.beomjo.compilation.util.Event import io.github.beomjo.search.base.BaseViewModel import io.github.beomjo.search.entity.SearchDocument +import io.github.beomjo.search.usecase.GetBookmarkState +import io.github.beomjo.search.usecase.RemoveBookmark +import io.github.beomjo.search.usecase.SetBookmark import io.github.beomjo.search.usecase.SetSearchDocumentVisit import io.kotest.core.spec.style.BehaviorSpec import io.mockk.* +import kotlinx.coroutines.flow.flowOf class DetailViewModelSpec : BehaviorSpec() { private val setSearchDocumentVisit = mockk(relaxed = true) + private val getBookmarkState = mockk(relaxed = true) + + private val removeBookmark = mockk(relaxed = true) + + private val setBookmark = mockk(relaxed = true) + private val searchDocumentObserver = mockk>(relaxed = true) - init { + private val isBookmarkedObserver = mockk>(relaxed = true) + + init { Given("Given a searchDocument") { val searchDocument = mockk() - val detailViewModel = DetailViewModel(setSearchDocumentVisit) + val detailViewModel = DetailViewModel( + setSearchDocumentVisit, + getBookmarkState, + removeBookmark, + setBookmark + ) detailViewModel.searchDocument.observeForever(searchDocumentObserver) When("Call init") { @@ -48,7 +65,13 @@ class DetailViewModelSpec : BehaviorSpec() { } Given("Search document given as null") { - val detailViewModel = DetailViewModel(setSearchDocumentVisit) + val detailViewModel = DetailViewModel( + setSearchDocumentVisit, + getBookmarkState, + removeBookmark, + setBookmark + ) + val eventObserver = mockk>>(relaxed = true) detailViewModel.event.observeForever(eventObserver) @@ -67,7 +90,12 @@ class DetailViewModelSpec : BehaviorSpec() { val searchDocument = mockk { every { url } returns documentUrl } - val detailViewModel = DetailViewModel(setSearchDocumentVisit) + val detailViewModel = DetailViewModel( + setSearchDocumentVisit, + getBookmarkState, + removeBookmark, + setBookmark + ) detailViewModel.init(searchDocument) When("Set visit search document") { @@ -80,7 +108,12 @@ class DetailViewModelSpec : BehaviorSpec() { } Given("Given Search document is null") { - val detailViewModel = DetailViewModel(setSearchDocumentVisit) + val detailViewModel = DetailViewModel( + setSearchDocumentVisit, + getBookmarkState, + removeBookmark, + setBookmark + ) When("Set visit search document") { detailViewModel.setVisit() @@ -91,6 +124,60 @@ class DetailViewModelSpec : BehaviorSpec() { } } + Given("Given a not bookmarked") { + val searchDocument = mockk() + + every { getBookmarkState.invoke(any()) } returns flowOf(false) + + val detailViewModel = DetailViewModel( + setSearchDocumentVisit, + getBookmarkState, + removeBookmark, + setBookmark + ) + detailViewModel.isBookmark.observeForever(isBookmarkedObserver) + detailViewModel.init(searchDocument) + + When("Call onClickBookmark") { + detailViewModel.onClickBookmark() + + Then("Should set a bookmark") { + verify { + isBookmarkedObserver.onChanged(eq(false)) + getBookmarkState.invoke(eq(searchDocument)) + } + coVerify { setBookmark(eq(searchDocument)) } + } + } + } + + Given("Given a bookmarked") { + val searchDocument = mockk() + + every { getBookmarkState.invoke(any()) } returns flowOf(true) + + val detailViewModel = DetailViewModel( + setSearchDocumentVisit, + getBookmarkState, + removeBookmark, + setBookmark + ) + detailViewModel.isBookmark.observeForever(isBookmarkedObserver) + detailViewModel.init(searchDocument) + + When("Call onClickBookmark") { + detailViewModel.onClickBookmark() + + Then("Should set a bookmark") { + verify { + isBookmarkedObserver.onChanged(eq(true)) + getBookmarkState.invoke(eq(searchDocument)) + } + coVerify { removeBookmark(eq(searchDocument)) } + } + } + } + afterTest { unmockkAll() } diff --git a/app/src/test/kotlin/io/github/beomjo/search/ui/viewmodels/SearchDocumentViewModelSpec.kt b/app/src/test/kotlin/io/github/beomjo/search/ui/viewmodels/SearchDocumentViewModelSpec.kt index fee60cc..19f2e5a 100644 --- a/app/src/test/kotlin/io/github/beomjo/search/ui/viewmodels/SearchDocumentViewModelSpec.kt +++ b/app/src/test/kotlin/io/github/beomjo/search/ui/viewmodels/SearchDocumentViewModelSpec.kt @@ -19,7 +19,10 @@ package io.github.beomjo.search.ui.viewmodels import androidx.lifecycle.Observer import io.github.beomjo.search.entity.SearchDocument import io.github.beomjo.search.entity.Visit +import io.github.beomjo.search.usecase.GetBookmarkState import io.github.beomjo.search.usecase.GetSearchDocumentVisit +import io.github.beomjo.search.usecase.RemoveBookmark +import io.github.beomjo.search.usecase.SetBookmark import io.kotest.core.spec.style.BehaviorSpec import io.mockk.* import kotlinx.coroutines.flow.flowOf @@ -28,8 +31,16 @@ class SearchDocumentViewModelSpec : BehaviorSpec() { private val getSearchDocumentVisit = mockk(relaxed = true) + private val getBookmarkState = mockk(relaxed = true) + + private val setBookmark = mockk(relaxed = true) + + private val removeBookmark = mockk(relaxed = true) + private val isVisitObserver = mockk>(relaxed = true) + private val isBookmarkedObserver = mockk>(relaxed = true) + init { Given("Give a SearchDocument") { val documentUrl = "http://" @@ -46,7 +57,10 @@ class SearchDocumentViewModelSpec : BehaviorSpec() { When("Create a ViewModel") { val viewModel = SearchDocumentViewModel( searchDocument, - getSearchDocumentVisit + getSearchDocumentVisit, + getBookmarkState, + setBookmark, + removeBookmark ) viewModel.isVisit.observeForever(isVisitObserver) @@ -59,7 +73,7 @@ class SearchDocumentViewModelSpec : BehaviorSpec() { } } - Given("There is no search document") { + Given("SearchDocument Content is given as null") { val documentUrl = "http://" val searchDocument = mockk { every { url } returns documentUrl @@ -70,7 +84,10 @@ class SearchDocumentViewModelSpec : BehaviorSpec() { When("Create a ViewModel") { val viewModel = SearchDocumentViewModel( searchDocument, - getSearchDocumentVisit + getSearchDocumentVisit, + getBookmarkState, + setBookmark, + removeBookmark ) viewModel.isVisit.observeForever(isVisitObserver) @@ -83,6 +100,120 @@ class SearchDocumentViewModelSpec : BehaviorSpec() { } } + Given("Given a SearchDocument") { + val documentUrl = "http://" + val searchDocument = mockk { + every { url } returns documentUrl + every { date } returns mockk() + } + + And("Returns the bookmarked status") { + every { getBookmarkState.invoke(searchDocument) } returns flowOf(true) + + When("Create a ViewModel") { + val viewModel = SearchDocumentViewModel( + searchDocument, + getSearchDocumentVisit, + getBookmarkState, + setBookmark, + removeBookmark + ) + viewModel.isBookmarked.observeForever(isBookmarkedObserver) + + Then("isBookmarked value needs to be updated, true") { + verify { + getBookmarkState.invoke(eq(searchDocument)) + isBookmarkedObserver.onChanged(eq(true)) + } + } + } + } + + And("Returns the not bookmarked status") { + every { getBookmarkState.invoke(searchDocument) } returns flowOf(false) + + When("Create a ViewModel") { + val viewModel = SearchDocumentViewModel( + searchDocument, + getSearchDocumentVisit, + getBookmarkState, + setBookmark, + removeBookmark + ) + viewModel.isBookmarked.observeForever(isBookmarkedObserver) + + Then("isBookmarked value needs to be updated, true") { + verify { + getBookmarkState.invoke(eq(searchDocument)) + isBookmarkedObserver.onChanged(eq(false)) + } + } + } + } + } + + Given("Given a not bookmarked") { + val documentUrl = "http://" + val searchDocument = mockk { + every { url } returns documentUrl + every { date } returns mockk() + } + + every { getBookmarkState.invoke(any()) } returns flowOf(false) + + val viewModel = SearchDocumentViewModel( + searchDocument, + getSearchDocumentVisit, + getBookmarkState, + setBookmark, + removeBookmark + ) + viewModel.isBookmarked.observeForever(isBookmarkedObserver) + + When("Call onClickBookmark") { + viewModel.onClickBookmark() + + Then("Should set a bookmark") { + verify { + isBookmarkedObserver.onChanged(eq(false)) + getBookmarkState.invoke(eq(searchDocument)) + } + coVerify { setBookmark(eq(searchDocument)) } + } + } + } + + Given("Given a bookmarked") { + val documentUrl = "http://" + val searchDocument = mockk { + every { url } returns documentUrl + every { date } returns mockk() + } + + every { getBookmarkState.invoke(any()) } returns flowOf(true) + + val viewModel = SearchDocumentViewModel( + searchDocument, + getSearchDocumentVisit, + getBookmarkState, + setBookmark, + removeBookmark + ) + viewModel.isBookmarked.observeForever(isBookmarkedObserver) + + When("Call onClickBookmark") { + viewModel.onClickBookmark() + + Then("Should set a bookmark") { + verify { + isBookmarkedObserver.onChanged(eq(true)) + getBookmarkState.invoke(eq(searchDocument)) + } + coVerify { removeBookmark(eq(searchDocument)) } + } + } + } + afterTest { unmockkAll() } diff --git a/data/src/test/java/io/github/beomjo/search/repository/BookmarkRepositoryImplSpec.kt b/data/src/test/java/io/github/beomjo/search/repository/BookmarkRepositoryImplSpec.kt index a1637e6..38f8d14 100644 --- a/data/src/test/java/io/github/beomjo/search/repository/BookmarkRepositoryImplSpec.kt +++ b/data/src/test/java/io/github/beomjo/search/repository/BookmarkRepositoryImplSpec.kt @@ -23,6 +23,7 @@ import io.github.beomjo.search.datasource.remote.api.paging.BookmarkPagingSource import io.github.beomjo.search.entity.DocumentType import io.github.beomjo.search.entity.SearchDocument import io.github.beomjo.search.mapper.toBookmarkTable +import io.github.beomjo.search.mapper.toEntity import io.kotest.core.spec.style.BehaviorSpec import io.kotest.matchers.shouldBe import io.kotest.matchers.types.shouldBeTypeOf @@ -128,10 +129,10 @@ class BookmarkRepositoryImplSpec : BehaviorSpec() { } } - Given("Given a bookmarkPagingSource") { + Given("Given a nothing") { val repositoryImpl = BookmarkRepositoryImpl(bookmarkDao, bookmarkPagingSource) - When("Call getBookmarkList") { + When("Call getBookmarkPagingData") { val result = repositoryImpl.getBookmarkPagingData() Then("Should return PagingData flow") { @@ -140,6 +141,32 @@ class BookmarkRepositoryImplSpec : BehaviorSpec() { } } + + Given("Given a nothing") { + val bookmarkTable = listOf( + BookmarkTable( + type = DocumentType.BOOK, + url = "http://", + title = "fqf", + content = "fafa", + writeDate = mockk(), + bookmarkedDate = mockk(), + thumbnail = "http://" + ) + ) + val repositoryImpl = BookmarkRepositoryImpl(bookmarkDao, bookmarkPagingSource) + + every { bookmarkDao.getBookmarks() } returns flowOf(bookmarkTable) + + When("Call getBookmarkList") { + val result = repositoryImpl.getBookmarkList() + + Then("Should return flow") { + result.first() shouldBe bookmarkTable.map { it.toEntity() } + } + } + } + afterTest { unmockkAll() } diff --git a/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetBookmark.kt b/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetBookmarkState.kt similarity index 96% rename from domain/src/main/kotlin/io/github/beomjo/search/usecase/GetBookmark.kt rename to domain/src/main/kotlin/io/github/beomjo/search/usecase/GetBookmarkState.kt index ebd16fd..5601aa6 100644 --- a/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetBookmark.kt +++ b/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetBookmarkState.kt @@ -22,7 +22,7 @@ import io.github.beomjo.search.usecase.base.FlowUseCase import kotlinx.coroutines.flow.Flow import javax.inject.Inject -class GetBookmark @Inject constructor( +class GetBookmarkState @Inject constructor( private val bookmarkRepository: BookmarkRepository ) : FlowUseCase() { override fun execute(param: SearchDocument): Flow { diff --git a/domain/src/test/java/io/github/beomjo/search/usecase/GetBookmarkListSpec.kt b/domain/src/test/java/io/github/beomjo/search/usecase/GetBookmarkListSpec.kt new file mode 100644 index 0000000..158b69d --- /dev/null +++ b/domain/src/test/java/io/github/beomjo/search/usecase/GetBookmarkListSpec.kt @@ -0,0 +1,55 @@ +/* + * Designed and developed by 2021 beomjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.github.beomjo.search.usecase + +import io.github.beomjo.search.entity.Empty +import io.github.beomjo.search.entity.SearchDocument +import io.github.beomjo.search.repository.BookmarkRepository +import io.kotest.core.spec.style.BehaviorSpec +import io.kotest.matchers.shouldBe +import io.mockk.every +import io.mockk.mockk +import io.mockk.unmockkAll +import io.mockk.verify +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.flowOf + +class GetBookmarkListSpec : BehaviorSpec() { + + private val bookmarkRepository = mockk() + + init { + Given("Given a Empty") { + val bookmarkList = listOf(mockk(), mockk()) + val getBookmarkListUseCase = GetBookmarkList(bookmarkRepository) + every { bookmarkRepository.getBookmarkList() } returns flowOf(bookmarkList) + + When("Call invoke") { + val bookmarkListFlow = getBookmarkListUseCase.invoke(Empty) + + Then("Should return a bookmark list flow") { + bookmarkListFlow.first() shouldBe bookmarkList + verify { bookmarkRepository.getBookmarkList() } + } + } + } + + afterTest { + unmockkAll() + } + } +} \ No newline at end of file diff --git a/domain/src/test/java/io/github/beomjo/search/usecase/GetBookmarkSpec.kt b/domain/src/test/java/io/github/beomjo/search/usecase/GetBookmarkSpec.kt index a892bf9..1a369e5 100644 --- a/domain/src/test/java/io/github/beomjo/search/usecase/GetBookmarkSpec.kt +++ b/domain/src/test/java/io/github/beomjo/search/usecase/GetBookmarkSpec.kt @@ -28,7 +28,7 @@ class GetBookmarkSpec : BehaviorSpec() { init { Given("Given a searchDocument") { val searchDocument = mockk() - val getBookmarkUseCase = GetBookmark(bookmarkRepository) + val getBookmarkUseCase = GetBookmarkState(bookmarkRepository) When("Call invoke") { getBookmarkUseCase.invoke(searchDocument) From e475d18a367cd35cccbd517df15986ff6c9db555 Mon Sep 17 00:00:00 2001 From: beomjo Date: Sun, 19 Sep 2021 16:33:27 +0900 Subject: [PATCH 263/273] chore: Fix detekr error --- .../github/beomjo/search/ui/adapter/BookmarkPagingAdapter.kt | 2 +- .../diff/{DocumentDiffUtil.kt => SearchDocumentDiffUtil.kt} | 0 .../beomjo/search/ui/adapter/viewholders/BookmarkViewHolder.kt | 2 +- .../io/github/beomjo/search/ui/viewmodels/BookmarkViewModel.kt | 2 +- .../github/beomjo/search/ui/viewmodels/DetailViewModelSpec.kt | 1 - .../datasource/remote/api/paging/BookmarkPagingSource.kt | 2 +- .../github/beomjo/search/repository/BookmarkRepositoryImpl.kt | 2 +- .../beomjo/search/datasource/local/BookmarkPagingSourceSpec.kt | 2 +- .../beomjo/search/repository/BookmarkRepositoryImplSpec.kt | 3 +-- detekt.yml | 3 +++ .../io/github/beomjo/search/repository/BookmarkRepository.kt | 2 +- .../kotlin/io/github/beomjo/search/usecase/GetBookmarkList.kt | 2 +- .../io/github/beomjo/search/usecase/GetBookmarkPagingData.kt | 2 +- .../kotlin/io/github/beomjo/search/usecase/GetBookmarkState.kt | 2 +- .../kotlin/io/github/beomjo/search/usecase/RemoveBookmark.kt | 2 +- .../main/kotlin/io/github/beomjo/search/usecase/SetBookmark.kt | 2 +- .../io/github/beomjo/search/usecase/GetBookmarkListSpec.kt | 2 +- .../github/beomjo/search/usecase/GetBookmarkPagingDataSpec.kt | 2 +- .../java/io/github/beomjo/search/usecase/GetBookmarkSpec.kt | 3 +-- .../java/io/github/beomjo/search/usecase/RemoveBookmarkSpec.kt | 2 +- .../java/io/github/beomjo/search/usecase/SetFavoriteSpec.kt | 2 +- 21 files changed, 21 insertions(+), 21 deletions(-) rename app/src/main/kotlin/io/github/beomjo/search/ui/adapter/diff/{DocumentDiffUtil.kt => SearchDocumentDiffUtil.kt} (100%) diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/BookmarkPagingAdapter.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/BookmarkPagingAdapter.kt index b4d1a19..d163d8e 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/BookmarkPagingAdapter.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/BookmarkPagingAdapter.kt @@ -57,4 +57,4 @@ interface BookmarkPagingAdapterFactory { lifeCycleOwner: LifecycleOwner, onClickItem: (SearchDocument) -> Unit, ): BookmarkPagingAdapter -} \ No newline at end of file +} diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/diff/DocumentDiffUtil.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/diff/SearchDocumentDiffUtil.kt similarity index 100% rename from app/src/main/kotlin/io/github/beomjo/search/ui/adapter/diff/DocumentDiffUtil.kt rename to app/src/main/kotlin/io/github/beomjo/search/ui/adapter/diff/SearchDocumentDiffUtil.kt diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/viewholders/BookmarkViewHolder.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/viewholders/BookmarkViewHolder.kt index 055fd48..1ac48bf 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/viewholders/BookmarkViewHolder.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/adapter/viewholders/BookmarkViewHolder.kt @@ -55,4 +55,4 @@ class BookmarkViewHolder( ) } } -} \ No newline at end of file +} diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/BookmarkViewModel.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/BookmarkViewModel.kt index 1f6c2e0..205e75e 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/BookmarkViewModel.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/viewmodels/BookmarkViewModel.kt @@ -66,4 +66,4 @@ class BookmarkViewModel @Inject constructor( ?.filter { bookmarkList.contains(it) } ?.let { _pager.value = it } } -} \ No newline at end of file +} diff --git a/app/src/test/kotlin/io/github/beomjo/search/ui/viewmodels/DetailViewModelSpec.kt b/app/src/test/kotlin/io/github/beomjo/search/ui/viewmodels/DetailViewModelSpec.kt index a7845cc..03f2631 100644 --- a/app/src/test/kotlin/io/github/beomjo/search/ui/viewmodels/DetailViewModelSpec.kt +++ b/app/src/test/kotlin/io/github/beomjo/search/ui/viewmodels/DetailViewModelSpec.kt @@ -43,7 +43,6 @@ class DetailViewModelSpec : BehaviorSpec() { private val isBookmarkedObserver = mockk>(relaxed = true) - init { Given("Given a searchDocument") { val searchDocument = mockk() diff --git a/data/src/main/kotlin/io/github/beomjo/search/datasource/remote/api/paging/BookmarkPagingSource.kt b/data/src/main/kotlin/io/github/beomjo/search/datasource/remote/api/paging/BookmarkPagingSource.kt index 2f60cab..e2e4fa1 100644 --- a/data/src/main/kotlin/io/github/beomjo/search/datasource/remote/api/paging/BookmarkPagingSource.kt +++ b/data/src/main/kotlin/io/github/beomjo/search/datasource/remote/api/paging/BookmarkPagingSource.kt @@ -48,4 +48,4 @@ internal class BookmarkPagingSource @Inject constructor( const val DEFAULT_OFFSET = 0 const val LIMIT = 10 } -} \ No newline at end of file +} diff --git a/data/src/main/kotlin/io/github/beomjo/search/repository/BookmarkRepositoryImpl.kt b/data/src/main/kotlin/io/github/beomjo/search/repository/BookmarkRepositoryImpl.kt index 7c5593c..0ab76ef 100644 --- a/data/src/main/kotlin/io/github/beomjo/search/repository/BookmarkRepositoryImpl.kt +++ b/data/src/main/kotlin/io/github/beomjo/search/repository/BookmarkRepositoryImpl.kt @@ -58,4 +58,4 @@ internal class BookmarkRepositoryImpl @Inject constructor( bookmarkTable.map { it.toEntity() } } } -} \ No newline at end of file +} diff --git a/data/src/test/java/io/github/beomjo/search/datasource/local/BookmarkPagingSourceSpec.kt b/data/src/test/java/io/github/beomjo/search/datasource/local/BookmarkPagingSourceSpec.kt index 2089a0e..dd6b50c 100644 --- a/data/src/test/java/io/github/beomjo/search/datasource/local/BookmarkPagingSourceSpec.kt +++ b/data/src/test/java/io/github/beomjo/search/datasource/local/BookmarkPagingSourceSpec.kt @@ -129,4 +129,4 @@ class BookmarkPagingSourceSpec : BehaviorSpec() { } } } -} \ No newline at end of file +} diff --git a/data/src/test/java/io/github/beomjo/search/repository/BookmarkRepositoryImplSpec.kt b/data/src/test/java/io/github/beomjo/search/repository/BookmarkRepositoryImplSpec.kt index 38f8d14..0e44d7c 100644 --- a/data/src/test/java/io/github/beomjo/search/repository/BookmarkRepositoryImplSpec.kt +++ b/data/src/test/java/io/github/beomjo/search/repository/BookmarkRepositoryImplSpec.kt @@ -141,7 +141,6 @@ class BookmarkRepositoryImplSpec : BehaviorSpec() { } } - Given("Given a nothing") { val bookmarkTable = listOf( BookmarkTable( @@ -171,4 +170,4 @@ class BookmarkRepositoryImplSpec : BehaviorSpec() { unmockkAll() } } -} \ No newline at end of file +} diff --git a/detekt.yml b/detekt.yml index e2501d1..8759cde 100644 --- a/detekt.yml +++ b/detekt.yml @@ -14,3 +14,6 @@ complexity: formatting: NoWildcardImports: active: false +exceptions: + TooGenericExceptionCaught: + active: false diff --git a/domain/src/main/kotlin/io/github/beomjo/search/repository/BookmarkRepository.kt b/domain/src/main/kotlin/io/github/beomjo/search/repository/BookmarkRepository.kt index d1f04fb..23fff78 100644 --- a/domain/src/main/kotlin/io/github/beomjo/search/repository/BookmarkRepository.kt +++ b/domain/src/main/kotlin/io/github/beomjo/search/repository/BookmarkRepository.kt @@ -14,4 +14,4 @@ interface BookmarkRepository { fun getBookmarkPagingData(): Flow> fun getBookmarkList(): Flow> -} \ No newline at end of file +} diff --git a/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetBookmarkList.kt b/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetBookmarkList.kt index 71bfd83..2845fe8 100644 --- a/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetBookmarkList.kt +++ b/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetBookmarkList.kt @@ -29,4 +29,4 @@ class GetBookmarkList @Inject constructor( override fun execute(param: Empty): Flow> { return bookmarkRepository.getBookmarkList() } -} \ No newline at end of file +} diff --git a/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetBookmarkPagingData.kt b/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetBookmarkPagingData.kt index 0d72798..75561be 100644 --- a/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetBookmarkPagingData.kt +++ b/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetBookmarkPagingData.kt @@ -30,4 +30,4 @@ class GetBookmarkPagingData @Inject constructor( override fun execute(param: Empty): Flow> { return bookmarkRepository.getBookmarkPagingData() } -} \ No newline at end of file +} diff --git a/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetBookmarkState.kt b/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetBookmarkState.kt index 5601aa6..19ac5a7 100644 --- a/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetBookmarkState.kt +++ b/domain/src/main/kotlin/io/github/beomjo/search/usecase/GetBookmarkState.kt @@ -28,4 +28,4 @@ class GetBookmarkState @Inject constructor( override fun execute(param: SearchDocument): Flow { return bookmarkRepository.isBookmarked(param) } -} \ No newline at end of file +} diff --git a/domain/src/main/kotlin/io/github/beomjo/search/usecase/RemoveBookmark.kt b/domain/src/main/kotlin/io/github/beomjo/search/usecase/RemoveBookmark.kt index 37c8970..a0a1ba6 100644 --- a/domain/src/main/kotlin/io/github/beomjo/search/usecase/RemoveBookmark.kt +++ b/domain/src/main/kotlin/io/github/beomjo/search/usecase/RemoveBookmark.kt @@ -27,4 +27,4 @@ class RemoveBookmark @Inject constructor( override suspend fun execute(param: SearchDocument) { bookmarkRepository.removeBookmark(param) } -} \ No newline at end of file +} diff --git a/domain/src/main/kotlin/io/github/beomjo/search/usecase/SetBookmark.kt b/domain/src/main/kotlin/io/github/beomjo/search/usecase/SetBookmark.kt index fdb980e..bb5f911 100644 --- a/domain/src/main/kotlin/io/github/beomjo/search/usecase/SetBookmark.kt +++ b/domain/src/main/kotlin/io/github/beomjo/search/usecase/SetBookmark.kt @@ -27,4 +27,4 @@ class SetBookmark @Inject constructor( override suspend fun execute(param: SearchDocument) { bookmarkRepository.setBookmark(param) } -} \ No newline at end of file +} diff --git a/domain/src/test/java/io/github/beomjo/search/usecase/GetBookmarkListSpec.kt b/domain/src/test/java/io/github/beomjo/search/usecase/GetBookmarkListSpec.kt index 158b69d..8399d8b 100644 --- a/domain/src/test/java/io/github/beomjo/search/usecase/GetBookmarkListSpec.kt +++ b/domain/src/test/java/io/github/beomjo/search/usecase/GetBookmarkListSpec.kt @@ -52,4 +52,4 @@ class GetBookmarkListSpec : BehaviorSpec() { unmockkAll() } } -} \ No newline at end of file +} diff --git a/domain/src/test/java/io/github/beomjo/search/usecase/GetBookmarkPagingDataSpec.kt b/domain/src/test/java/io/github/beomjo/search/usecase/GetBookmarkPagingDataSpec.kt index 9920ef6..074a90a 100644 --- a/domain/src/test/java/io/github/beomjo/search/usecase/GetBookmarkPagingDataSpec.kt +++ b/domain/src/test/java/io/github/beomjo/search/usecase/GetBookmarkPagingDataSpec.kt @@ -51,4 +51,4 @@ class GetBookmarkPagingDataSpec : BehaviorSpec() { unmockkAll() } } -} \ No newline at end of file +} diff --git a/domain/src/test/java/io/github/beomjo/search/usecase/GetBookmarkSpec.kt b/domain/src/test/java/io/github/beomjo/search/usecase/GetBookmarkSpec.kt index 1a369e5..c725aa3 100644 --- a/domain/src/test/java/io/github/beomjo/search/usecase/GetBookmarkSpec.kt +++ b/domain/src/test/java/io/github/beomjo/search/usecase/GetBookmarkSpec.kt @@ -34,9 +34,8 @@ class GetBookmarkSpec : BehaviorSpec() { getBookmarkUseCase.invoke(searchDocument) Then("Should return whether or not it has been bookmarked") { - } } } } -} \ No newline at end of file +} diff --git a/domain/src/test/java/io/github/beomjo/search/usecase/RemoveBookmarkSpec.kt b/domain/src/test/java/io/github/beomjo/search/usecase/RemoveBookmarkSpec.kt index 8821308..9559321 100644 --- a/domain/src/test/java/io/github/beomjo/search/usecase/RemoveBookmarkSpec.kt +++ b/domain/src/test/java/io/github/beomjo/search/usecase/RemoveBookmarkSpec.kt @@ -44,4 +44,4 @@ class RemoveBookmarkSpec : BehaviorSpec() { unmockkAll() } } -} \ No newline at end of file +} diff --git a/domain/src/test/java/io/github/beomjo/search/usecase/SetFavoriteSpec.kt b/domain/src/test/java/io/github/beomjo/search/usecase/SetFavoriteSpec.kt index c61cdc5..0edbe3f 100644 --- a/domain/src/test/java/io/github/beomjo/search/usecase/SetFavoriteSpec.kt +++ b/domain/src/test/java/io/github/beomjo/search/usecase/SetFavoriteSpec.kt @@ -44,4 +44,4 @@ class SetFavoriteSpec : BehaviorSpec() { unmockkAll() } } -} \ No newline at end of file +} From a5a9301430ba3403d2d007220cc32e74cf987122 Mon Sep 17 00:00:00 2001 From: beomjo Date: Sun, 19 Sep 2021 16:38:11 +0900 Subject: [PATCH 264/273] chore: Changing Test function naming --- .../beomjo/search/usecase/GetSearchDocumentVisitSpec.kt | 2 +- .../github/beomjo/search/usecase/GetSearchHistoryListSpec.kt | 4 ++-- .../github/beomjo/search/usecase/GetSearchPagingDataSpec.kt | 2 +- .../beomjo/search/usecase/SetSearchDocumentVisitSpec.kt | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/domain/src/test/java/io/github/beomjo/search/usecase/GetSearchDocumentVisitSpec.kt b/domain/src/test/java/io/github/beomjo/search/usecase/GetSearchDocumentVisitSpec.kt index 4ad482a..65e02ec 100644 --- a/domain/src/test/java/io/github/beomjo/search/usecase/GetSearchDocumentVisitSpec.kt +++ b/domain/src/test/java/io/github/beomjo/search/usecase/GetSearchDocumentVisitSpec.kt @@ -37,7 +37,7 @@ class GetSearchDocumentVisitSpec : BehaviorSpec() { val useCase = GetSearchDocumentVisit(searchRepository) every { searchRepository.getVisit(expectUrl) } returns flowOf(visit) - When("Invoke") { + When("Call Invoke") { val result = useCase.invoke(expectUrl) Then("Should return a visit") { diff --git a/domain/src/test/java/io/github/beomjo/search/usecase/GetSearchHistoryListSpec.kt b/domain/src/test/java/io/github/beomjo/search/usecase/GetSearchHistoryListSpec.kt index 1bb74ce..444df38 100644 --- a/domain/src/test/java/io/github/beomjo/search/usecase/GetSearchHistoryListSpec.kt +++ b/domain/src/test/java/io/github/beomjo/search/usecase/GetSearchHistoryListSpec.kt @@ -33,14 +33,14 @@ class GetSearchHistoryListSpec : BehaviorSpec() { private val searchRepository = mockk() init { - Given("use case is ") { + Given("Given nothing") { val getSearchHistoryList = GetSearchHistoryList(searchRepository) val expect = listOf(mockk()) coEvery { searchRepository.getSearchHistoryList() } returns flowOf(expect) - When("invoke") { + When("Call invoke") { val result = getSearchHistoryList.invoke(Empty) Then("Should return a HistoryList") { diff --git a/domain/src/test/java/io/github/beomjo/search/usecase/GetSearchPagingDataSpec.kt b/domain/src/test/java/io/github/beomjo/search/usecase/GetSearchPagingDataSpec.kt index ea3c4e0..71ea343 100644 --- a/domain/src/test/java/io/github/beomjo/search/usecase/GetSearchPagingDataSpec.kt +++ b/domain/src/test/java/io/github/beomjo/search/usecase/GetSearchPagingDataSpec.kt @@ -47,7 +47,7 @@ class GetSearchPagingDataSpec : BehaviorSpec() { coEvery { searchRepository.getDocumentPagingData(param) } returns flowOf(pagingData) coEvery { searchRepository.insertSearchHistory(any()) } just Runs - When("invoke") { + When("Call invoke") { val resultFlow = getSearchPagingData.invoke(param) Then("Return PagingData") { diff --git a/domain/src/test/java/io/github/beomjo/search/usecase/SetSearchDocumentVisitSpec.kt b/domain/src/test/java/io/github/beomjo/search/usecase/SetSearchDocumentVisitSpec.kt index db3b279..dd1adea 100644 --- a/domain/src/test/java/io/github/beomjo/search/usecase/SetSearchDocumentVisitSpec.kt +++ b/domain/src/test/java/io/github/beomjo/search/usecase/SetSearchDocumentVisitSpec.kt @@ -33,7 +33,7 @@ class SetSearchDocumentVisitSpec : BehaviorSpec() { val slot = slot() coEvery { searchRepository.insertVisit(capture(slot)) } just Runs - When("Invoke") { + When("Call invoke") { useCase.invoke(url) Then("Should call setVisit of SearchRepository") { From 6886323d0b34d396e4683167074973baa0766698 Mon Sep 17 00:00:00 2001 From: beomjo Date: Sun, 19 Sep 2021 17:18:08 +0900 Subject: [PATCH 265/273] chore: Amend GetBookmarkState test --- .../{GetBookmarkSpec.kt => GetBookmarkStateSpec.kt} | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) rename domain/src/test/java/io/github/beomjo/search/usecase/{GetBookmarkSpec.kt => GetBookmarkStateSpec.kt} (81%) diff --git a/domain/src/test/java/io/github/beomjo/search/usecase/GetBookmarkSpec.kt b/domain/src/test/java/io/github/beomjo/search/usecase/GetBookmarkStateSpec.kt similarity index 81% rename from domain/src/test/java/io/github/beomjo/search/usecase/GetBookmarkSpec.kt rename to domain/src/test/java/io/github/beomjo/search/usecase/GetBookmarkStateSpec.kt index c725aa3..dc8bc6d 100644 --- a/domain/src/test/java/io/github/beomjo/search/usecase/GetBookmarkSpec.kt +++ b/domain/src/test/java/io/github/beomjo/search/usecase/GetBookmarkStateSpec.kt @@ -20,10 +20,11 @@ import io.github.beomjo.search.entity.SearchDocument import io.github.beomjo.search.repository.BookmarkRepository import io.kotest.core.spec.style.BehaviorSpec import io.mockk.mockk +import io.mockk.verify -class GetBookmarkSpec : BehaviorSpec() { +class GetBookmarkStateSpec : BehaviorSpec() { - private val bookmarkRepository = mockk() + private val bookmarkRepository = mockk(relaxed = true) init { Given("Given a searchDocument") { @@ -34,6 +35,9 @@ class GetBookmarkSpec : BehaviorSpec() { getBookmarkUseCase.invoke(searchDocument) Then("Should return whether or not it has been bookmarked") { + verify { + bookmarkRepository.isBookmarked(eq(searchDocument)) + } } } } From ca3e394082ca5f5a95efd7677889610e9c8b118d Mon Sep 17 00:00:00 2001 From: beomjo Date: Sun, 19 Sep 2021 17:23:07 +0900 Subject: [PATCH 266/273] feat: Sort the search history in descending order --- .../beomjo/search/datasource/local/dao/SearchHistoryDao.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/src/main/kotlin/io/github/beomjo/search/datasource/local/dao/SearchHistoryDao.kt b/data/src/main/kotlin/io/github/beomjo/search/datasource/local/dao/SearchHistoryDao.kt index b96fbd3..243a575 100644 --- a/data/src/main/kotlin/io/github/beomjo/search/datasource/local/dao/SearchHistoryDao.kt +++ b/data/src/main/kotlin/io/github/beomjo/search/datasource/local/dao/SearchHistoryDao.kt @@ -29,6 +29,6 @@ internal interface SearchHistoryDao { @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insertHistory(history: SearchHistoryTable) - @Query("SELECT * FROM search_history") + @Query("SELECT * FROM search_history ORDER BY date DESC") fun getHistoryList(): Flow> } From 8336c33d5c0c3177b0a41e745c9f3931d54e7174 Mon Sep 17 00:00:00 2001 From: beomjo Date: Sun, 19 Sep 2021 17:34:26 +0900 Subject: [PATCH 267/273] feat: Add searchHistoryList divider, background --- .../github/beomjo/search/ui/fragment/SearchFragment.kt | 7 +++++++ app/src/main/res/drawable/bg_history_list.xml | 10 ++++++++++ app/src/main/res/layout/fragment_search.xml | 1 + 3 files changed, 18 insertions(+) create mode 100644 app/src/main/res/drawable/bg_history_list.xml diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/fragment/SearchFragment.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/fragment/SearchFragment.kt index 5005638..db46297 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/fragment/SearchFragment.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/fragment/SearchFragment.kt @@ -24,6 +24,7 @@ import androidx.lifecycle.ViewModelStoreOwner import androidx.lifecycle.lifecycleScope import androidx.paging.LoadState import androidx.recyclerview.widget.ConcatAdapter +import androidx.recyclerview.widget.DividerItemDecoration import dagger.hilt.android.AndroidEntryPoint import io.github.beomjo.search.R import io.github.beomjo.search.base.BaseFragment @@ -113,6 +114,12 @@ class SearchFragment : BaseFragment(R.layout.fragment_sea } searchHistoryAdapter = this@SearchFragment.searchHistoryAdapter + searchHistory.addItemDecoration( + DividerItemDecoration( + context, + DividerItemDecoration.VERTICAL + ) + ) } } diff --git a/app/src/main/res/drawable/bg_history_list.xml b/app/src/main/res/drawable/bg_history_list.xml new file mode 100644 index 0000000..2750ccf --- /dev/null +++ b/app/src/main/res/drawable/bg_history_list.xml @@ -0,0 +1,10 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_search.xml b/app/src/main/res/layout/fragment_search.xml index 5465d28..9ef38bd 100644 --- a/app/src/main/res/layout/fragment_search.xml +++ b/app/src/main/res/layout/fragment_search.xml @@ -129,6 +129,7 @@ android:id="@+id/search_history" android:layout_width="0dp" android:layout_height="wrap_content" + android:background="@drawable/bg_history_list" android:orientation="vertical" app:adapter="@{searchHistoryAdapter}" app:isVisible="@{viewModel.hasFocus}" From 0f6049e1a45f45da6baaacea6a3473ff037e3a4a Mon Sep 17 00:00:00 2001 From: beomjo Date: Mon, 20 Sep 2021 00:53:50 +0900 Subject: [PATCH 268/273] fix: Modify comparison logic to add Date Separator --- .../github/beomjo/search/ui/paging/SearchSeparatorGenerator.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/kotlin/io/github/beomjo/search/ui/paging/SearchSeparatorGenerator.kt b/app/src/main/kotlin/io/github/beomjo/search/ui/paging/SearchSeparatorGenerator.kt index 6d2c2df..4c4238c 100644 --- a/app/src/main/kotlin/io/github/beomjo/search/ui/paging/SearchSeparatorGenerator.kt +++ b/app/src/main/kotlin/io/github/beomjo/search/ui/paging/SearchSeparatorGenerator.kt @@ -45,7 +45,7 @@ class SearchSeparatorGenerator @AssistedInject constructor( val afterDate = after.searchDocument.date val beforeDateString = dateHelper.convert(beforeDate, R.string.date_month) - val afterDateString = dateHelper.convert(afterDate) + val afterDateString = dateHelper.convert(afterDate, R.string.date_month) return@insertSeparators when (beforeDateString != afterDateString) { true -> SearchViewModel.SearchUiItem.SeparatorItem(description = afterDateString) else -> null From d2d29de05a75f248423731c924fa7f05eddb05ca Mon Sep 17 00:00:00 2001 From: beomjo Date: Mon, 20 Sep 2021 01:58:46 +0900 Subject: [PATCH 269/273] docs: Modifying README.md --- README.md | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5371079..70f8f2c 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,34 @@ in your local.properties REST_KEY={YOUR_KEY} ``` +## Download +- + +## Tech stack & Open-source libraries +- Minimum SDK level 21 +- Coroutines, Flow for asynchronous. +- LiveData - notify domain layer data to views. +- Lifecycle - dispose of observing data when lifecycle state changes. +- ViewModel - UI related data holder, lifecycle aware. +- Room - Storing data in local database +- Paging3 - Load and display data pages of large data sets from local storage or over a network +- Dagger Hilt - Dependency Injection +- Navigation Component - Move implementation between Fragment and Activity simply and reliably +- Glide - loading images +- Bindables - DataBinding kit for notifying data changes from Model layers to UI layers. +- Material-Components - Material design components like ripple animation, cardView. +- Testing + - kotest + - mockk + + +## Architecture +- Clean Architecture +- MVVM Architecture (View - DataBinding - ViewModel - Model) + +## MAD STORE + + ## LICENSE ```xml Designed and developed by 2021 beomjo @@ -34,5 +62,4 @@ Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and -limitations under the License. -``` \ No newline at end of file +limitations under the License. \ No newline at end of file From 742551369906d94d1756a52c185d6df43e152b1c Mon Sep 17 00:00:00 2001 From: beomjo Date: Mon, 20 Sep 2021 02:13:53 +0900 Subject: [PATCH 270/273] docs: Add MadScore Images --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 70f8f2c..503bbdf 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,9 @@ REST_KEY={YOUR_KEY} - MVVM Architecture (View - DataBinding - ViewModel - Model) ## MAD STORE +![summary](https://user-images.githubusercontent.com/39984656/133936190-2808b53b-1fea-4729-bc44-55aebe845ea5.png) +![kotlin](https://user-images.githubusercontent.com/39984656/133936194-ce21ad52-70c9-4a61-be71-c62e748468e3.png) +![jetpack](https://user-images.githubusercontent.com/39984656/133936197-cbfefd7d-51bc-48d1-8cba-ac983b4fe44f.png) ## LICENSE From c60491bf210cab88ba52cbc8204c2cff569a954e Mon Sep 17 00:00:00 2001 From: beomjo Date: Mon, 20 Sep 2021 02:28:31 +0900 Subject: [PATCH 271/273] docs: Add Sample video --- README.md | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 503bbdf..9ccf52e 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,12 @@

+

+ Pageation was implemented using the Kakao search API,
+ and examples of search, alignment, separator, and bookmark functions can be viewed. +

+ + ## Clone Project ``` $ git clone --recursive https://github.com/beomjo/kakao-search.git @@ -23,22 +29,24 @@ REST_KEY={YOUR_KEY} ## Download - + + ## Tech stack & Open-source libraries - Minimum SDK level 21 -- Coroutines, Flow for asynchronous. -- LiveData - notify domain layer data to views. -- Lifecycle - dispose of observing data when lifecycle state changes. -- ViewModel - UI related data holder, lifecycle aware. -- Room - Storing data in local database -- Paging3 - Load and display data pages of large data sets from local storage or over a network -- Dagger Hilt - Dependency Injection -- Navigation Component - Move implementation between Fragment and Activity simply and reliably -- Glide - loading images -- Bindables - DataBinding kit for notifying data changes from Model layers to UI layers. -- Material-Components - Material design components like ripple animation, cardView. -- Testing - - kotest - - mockk +- **Coroutines, Flow** for asynchronous. +- **LiveData** - notify domain layer data to views. +- **Lifecycle** - dispose of observing data when lifecycle state changes. +- **ViewModel** - UI related data holder, lifecycle aware. +- **Room** - Storing data in local database +- **Paging3** - Load and display data pages of large data sets from local storage or over a network +- **Dagger Hilt** - Dependency Injection +- **Navigation Component** - Move implementation between Fragment and Activity simply and reliably +- **Glide** - loading images +- **Bindables** - DataBinding kit for notifying data changes from Model layers to UI layers. +- **Material-Components** - Material design components like ripple animation, cardView. +- **Testing** + - **kotest** + - **mockk** ## Architecture From 929b8761f1e6306727fdf6704aaab08c3a437bc0 Mon Sep 17 00:00:00 2001 From: beomjo Date: Wed, 22 Sep 2021 02:11:09 +0900 Subject: [PATCH 272/273] Docs: Add cleanarchitecture diagram --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 9ccf52e..cf85698 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,10 @@ REST_KEY={YOUR_KEY} ## Architecture - Clean Architecture + - Structure + ![image](https://user-images.githubusercontent.com/39984656/134216164-4018a2a8-ffcc-4150-b566-cf3fd8155def.png) + - Dependency diagram between layers + ![image](https://user-images.githubusercontent.com/39984656/134216107-72e31ff1-e265-486d-a512-4f8bd0dbbcaf.png) - MVVM Architecture (View - DataBinding - ViewModel - Model) ## MAD STORE @@ -73,4 +77,4 @@ Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and -limitations under the License. \ No newline at end of file +limitations under the License. From 076ee1ce41e704e366960930b41719c364e18239 Mon Sep 17 00:00:00 2001 From: beomjo Date: Thu, 23 Sep 2021 02:37:25 +0900 Subject: [PATCH 273/273] build: Update kotest dependency --- buildSrc/src/main/kotlin/TestDependency.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/src/main/kotlin/TestDependency.kt b/buildSrc/src/main/kotlin/TestDependency.kt index ee19077..552645e 100644 --- a/buildSrc/src/main/kotlin/TestDependency.kt +++ b/buildSrc/src/main/kotlin/TestDependency.kt @@ -21,5 +21,5 @@ object TestDependency { const val COROUTINE_TEST = "org.jetbrains.kotlinx:kotlinx-coroutines-test:1.5.1" const val ANDROID_JUNIT_RUNNER = "AndroidJUnitRunner" const val MOCKK = "io.mockk:mockk:1.12.0" - const val KOTEST = "io.kotest:kotest-runner-junit5:4.6.1" + const val KOTEST = "io.kotest:kotest-runner-junit5:4.6.3" } \ No newline at end of file