From d0cfa8e1a8ef0791f3f44205c811d3a66a617e97 Mon Sep 17 00:00:00 2001
From: JSPark <48265129+pknujsp@users.noreply.github.com>
Date: Mon, 29 May 2023 22:10:49 +0900
Subject: [PATCH] =?UTF-8?q?#91=20BaseNavArgs=EA=B0=9C=EC=84=A0(NavArgs?=
=?UTF-8?q?=EB=A1=9C=20=EA=B0=80=EB=8A=A5=ED=95=9C=20=EA=B1=B0=EC=9D=98=20?=
=?UTF-8?q?=EB=8C=80=EB=B6=80=EB=B6=84=EC=9D=98=20=ED=83=80=EC=9E=85=20?=
=?UTF-8?q?=ED=98=B8=ED=99=98)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/build.gradle.kts | 1 +
app/src/main/res/navigation/main_nav.xml | 1 +
build.gradle.kts | 2 +-
.../core/common/util/UriBuilder.kt | 8 ++-
.../core/data/remote/di/RepositoryModule.kt | 4 +-
.../MedicineApprovalRepositoryImpl.kt | 6 +-
core/database/build.gradle.kts | 3 +-
.../core/database/{RoomDb.kt => RoomDB.kt} | 4 +-
.../mediproject/core/database/RoomModule.kt | 9 ++-
.../searchhistory/SearchHistoryDao.kt | 12 ++--
.../searchhistory/SearchHistoryMapper.kt | 9 +++
core/domain/build.gradle.kts | 1 +
.../core/domain/SearchHistoryUseCase.kt | 24 +++++++
.../core/model/local/navargs/BaseNavArgs.kt | 31 +++++++---
.../search/local/SearchHistoryItemDto.kt | 9 +++
.../searchmedicines/local/SearchQueryArgs.kt | 12 ++++
.../core/ui/base/view/MediSearchbar.kt | 8 +++
.../mediproject/feature/home/HomeFragment.kt | 18 +++---
.../src/main/res/layout/fragment_home.xml | 2 +-
.../home/src/main/res/navigation/home_nav.xml | 17 ++---
.../feature/search/SearchMedicinesFragment.kt | 59 ++++++++----------
.../search/SearchMedicinesViewModel.kt | 13 ++--
.../RecentSearchListFragment.kt | 62 ++++++++++++-------
.../RecentSearchListViewModel.kt | 16 ++++-
.../manual/ManualSearchResultFragment.kt | 19 +++---
.../res/layout/fragment_search_medicines.xml | 2 +-
.../res/navigation/search_medicines_nav.xml | 10 ++-
27 files changed, 232 insertions(+), 130 deletions(-)
rename core/database/src/main/java/com/android/mediproject/core/database/{RoomDb.kt => RoomDB.kt} (72%)
create mode 100644 core/database/src/main/java/com/android/mediproject/core/database/searchhistory/SearchHistoryMapper.kt
create mode 100644 core/domain/src/main/java/com/android/mediproject/core/domain/SearchHistoryUseCase.kt
create mode 100644 core/model/src/main/java/com/android/mediproject/core/model/search/local/SearchHistoryItemDto.kt
create mode 100644 core/model/src/main/java/com/android/mediproject/core/model/searchmedicines/local/SearchQueryArgs.kt
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index daaa5240b..e354ce243 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -42,6 +42,7 @@ dependencies {
implementation(project(":core:data"))
implementation(project(":core:ui"))
implementation(project(":core:model"))
+ implementation(project(":core:database"))
implementation(project(":feature:interestedmedicine"))
diff --git a/app/src/main/res/navigation/main_nav.xml b/app/src/main/res/navigation/main_nav.xml
index df0250b5e..00d63db4f 100644
--- a/app/src/main/res/navigation/main_nav.xml
+++ b/app/src/main/res/navigation/main_nav.xml
@@ -14,5 +14,6 @@
+
\ No newline at end of file
diff --git a/build.gradle.kts b/build.gradle.kts
index a762e3440..7dba145b2 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -19,7 +19,7 @@ plugins {
alias(libs.plugins.kotlin.android) apply false
alias(libs.plugins.nav.safeargs.kotlin) apply false
alias(libs.plugins.kapt) apply false
- alias(libs.plugins.ksp) apply false
+ // alias(libs.plugins.ksp) apply false
alias(libs.plugins.kotlin.parcelize) apply false
}
diff --git a/core/common/src/main/java/com/android/mediproject/core/common/util/UriBuilder.kt b/core/common/src/main/java/com/android/mediproject/core/common/util/UriBuilder.kt
index 6f4ef3d42..5952e218d 100644
--- a/core/common/src/main/java/com/android/mediproject/core/common/util/UriBuilder.kt
+++ b/core/common/src/main/java/com/android/mediproject/core/common/util/UriBuilder.kt
@@ -16,14 +16,16 @@ import com.android.mediproject.core.model.local.navargs.BaseNavArgs
* @param parameter Uri에 들어갈 파라미터
* @return Uri
*/
-private fun toDeepUrl(deepLinkUrl: String, parameter: Map): Uri = StringBuilder(deepLinkUrl).let { uri ->
+private fun toDeepUrl(deepLinkUrl: String, parameter: Map): Uri = StringBuilder(deepLinkUrl).let { uri ->
parameter.takeIf {
it.isNotEmpty()
}?.also { map ->
uri.append("?")
map.onEachIndexed { index, entry ->
- uri.append("${entry.key}=${entry.value}")
- if (index != map.size - 1) uri.append("&")
+ if (entry.value != null) {
+ uri.append("${entry.key}=${entry.value}")
+ if (index != map.size - 1) uri.append("&")
+ }
}
}
uri.toString().toUri()
diff --git a/core/data/src/main/java/com/android/mediproject/core/data/remote/di/RepositoryModule.kt b/core/data/src/main/java/com/android/mediproject/core/data/remote/di/RepositoryModule.kt
index b43de3355..ca6c9ec03 100644
--- a/core/data/src/main/java/com/android/mediproject/core/data/remote/di/RepositoryModule.kt
+++ b/core/data/src/main/java/com/android/mediproject/core/data/remote/di/RepositoryModule.kt
@@ -46,9 +46,9 @@ object RepositoryModule {
@Provides
@Singleton
fun provideMedicineApprovalRepository(
- medicineApprovalDataSource: MedicineApprovalDataSource, searchHistoryDao: SearchHistoryDao
+ medicineApprovalDataSource: MedicineApprovalDataSource, searchHistoryRepository: SearchHistoryRepository
): MedicineApprovalRepository = MedicineApprovalRepositoryImpl(
- medicineApprovalDataSource, searchHistoryDao
+ medicineApprovalDataSource, searchHistoryRepository
)
@Provides
diff --git a/core/data/src/main/java/com/android/mediproject/core/data/remote/medicineapproval/MedicineApprovalRepositoryImpl.kt b/core/data/src/main/java/com/android/mediproject/core/data/remote/medicineapproval/MedicineApprovalRepositoryImpl.kt
index 42293cf1f..548b69133 100644
--- a/core/data/src/main/java/com/android/mediproject/core/data/remote/medicineapproval/MedicineApprovalRepositoryImpl.kt
+++ b/core/data/src/main/java/com/android/mediproject/core/data/remote/medicineapproval/MedicineApprovalRepositoryImpl.kt
@@ -4,7 +4,7 @@ import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import com.android.mediproject.core.common.DATA_GO_KR_PAGE_SIZE
-import com.android.mediproject.core.database.searchhistory.SearchHistoryDao
+import com.android.mediproject.core.data.search.SearchHistoryRepository
import com.android.mediproject.core.model.medicine.medicineapproval.Item
import com.android.mediproject.core.model.medicine.medicinedetailinfo.MedicineDetailInfoResponse
import com.android.mediproject.core.network.datasource.medicineapproval.MedicineApprovalDataSource
@@ -17,7 +17,7 @@ import kotlinx.coroutines.flow.map
import javax.inject.Inject
class MedicineApprovalRepositoryImpl @Inject constructor(
- private val medicineApprovalDataSource: MedicineApprovalDataSource, private val searchHistoryDao: SearchHistoryDao
+ private val medicineApprovalDataSource: MedicineApprovalDataSource, private val searchHistoryRepository: SearchHistoryRepository
) : MedicineApprovalRepository {
/**
@@ -35,7 +35,7 @@ class MedicineApprovalRepositoryImpl @Inject constructor(
if (itemName == null && entpName == null) {
emptyFlow()
} else {
-
+ searchHistoryRepository.insertSearchHistory(itemName ?: entpName!!)
Pager(config = PagingConfig(pageSize = DATA_GO_KR_PAGE_SIZE, prefetchDistance = 5), pagingSourceFactory = {
MedicineApprovalListDataSourceImpl(
medicineApprovalDataSource, itemName, entpName, medicationType
diff --git a/core/database/build.gradle.kts b/core/database/build.gradle.kts
index 2ffb38115..a2afa5298 100644
--- a/core/database/build.gradle.kts
+++ b/core/database/build.gradle.kts
@@ -1,7 +1,6 @@
plugins {
id("mediproject.android.library")
id("mediproject.android.hilt")
- alias(libs.plugins.ksp)
}
android {
@@ -15,7 +14,7 @@ android {
dependencies {
implementation(project(":core:common"))
implementation(project(":core:model"))
-
implementation(libs.bundles.rooms)
implementation(libs.kotlinx.coroutines.android)
+ kapt(libs.androidx.room.compileKsp)
}
\ No newline at end of file
diff --git a/core/database/src/main/java/com/android/mediproject/core/database/RoomDb.kt b/core/database/src/main/java/com/android/mediproject/core/database/RoomDB.kt
similarity index 72%
rename from core/database/src/main/java/com/android/mediproject/core/database/RoomDb.kt
rename to core/database/src/main/java/com/android/mediproject/core/database/RoomDB.kt
index 84818125c..98542af44 100644
--- a/core/database/src/main/java/com/android/mediproject/core/database/RoomDb.kt
+++ b/core/database/src/main/java/com/android/mediproject/core/database/RoomDB.kt
@@ -6,7 +6,7 @@ import com.android.mediproject.core.database.searchhistory.SearchHistoryDao
import com.android.mediproject.core.database.searchhistory.SearchHistoryDto
-@Database(entities = [SearchHistoryDto::class], version = 1)
-abstract class RoomDb : RoomDatabase() {
+@Database(entities = [SearchHistoryDto::class], version = 1, exportSchema = true)
+abstract class RoomDB : RoomDatabase() {
abstract fun searchHistoryDao(): SearchHistoryDao
}
\ No newline at end of file
diff --git a/core/database/src/main/java/com/android/mediproject/core/database/RoomModule.kt b/core/database/src/main/java/com/android/mediproject/core/database/RoomModule.kt
index 88e1abe42..f732e19cc 100644
--- a/core/database/src/main/java/com/android/mediproject/core/database/RoomModule.kt
+++ b/core/database/src/main/java/com/android/mediproject/core/database/RoomModule.kt
@@ -10,21 +10,20 @@ import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton
-@Module(includes = [DaoModule::class])
+@Module
@InstallIn(SingletonComponent::class)
object RoomModule {
@Provides
@Singleton
- fun provideRoomDb(@ApplicationContext context: Context): RoomDb = Room.databaseBuilder(
- context, RoomDb::class.java, "medi_database"
+ fun provideRoomDb(@ApplicationContext context: Context): RoomDB = Room.databaseBuilder(
+ context, RoomDB::class.java, "medi_database"
).build()
}
-
@Module
@InstallIn(SingletonComponent::class)
object DaoModule {
@Provides
- fun provideSearchHistoryDao(roomDb: RoomDb): SearchHistoryDao = roomDb.searchHistoryDao()
+ fun provideSearchHistoryDao(roomDB: RoomDB): SearchHistoryDao = roomDB.searchHistoryDao()
}
\ No newline at end of file
diff --git a/core/database/src/main/java/com/android/mediproject/core/database/searchhistory/SearchHistoryDao.kt b/core/database/src/main/java/com/android/mediproject/core/database/searchhistory/SearchHistoryDao.kt
index e6f14ee66..c595def4a 100644
--- a/core/database/src/main/java/com/android/mediproject/core/database/searchhistory/SearchHistoryDao.kt
+++ b/core/database/src/main/java/com/android/mediproject/core/database/searchhistory/SearchHistoryDao.kt
@@ -1,7 +1,6 @@
package com.android.mediproject.core.database.searchhistory
import androidx.room.Dao
-import androidx.room.Delete
import androidx.room.Query
import androidx.room.Upsert
import kotlinx.coroutines.flow.Flow
@@ -14,26 +13,25 @@ interface SearchHistoryDao {
* @param searchHistoryDto
*/
@Upsert
- suspend fun insert(searchHistoryDto: SearchHistoryDto)
+ fun insert(searchHistoryDto: SearchHistoryDto)
/**
* id에 해당하는 검색 기록을 삭제한다.
* @param id
*/
- @Delete
- suspend fun delete(id: Long)
+ @Query("DELETE FROM search_history_table WHERE id = :id")
+ fun delete(id: Long)
/**
* 개수 만큼 검색 목록을 가져온다.
* @param count
*/
@Query("SELECT * FROM search_history_table ORDER BY id DESC LIMIT :count")
- suspend fun select(count: Int): Flow>
+ fun select(count: Int): Flow>
/**
* 모든 검색 기록을 삭제한다.
*/
@Query("DELETE FROM search_history_table")
- @Delete
- suspend fun deleteAll()
+ fun deleteAll()
}
\ No newline at end of file
diff --git a/core/database/src/main/java/com/android/mediproject/core/database/searchhistory/SearchHistoryMapper.kt b/core/database/src/main/java/com/android/mediproject/core/database/searchhistory/SearchHistoryMapper.kt
new file mode 100644
index 000000000..fa2ef8e01
--- /dev/null
+++ b/core/database/src/main/java/com/android/mediproject/core/database/searchhistory/SearchHistoryMapper.kt
@@ -0,0 +1,9 @@
+package com.android.mediproject.core.database.searchhistory
+
+import java.time.LocalDateTime
+
+fun SearchHistoryDto.toSearchHistoryItemDto(): com.android.mediproject.core.model.search.local.SearchHistoryItemDto {
+ return com.android.mediproject.core.model.search.local.SearchHistoryItemDto(
+ id = id, query = query, searchedAt = LocalDateTime.parse(this.searchDateTime)
+ )
+}
\ No newline at end of file
diff --git a/core/domain/build.gradle.kts b/core/domain/build.gradle.kts
index 4ef9e7a45..c9bbe35ea 100644
--- a/core/domain/build.gradle.kts
+++ b/core/domain/build.gradle.kts
@@ -22,6 +22,7 @@ dependencies {
implementation(project(":core:model"))
implementation(project(":core:network"))
implementation(project(":core:data"))
+ implementation(project(":core:database"))
implementation(libs.androidx.core.ktx)
implementation(libs.kotlinx.serialization.json)
diff --git a/core/domain/src/main/java/com/android/mediproject/core/domain/SearchHistoryUseCase.kt b/core/domain/src/main/java/com/android/mediproject/core/domain/SearchHistoryUseCase.kt
new file mode 100644
index 000000000..a047cc9d8
--- /dev/null
+++ b/core/domain/src/main/java/com/android/mediproject/core/domain/SearchHistoryUseCase.kt
@@ -0,0 +1,24 @@
+package com.android.mediproject.core.domain
+
+import com.android.mediproject.core.data.search.SearchHistoryRepository
+import com.android.mediproject.core.database.searchhistory.toSearchHistoryItemDto
+import kotlinx.coroutines.flow.map
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+class SearchHistoryUseCase @Inject constructor(
+ private val searchHistoryRepository: SearchHistoryRepository
+) {
+ suspend fun insertSearchHistory(query: String) = searchHistoryRepository.insertSearchHistory(query)
+
+ suspend fun getSearchHistoryList(count: Int) = searchHistoryRepository.getSearchHistoryList(count).map {
+ it.map {
+ it.toSearchHistoryItemDto()
+ }
+ }
+
+ suspend fun deleteSearchHistory(id: Long) = searchHistoryRepository.deleteSearchHistory(id)
+
+ suspend fun deleteAllSearchHistory() = searchHistoryRepository.deleteAllSearchHistory()
+}
\ No newline at end of file
diff --git a/core/model/src/main/java/com/android/mediproject/core/model/local/navargs/BaseNavArgs.kt b/core/model/src/main/java/com/android/mediproject/core/model/local/navargs/BaseNavArgs.kt
index 1f0a6177f..8105bc8e6 100644
--- a/core/model/src/main/java/com/android/mediproject/core/model/local/navargs/BaseNavArgs.kt
+++ b/core/model/src/main/java/com/android/mediproject/core/model/local/navargs/BaseNavArgs.kt
@@ -5,38 +5,53 @@ import androidx.navigation.NavArgs
import kotlin.reflect.KClass
import kotlin.reflect.full.memberProperties
import kotlin.reflect.full.primaryConstructor
+import kotlin.reflect.javaType
abstract class BaseNavArgs(
val className: String
) : NavArgs {
- @Suppress("CAST_NEVER_SUCCEEDS")
fun toBundle(): Bundle {
val result = Bundle()
toMap().forEach { (key, value) ->
- result.putString(key, value)
+ when (value) {
+ null -> return@forEach
+ is String -> result.putString(key, value)
+ is Int -> result.putInt(key, value)
+ is Long -> result.putLong(key, value)
+ is Float -> result.putFloat(key, value)
+ is Boolean -> result.putBoolean(key, value)
+ }
}
return result
}
companion object {
+ @OptIn(ExperimentalStdlibApi::class)
@JvmStatic
fun fromBundle(bundle: Bundle): BaseNavArgs {
- // kotlin reflection Class.forName(bundle.getString("className")!!)
val kClass: KClass = Class.forName(bundle.getString("className")!!).kotlin as KClass
bundle.classLoader = kClass.java.classLoader
val constructor = kClass.primaryConstructor!!
val args = constructor.parameters.map { parameter ->
- bundle.getString(parameter.name, "")
+ val type = parameter.type.javaType
+ with(type) {
+ when (type) {
+ String::class.java -> bundle.getString(parameter.name)
+ Int::class.java -> bundle.getInt(parameter.name)
+ Long::class.java -> bundle.getLong(parameter.name)
+ Float::class.java -> bundle.getFloat(parameter.name)
+ Boolean::class.java -> bundle.getBoolean(parameter.name)
+ else -> throw IllegalArgumentException("Argument \"${parameter.name}\" is marked as non-null but was passed a null value.")
+ }
+ }
}
return constructor.call(*args.toTypedArray())
}
}
- fun toMap(): Map = this::class.memberProperties.let { properties ->
- properties.associate { property ->
- property.name to property.getter.call(this).toString()
- }.toMap()
+ fun toMap(): Map = this::class.memberProperties.associate { property ->
+ property.name to property.getter.call(this)
}
}
\ No newline at end of file
diff --git a/core/model/src/main/java/com/android/mediproject/core/model/search/local/SearchHistoryItemDto.kt b/core/model/src/main/java/com/android/mediproject/core/model/search/local/SearchHistoryItemDto.kt
new file mode 100644
index 000000000..2caaee1ff
--- /dev/null
+++ b/core/model/src/main/java/com/android/mediproject/core/model/search/local/SearchHistoryItemDto.kt
@@ -0,0 +1,9 @@
+package com.android.mediproject.core.model.search.local
+
+import java.time.LocalDateTime
+
+data class SearchHistoryItemDto(
+ val id: Long,
+ val query: String,
+ val searchedAt: LocalDateTime
+)
\ No newline at end of file
diff --git a/core/model/src/main/java/com/android/mediproject/core/model/searchmedicines/local/SearchQueryArgs.kt b/core/model/src/main/java/com/android/mediproject/core/model/searchmedicines/local/SearchQueryArgs.kt
new file mode 100644
index 000000000..643c8568f
--- /dev/null
+++ b/core/model/src/main/java/com/android/mediproject/core/model/searchmedicines/local/SearchQueryArgs.kt
@@ -0,0 +1,12 @@
+package com.android.mediproject.core.model.searchmedicines.local
+
+import com.android.mediproject.core.model.local.navargs.BaseNavArgs
+
+/**
+ * 검색어를 전달할 인자
+ *
+ * @property query 검색어
+ */
+data class SearchQueryArgs(
+ val query: String = ""
+) : BaseNavArgs(SearchQueryArgs::class.java.name)
\ No newline at end of file
diff --git a/core/ui/src/main/java/com/android/mediproject/core/ui/base/view/MediSearchbar.kt b/core/ui/src/main/java/com/android/mediproject/core/ui/base/view/MediSearchbar.kt
index 02853b3dc..4fa8e2c51 100644
--- a/core/ui/src/main/java/com/android/mediproject/core/ui/base/view/MediSearchbar.kt
+++ b/core/ui/src/main/java/com/android/mediproject/core/ui/base/view/MediSearchbar.kt
@@ -4,6 +4,7 @@ import android.annotation.SuppressLint
import android.content.Context
import android.content.res.ColorStateList
import android.graphics.Color
+import android.text.Editable
import android.util.AttributeSet
import android.util.TypedValue
import android.view.MotionEvent
@@ -230,4 +231,11 @@ class MediSearchbar constructor(
super.onInterceptTouchEvent(ev)
}
}
+
+
+ fun getText(): Editable = searchEditView.text
+
+ fun setText(text: String) {
+ searchEditView.setText(text)
+ }
}
\ No newline at end of file
diff --git a/feature/home/src/main/java/com/android/mediproject/feature/home/HomeFragment.kt b/feature/home/src/main/java/com/android/mediproject/feature/home/HomeFragment.kt
index 21fc00258..8dcf2bedd 100644
--- a/feature/home/src/main/java/com/android/mediproject/feature/home/HomeFragment.kt
+++ b/feature/home/src/main/java/com/android/mediproject/feature/home/HomeFragment.kt
@@ -4,6 +4,8 @@ import android.os.Bundle
import android.view.View
import androidx.fragment.app.viewModels
import androidx.navigation.fragment.findNavController
+import com.android.mediproject.core.common.util.navigateByDeepLink
+import com.android.mediproject.core.model.searchmedicines.local.SearchQueryArgs
import com.android.mediproject.core.ui.base.BaseFragment
import com.android.mediproject.feature.comments.recentcommentlist.RecentCommentListFragment
import com.android.mediproject.feature.home.databinding.FragmentHomeBinding
@@ -52,10 +54,7 @@ class HomeFragment : BaseFragment(FragmentHo
*/
private fun initSearchBar() {
binding.searchView.setOnBarClickListener {
- Bundle().apply {
- putString("searchQuery", null)
- findNavController().navigate(R.id.action_homeFragment_to_searchMedicinesFragment, this)
- }
+ findNavController().navigate(HomeFragmentDirections.actionHomeFragmentToSearchMedicinesFragment())
}
}
@@ -74,13 +73,10 @@ class HomeFragment : BaseFragment(FragmentHo
}
setFragmentResultListener(RecentSearchListFragment.ResultKey.RESULT_KEY.name, viewLifecycleOwner) { _, bundle ->
bundle.apply {
- getString(RecentSearchListFragment.ResultKey.WORD.name).also {
- Bundle().apply {
- putString("searchQuery", it)
- findNavController().navigate(R.id.action_homeFragment_to_searchMedicinesFragment, this)
- }
- }
-
+ findNavController().navigateByDeepLink(
+ "medilens://main/search/recentSearchListFragment",
+ SearchQueryArgs(getString(RecentSearchListFragment.ResultKey.WORD.name) ?: "")
+ )
}
}
}
diff --git a/feature/home/src/main/res/layout/fragment_home.xml b/feature/home/src/main/res/layout/fragment_home.xml
index 76744e66d..e6d4dee5c 100644
--- a/feature/home/src/main/res/layout/fragment_home.xml
+++ b/feature/home/src/main/res/layout/fragment_home.xml
@@ -68,7 +68,7 @@
android:layout_marginTop="69dp"
android:layout_marginBottom="58dp"
android:bufferType="spannable"
- android:lineSpacingMultiplier="1.2"
+ android:lineSpacingMultiplier="1.1"
android:text="@{viewModel.headerText}"
android:textColor="@color/white"
android:textSize="23sp"
diff --git a/feature/home/src/main/res/navigation/home_nav.xml b/feature/home/src/main/res/navigation/home_nav.xml
index aeef86341..3383d2cfe 100644
--- a/feature/home/src/main/res/navigation/home_nav.xml
+++ b/feature/home/src/main/res/navigation/home_nav.xml
@@ -10,25 +10,16 @@
android:name="com.android.mediproject.feature.home.HomeFragment"
android:label="HomeFragment"
tools:layout="@layout/fragment_home">
-
-
-
+
+
-
-
-
-
-
-
+ tools:layout="@layout/fragment_search_medicines"
+ android:label="SearchMedicinesFragment" />
\ No newline at end of file
diff --git a/feature/search/src/main/java/com/android/mediproject/feature/search/SearchMedicinesFragment.kt b/feature/search/src/main/java/com/android/mediproject/feature/search/SearchMedicinesFragment.kt
index db8a87807..b2491c568 100644
--- a/feature/search/src/main/java/com/android/mediproject/feature/search/SearchMedicinesFragment.kt
+++ b/feature/search/src/main/java/com/android/mediproject/feature/search/SearchMedicinesFragment.kt
@@ -28,46 +28,40 @@ class SearchMedicinesFragment :
// contents_fragment_container_view 에 최근 검색 목록과 검색 결과 목록 화면 두 개를 띄운다.
initSearchBar()
- arguments?.apply {
- getString("searchQuery")?.also {
- binding.searchView.searchWithQuery(query = it)
- }
- }
-
viewLifecycleOwner.repeatOnStarted {
fragmentViewModel.searchQuery.collect { query ->
- if (query.isNotBlank()) {
- binding.contentsFragmentContainerView.findNavController().also { navController ->
- navController.currentDestination?.also { currentDestination ->
- if (currentDestination.id == R.id.manualSearchResultFragment) navController.navigate(R.id.action_manualSearchResultFragment_self)
- else navController.navigate(
- RecentSearchListFragmentDirections.actionRecentSearchListFragmentToManualSearchResultFragment()
- )
-
- }
- }
- }
+ // Flow로 받은 문자열이 일치하는 경우에만 searchView에 표시한다.
+ if (!binding.searchView.getText().contentEquals(query)) binding.searchView.setText(query)
}
}
+
}
- override fun onStart() {
- super.onStart()
+ private fun moveToManualSearchResultFragment() {
+ val navController = binding.contentsFragmentContainerView.findNavController()
+ navController.currentDestination?.also { currentDestination ->
+ // 현재 프래그먼트가 검색 결과 프래그먼트인 경우에는 백스택에서 검색 결과 프래그먼트를 제거하고 검색 결과 프래그먼트로
+ // 다시 이동한다.
+ // 검색 결과 프래그먼트가 아닌 경우에는 검색 결과 프래그먼트로 이동한다.
+ if (currentDestination.id == R.id.manualSearchResultFragment) navController.navigate(R.id.action_manualSearchResultFragment_self)
+ else navController.navigate(
+ RecentSearchListFragmentDirections.actionRecentSearchListFragmentToManualSearchResultFragment()
+ )
+ }
+ }
- binding.apply {
- childFragmentManager.findFragmentById(R.id.contentsFragmentContainerView)?.also { navHostFragment ->
- navHostFragment.childFragmentManager.apply {
- setFragmentResultListener(
- RecentSearchListFragment.ResultKey.RESULT_KEY.name, navHostFragment.viewLifecycleOwner
- ) { _, bundle ->
+ override fun onViewStateRestored(savedInstanceState: Bundle?) {
+ super.onViewStateRestored(savedInstanceState)
- bundle.apply {
- getString(RecentSearchListFragment.ResultKey.WORD.name)?.also {
- binding.searchView.searchWithQuery(query = it)
- }
- }
- }
+ childFragmentManager.findFragmentById(R.id.contentsFragmentContainerView)?.also { navHostFragment ->
+ val childFragmentManager = navHostFragment.childFragmentManager
+ childFragmentManager.setFragmentResultListener(
+ RecentSearchListFragment.ResultKey.RESULT_KEY.name, navHostFragment.viewLifecycleOwner
+ ) { _, bundle ->
+ bundle.getString(RecentSearchListFragment.ResultKey.WORD.name)?.also {
+ binding.searchView.searchWithQuery(it)
}
+
}
}
}
@@ -83,7 +77,8 @@ class SearchMedicinesFragment :
binding.searchView.setOnSearchBtnClickListener(object : MediSearchbar.SearchQueryCallback {
override fun onSearchQuery(query: String) {
hideKeyboard()
- fragmentViewModel.searchMedicines(query)
+ fragmentViewModel.setQuery(query)
+ moveToManualSearchResultFragment()
}
override fun onEmptyQuery() {
diff --git a/feature/search/src/main/java/com/android/mediproject/feature/search/SearchMedicinesViewModel.kt b/feature/search/src/main/java/com/android/mediproject/feature/search/SearchMedicinesViewModel.kt
index 0536b46a2..aa875f6a5 100644
--- a/feature/search/src/main/java/com/android/mediproject/feature/search/SearchMedicinesViewModel.kt
+++ b/feature/search/src/main/java/com/android/mediproject/feature/search/SearchMedicinesViewModel.kt
@@ -11,12 +11,15 @@ import javax.inject.Inject
@HiltViewModel
class SearchMedicinesViewModel @Inject constructor() : BaseViewModel() {
- private val _searchQuery = MutableStateFlow("")
+ private val _searchQuery = MutableStateFlow("")
val searchQuery = _searchQuery.asStateFlow()
- fun searchMedicines(query: String) {
- viewModelScope.launch {
- _searchQuery.emit(query)
- }
+
+ /**
+ * 검색어 저장
+ */
+ fun setQuery(query: String) = viewModelScope.launch {
+ _searchQuery.value = query
}
+
}
\ No newline at end of file
diff --git a/feature/search/src/main/java/com/android/mediproject/feature/search/recentsearchlist/RecentSearchListFragment.kt b/feature/search/src/main/java/com/android/mediproject/feature/search/recentsearchlist/RecentSearchListFragment.kt
index 1ead8c9ae..a98e9e98c 100644
--- a/feature/search/src/main/java/com/android/mediproject/feature/search/recentsearchlist/RecentSearchListFragment.kt
+++ b/feature/search/src/main/java/com/android/mediproject/feature/search/recentsearchlist/RecentSearchListFragment.kt
@@ -4,12 +4,15 @@ import android.os.Bundle
import android.view.View
import android.view.ViewGroup.LayoutParams
import androidx.core.os.bundleOf
-import androidx.fragment.app.viewModels
+import androidx.fragment.app.activityViewModels
+import com.android.mediproject.core.model.search.local.SearchHistoryItemDto
import com.android.mediproject.core.ui.base.BaseFragment
import com.android.mediproject.core.ui.base.view.ButtonChip
import com.android.mediproject.feature.search.databinding.FragmentRecentSearchListBinding
import com.google.android.flexbox.FlexboxLayout
import dagger.hilt.android.AndroidEntryPoint
+import kotlinx.coroutines.flow.collectLatest
+import repeatOnStarted
/**
@@ -25,12 +28,20 @@ class RecentSearchListFragment :
RESULT_KEY, WORD
}
- override val fragmentViewModel: RecentSearchListViewModel by viewModels()
+ override val fragmentViewModel: RecentSearchListViewModel by activityViewModels()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
- addHistoryItemChips()
initHeader()
+
+ viewLifecycleOwner.repeatOnStarted {
+ fragmentViewModel.searchHistoryList().collectLatest {
+ // 최근 검색 목록을 가져옵니다.
+ it.forEach { searchHistoryItemDto ->
+ addHistoryItemChips(searchHistoryItemDto)
+ }
+ }
+ }
}
/**
@@ -38,31 +49,34 @@ class RecentSearchListFragment :
*
* 클릭 시 관련 로직을 수행하도록 합니다.
*/
- private fun addHistoryItemChips() {
+ private fun addHistoryItemChips(searchHistoryItemDto: SearchHistoryItemDto) {
binding.apply {
val horizontalSpace = resources.getDimension(com.android.mediproject.core.ui.R.dimen.dp_4).toInt()
+ this.searchHistoryList.addView(ButtonChip(requireContext()).apply {
+ layoutParams = FlexboxLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT).apply {
+ setMargins(horizontalSpace, 0, horizontalSpace, 0)
+ }
+ data = searchHistoryItemDto.query
+ setChipText(data.toString())
+ setOnChipClickListener {
+ onClicked(searchHistoryItemDto.query)
+ }
+ })
+ }
+ }
- repeat(5) {
- this.searchHistoryList.addView(ButtonChip(requireContext()).apply {
- layoutParams = FlexboxLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT).apply {
- setMargins(horizontalSpace, 0, horizontalSpace, 0)
- }
- data = it.toString()
- setChipText("검색어 $it")
- setOnChipClickListener {
- it?.also {
- parentFragmentManager.apply {
- setFragmentResult(
- ResultKey.RESULT_KEY.name, bundleOf(
- ResultKey.WORD.name to it
- )
- )
- }
+ override fun onDestroyView() {
+ binding.searchHistoryList.removeAllViews()
+ super.onDestroyView()
+ }
- }
- }
- })
- }
+ private fun onClicked(query: String) {
+ parentFragmentManager.apply {
+ setFragmentResult(
+ ResultKey.RESULT_KEY.name, bundleOf(
+ ResultKey.WORD.name to query
+ )
+ )
}
}
diff --git a/feature/search/src/main/java/com/android/mediproject/feature/search/recentsearchlist/RecentSearchListViewModel.kt b/feature/search/src/main/java/com/android/mediproject/feature/search/recentsearchlist/RecentSearchListViewModel.kt
index 9f2c88833..49bfd9c0c 100644
--- a/feature/search/src/main/java/com/android/mediproject/feature/search/recentsearchlist/RecentSearchListViewModel.kt
+++ b/feature/search/src/main/java/com/android/mediproject/feature/search/recentsearchlist/RecentSearchListViewModel.kt
@@ -1,10 +1,22 @@
package com.android.mediproject.feature.search.recentsearchlist
+import androidx.lifecycle.viewModelScope
+import com.android.mediproject.core.domain.SearchHistoryUseCase
import com.android.mediproject.core.ui.base.BaseViewModel
import dagger.hilt.android.lifecycle.HiltViewModel
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.shareIn
import javax.inject.Inject
@HiltViewModel
-class RecentSearchListViewModel @Inject constructor() : BaseViewModel() {
-
+class RecentSearchListViewModel @Inject constructor(
+ private val searchHistoryUseCase: SearchHistoryUseCase
+) : BaseViewModel() {
+ val searchHistoryList by lazy {
+ suspend {
+ searchHistoryUseCase.getSearchHistoryList(6).shareIn(
+ viewModelScope, started = SharingStarted.Lazily, replay = 1
+ )
+ }
+ }
}
\ No newline at end of file
diff --git a/feature/search/src/main/java/com/android/mediproject/feature/search/result/manual/ManualSearchResultFragment.kt b/feature/search/src/main/java/com/android/mediproject/feature/search/result/manual/ManualSearchResultFragment.kt
index 0b2967949..25e2f62bd 100644
--- a/feature/search/src/main/java/com/android/mediproject/feature/search/result/manual/ManualSearchResultFragment.kt
+++ b/feature/search/src/main/java/com/android/mediproject/feature/search/result/manual/ManualSearchResultFragment.kt
@@ -5,6 +5,7 @@ import android.view.View
import androidx.core.content.ContextCompat
import androidx.fragment.app.viewModels
import androidx.navigation.findNavController
+import androidx.navigation.fragment.navArgs
import androidx.paging.map
import androidx.recyclerview.widget.DividerItemDecoration
import com.android.mediproject.core.common.paging.setOnStateChangedListener
@@ -31,6 +32,8 @@ class ManualSearchResultFragment :
override val fragmentViewModel: ManualSearchResultViewModel by viewModels()
+ private val searchQueryArgs: ManualSearchResultFragmentArgs by navArgs()
+
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
@@ -38,6 +41,10 @@ class ManualSearchResultFragment :
binding.apply {
viewModel = fragmentViewModel
+ if (searchQueryArgs.query.isNotEmpty()) {
+ searchMedicinesViewModel.setQuery(searchQueryArgs.query)
+ }
+
val searchResultListAdapter = ApprovedMedicinesAdapter().also {
it.withLoadStateHeaderAndFooter(header = PagingLoadStateAdapter { it.retry() },
footer = PagingLoadStateAdapter { it.retry() })
@@ -79,13 +86,11 @@ class ManualSearchResultFragment :
// 검색 결과를 수신하면 리스트에 표시한다.
launch {
fragmentViewModel.searchResultFlow.collectLatest {
- it.let { pager ->
- pager.map { item ->
- item.onClick = this@ManualSearchResultFragment::openMedicineInfo
- item
- }
- }.also { pagingData ->
- searchResultListAdapter.submitData(pagingData)
+ it.map { item ->
+ item.onClick = this@ManualSearchResultFragment::openMedicineInfo
+ item
+ }.apply {
+ searchResultListAdapter.submitData(this)
}
}
}
diff --git a/feature/search/src/main/res/layout/fragment_search_medicines.xml b/feature/search/src/main/res/layout/fragment_search_medicines.xml
index ee9d4093e..85d7f86a0 100644
--- a/feature/search/src/main/res/layout/fragment_search_medicines.xml
+++ b/feature/search/src/main/res/layout/fragment_search_medicines.xml
@@ -34,6 +34,7 @@
android:layout_marginTop="27dp"
app:ai_text="@string/search_with_ai"
app:camera_icon="@drawable/baseline_camera_24"
+ app:ime_options="actionSearch"
app:is_all_btn="false"
app:layout_constraintBottom_toTopOf="@id/contentsFragmentContainerView"
app:layout_constraintLeft_toLeftOf="parent"
@@ -42,7 +43,6 @@
app:layout_goneMarginTop="30dp"
app:search_hint="@string/search_hint"
app:search_icon="@drawable/baseline_search_24"
- app:ime_options="actionSearch"
/>
+
+
+
+
-
+
\ No newline at end of file