Skip to content

Commit

Permalink
#91 수동 검색 로직 작업 완료, 검색 기록 데이터 베이스 저장 로직 제작 완료
Browse files Browse the repository at this point in the history
  • Loading branch information
pknujsp committed May 30, 2023
1 parent a83ad40 commit 652c2c1
Show file tree
Hide file tree
Showing 12 changed files with 94 additions and 59 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,20 @@ object LoadingDialog {

fun showLoadingDialog(context: Context, textMessage: String?) {
dismiss()
AlertDialog.Builder(context).setView(ProgressIndicator(context, null, textMessage)).setCancelable(false).create().also {
it.window?.setBackgroundDrawableResource(android.R.color.transparent)
it.window?.attributes = it.window?.attributes?.apply {
width = ViewGroup.LayoutParams.WRAP_CONTENT
height = ViewGroup.LayoutParams.WRAP_CONTENT
AlertDialog.Builder(context).setView(ProgressIndicator(context, textMessage)).setCancelable(false).create().also {
it.window?.apply {
setClipToOutline(true)
setElevation(8f)
// shadow

attributes = attributes.apply {
width = ViewGroup.LayoutParams.WRAP_CONTENT
height = ViewGroup.LayoutParams.WRAP_CONTENT
dimAmount = 0.5f
}
}
it.setCanceledOnTouchOutside(false)
dismiss()
dialog = it
it.show()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ package com.android.mediproject.core.common.dialog

import android.content.Context
import android.graphics.Color
import android.graphics.Typeface
import android.util.AttributeSet
import android.util.TypedValue
import android.view.Gravity
import android.widget.TextView
Expand All @@ -14,7 +12,7 @@ import com.airbnb.lottie.LottieDrawable.INFINITE
import com.android.mediproject.core.common.R
import com.android.mediproject.core.common.uiutil.dpToPx

class ProgressIndicator(context: Context, attrs: AttributeSet?, textMessage: String?) : ConstraintLayout(context, attrs) {
class ProgressIndicator(context: Context, textMessage: String?) : ConstraintLayout(context) {

private val lottie = LottieAnimationView(context).apply {
setAnimation(R.raw.bluedottedprogress)
Expand All @@ -26,7 +24,6 @@ class ProgressIndicator(context: Context, attrs: AttributeSet?, textMessage: Str
textMessage?.apply {
textView.text = this
textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 15f)
textView.typeface = Typeface.create("sans-serif-condensed", Typeface.NORMAL)
textView.setTextColor(Color.DKGRAY)
} ?: run { textView.visibility = GONE }

Expand Down
13 changes: 9 additions & 4 deletions core/common/src/main/res/drawable/progress_background.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<solid android:color="#a3a3a6"/>
<corners android:radius="28dp"/>
<padding android:left="20dp" android:right="20dp" android:top="24dp" android:bottom="24dp"/>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#ffffff" />
<corners android:radius="28dp" />
<padding
android:bottom="20dp"
android:left="24dp"
android:right="24dp"
android:top="20dp" />
</shape>
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,12 @@ import kotlinx.coroutines.runBlocking
import javax.inject.Inject

class SearchHistoryRepositoryImpl @Inject constructor(
private val searchHistoryDao: SearchHistoryDao,
private val searchHistoryDao: SearchHistoryDao
) : SearchHistoryRepository {
override suspend fun insertSearchHistory(searchHistoryDto: SearchHistoryDto) = runBlocking {
searchHistoryDto.apply {
searchHistoryDao.insert(searchHistoryDto.apply {
query = query.trim()
}
if (!searchHistoryDao.isExist(searchHistoryDto.query)) searchHistoryDao.insert(searchHistoryDto)
})
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ package com.android.mediproject.core.database

import androidx.room.Database
import androidx.room.RoomDatabase
import androidx.room.TypeConverters
import com.android.mediproject.core.database.searchhistory.SearchHistoryDao
import com.android.mediproject.core.database.searchhistory.SearchHistoryDto


@Database(entities = [SearchHistoryDto::class], version = 1, exportSchema = true)
@TypeConverters(RoomTypeConverter::class)
abstract class RoomDB : RoomDatabase() {
abstract fun searchHistoryDao(): SearchHistoryDao
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.android.mediproject.core.database

import androidx.room.TypeConverter
import java.time.LocalDateTime

object RoomTypeConverter {
@TypeConverter
fun fromTimeStamp(timeStamp: String?): LocalDateTime? = timeStamp?.let { LocalDateTime.parse(it) }

@TypeConverter
fun toTimeStamp(date: LocalDateTime?): String? = date?.toString()

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,44 @@ import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import androidx.room.Transaction
import kotlinx.coroutines.flow.Flow

@Dao
interface SearchHistoryDao {
abstract class SearchHistoryDao {

/**
* 검색 기록을 추가한다.
* @param searchHistoryDto
*/
@Transaction
open suspend fun insert(SearchHistoryDto: SearchHistoryDto) {
if (!isExist(SearchHistoryDto.query)) realInsert(SearchHistoryDto)
}

@Insert(entity = SearchHistoryDto::class, onConflict = OnConflictStrategy.IGNORE)
suspend fun insert(SearchHistoryDto: SearchHistoryDto)
abstract suspend fun realInsert(SearchHistoryDto: SearchHistoryDto)

/**
* id에 해당하는 검색 기록을 삭제한다.
* @param id
*/
@Query("DELETE FROM search_history_table WHERE id = :id")
suspend fun delete(id: Long)
abstract suspend fun delete(id: Long)

/**
* 개수 만큼 검색 목록을 가져온다.
* @param count
*/
@Query("SELECT * FROM search_history_table ORDER BY id DESC LIMIT :count")
fun select(count: Int): Flow<List<SearchHistoryDto>>
abstract fun select(count: Int): Flow<List<SearchHistoryDto>>

/**
* 모든 검색 기록을 삭제한다.
*/
@Query("DELETE FROM search_history_table")
suspend fun deleteAll()
abstract suspend fun deleteAll()

@Query("SELECT EXISTS (SELECT * FROM search_history_table WHERE `query` = :query)")
suspend fun isExist(query: String): Boolean
abstract suspend fun isExist(query: String): Boolean
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.android.mediproject.core.database.searchhistory
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import java.time.LocalDateTime

@Entity(tableName = "search_history_table")
data class SearchHistoryDto(
Expand All @@ -11,9 +12,10 @@ data class SearchHistoryDto(
@ColumnInfo(name = "query") var query: String,

@ColumnInfo(
name = "search_date_time", defaultValue = "CURRENT_TIMESTAMP"
) val searchDateTime: String
name = "search_date_time"
) val searchDateTime: LocalDateTime

) {
constructor(query: String) : this(0, query, "")
constructor(query: String) : this(0, query, LocalDateTime.now())

}
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
package com.android.mediproject.core.database.searchhistory

import java.time.LocalDateTime
import java.time.format.DateTimeFormatter

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, dateTimeFormatter)
id = id, query = query, searchedAt = searchDateTime
)
}

private val dateTimeFormatter by lazy { DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss") }
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ class SearchMedicinesFragment :
arguments?.getString("query")?.takeIf {
it.isNotEmpty()
}?.also {
binding.searchView.setText(it)
fragmentViewModel.setQuery(it)
binding.contentsFragmentContainerView.findNavController().navigate(
RecentSearchListFragmentDirections.actionRecentSearchListFragmentToManualSearchResultFragment(),
NavOptions.Builder().setPopUpTo(R.id.manualSearchResultFragment, true).build()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import androidx.paging.map
import androidx.recyclerview.widget.DividerItemDecoration
import com.android.mediproject.core.common.paging.setOnStateChangedListener
import com.android.mediproject.core.common.util.navigateByDeepLink
import com.android.mediproject.core.common.viewmodel.UiState
import com.android.mediproject.core.model.constants.MedicationType
import com.android.mediproject.core.model.local.navargs.MedicineInfoArgs
import com.android.mediproject.core.model.medicine.medicineapproval.ApprovedMedicineItemDto
Expand All @@ -18,8 +19,6 @@ import com.android.mediproject.feature.search.R
import com.android.mediproject.feature.search.SearchMedicinesViewModel
import com.android.mediproject.feature.search.databinding.FragmentManualSearchResultBinding
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import repeatOnStarted

Expand Down Expand Up @@ -77,19 +76,28 @@ class ManualSearchResultFragment :
viewLifecycleOwner.repeatOnStarted {
// 검색 결과를 수신하면 리스트에 표시한다.
launch {
fragmentViewModel.searchResultFlow.collectLatest {
it.map { item ->
item.onClick = this@ManualSearchResultFragment::openMedicineInfo
item
}.apply {
searchResultListAdapter.submitData(this)
fragmentViewModel.searchResultFlow.collect {
when (it) {
is UiState.Success -> {
searchResultListAdapter.submitData(it.data.map { item ->
item.onClick = this@ManualSearchResultFragment::openMedicineInfo
item
})
}

is UiState.Error -> {
toast(it.message)
}

is UiState.Initial -> {}
is UiState.Loading -> {}
}
}
}

// 검색어가 변경되면 검색을 다시 수행한다.
launch {
searchMedicinesViewModel.searchQuery.first().also { query ->
searchMedicinesViewModel.searchQuery.value.also { query ->
fragmentViewModel.searchMedicinesByItemName(query)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,14 @@ import com.android.mediproject.core.model.parameters.ApprovalListSearchParameter
import com.android.mediproject.core.ui.base.BaseViewModel
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.last
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import javax.inject.Inject
Expand All @@ -43,19 +44,19 @@ class ManualSearchResultViewModel @Inject constructor(
)
val searchParameter = _searchParameter.asStateFlow()

val searchResultFlow: Flow<UiState<PagingData<ApprovedMedicineItemDto>>> = searchParameter.flatMapLatest { parameter ->
if (parameter.entpName.isNullOrEmpty() && parameter.itemName.isNullOrEmpty()) {
flowOf(UiState.Error("검색어를 입력해주세요"))
} else {
flowOf(
UiState.Success(
getMedicineApprovalListUseCase.invoke(
parameter
).last()
)
)
}
}.flowOn(ioDispatcher)
val searchResultFlow: StateFlow<UiState<PagingData<ApprovedMedicineItemDto>>> by lazy {
searchParameter.flatMapLatest { parameter ->
if (parameter.entpName.isNullOrEmpty() && parameter.itemName.isNullOrEmpty()) {
flowOf(UiState.Error("검색어를 입력해주세요."))
} else {
getMedicineApprovalListUseCase(parameter).flatMapLatest {
flowOf(UiState.Success(it))
}
}
}.catch {
flowOf(UiState.Error(it.message ?: "알 수 없는 오류가 발생했습니다."))
}.stateIn(viewModelScope, started = SharingStarted.Lazily, initialValue = UiState.Loading)
}

/**
* 의약품명으로 검색
Expand Down

0 comments on commit 652c2c1

Please sign in to comment.