Skip to content

Commit

Permalink
선호학과 정보 저장 (#366)
Browse files Browse the repository at this point in the history
  • Loading branch information
plgafhd authored Oct 25, 2024
1 parent a469703 commit f5eee38
Show file tree
Hide file tree
Showing 8 changed files with 189 additions and 33 deletions.
10 changes: 10 additions & 0 deletions app/src/main/java/com/wafflestudio/snutt2/data/SNUTTStorage.kt
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,16 @@ class SNUTTStorage @Inject constructor(
),
)

val recentSearchedDepartments = PrefValue<List<TagDto>>(
prefContext,
PrefListValueMetaData(
domain = DOMAIN_SCOPE_LOGIN,
key = "recent_searched_departments",
type = TagDto::class.java,
defaultValue = listOf(),
),
)

fun clearLoginScope() {
prefContext.clear(DOMAIN_SCOPE_LOGIN)
prefContext.clear(DOMAIN_SCOPE_CURRENT_VERSION)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@ import com.wafflestudio.snutt2.lib.network.dto.core.LectureDto
import com.wafflestudio.snutt2.model.SearchTimeDto
import com.wafflestudio.snutt2.model.TagDto
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow

interface LectureSearchRepository {

val recentSearchedDepartments: StateFlow<List<TagDto>>

fun getLectureSearchResultStream(
year: Long,
semester: Long,
Expand All @@ -23,4 +26,8 @@ interface LectureSearchRepository {
suspend fun getBuildings(
places: String,
): List<LectureBuildingDto>

fun storeRecentSearchedDepartment(tag: TagDto)

fun removeRecentSearchedDepartment(tag: TagDto)
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.wafflestudio.snutt2.data.lecture_search
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import com.wafflestudio.snutt2.data.SNUTTStorage
import com.wafflestudio.snutt2.lib.SnuttUrls
import com.wafflestudio.snutt2.lib.network.SNUTTRestApi
import com.wafflestudio.snutt2.lib.network.dto.core.LectureBuildingDto
Expand All @@ -18,8 +19,11 @@ import javax.inject.Singleton
class LectureSearchRepositoryImpl @Inject constructor(
private val api: SNUTTRestApi,
private val snuttUrls: SnuttUrls,
private val storage: SNUTTStorage,
) : LectureSearchRepository {

override val recentSearchedDepartments = storage.recentSearchedDepartments.asStateFlow()

override fun getLectureSearchResultStream(
year: Long,
semester: Long,
Expand Down Expand Up @@ -66,6 +70,19 @@ class LectureSearchRepositoryImpl @Inject constructor(
return response.content
}

override fun storeRecentSearchedDepartment(tag: TagDto) {
val previousStoredTags = storage.recentSearchedDepartments.get()

storage.recentSearchedDepartments.update(
(previousStoredTags.filter { it != tag } + tag).takeLast(5),
)
}

override fun removeRecentSearchedDepartment(tag: TagDto) {
val previousStoredTags = storage.recentSearchedDepartments.get()
storage.recentSearchedDepartments.update(previousStoredTags - tag)
}

companion object {
const val LECTURES_LOAD_PAGE_SIZE = 30
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,9 +169,13 @@ fun SearchPage(
launchSuspendApi(apiOnProgress, apiOnError) {
searchViewModel.query()
}
searchViewModel.storeRecentSearchedDepartments()
}
scope.launch { bottomSheet.hide() }
},
hideBottomSheet = {
scope.launch { bottomSheet.hide() }
},
draggedTimeBlock = draggedTimeBlock,
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.flatMapLatest
Expand Down Expand Up @@ -88,6 +89,8 @@ class SearchViewModel @Inject constructor(
// 검색 쿼리에 들어가는 시간대 검색 시간대 목록
private val _searchTimeList = MutableStateFlow<List<SearchTimeDto>?>(null)

val recentSearchedDepartments: StateFlow<List<TagDto>> = lectureSearchRepository.recentSearchedDepartments

init {
viewModelScope.launch {
semesterChange.distinctUntilChanged().collectLatest {
Expand All @@ -113,6 +116,19 @@ class SearchViewModel @Inject constructor(
.map { it.toDataWithState(selectedTags.contains(it)) }
}.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), emptyList())

val selectableRecentSearchedDepartments: StateFlow<List<Selectable<TagDto>>> = combine(
tagsByTagType, recentSearchedDepartments, _selectedTags,
) { tagsByTagType, recentDepartments, selectedTags ->
val tagItemsByTagType = tagsByTagType.map { tag -> tag.item }
recentDepartments.filter { recentDepartment ->
tagItemsByTagType.contains(recentDepartment)
}.map { it.toDataWithState(selectedTags.contains(it)) }
}.stateIn(
viewModelScope,
SharingStarted.Eagerly,
emptyList(),
)

val bookmarkList = combine(
_getBookmarkListSignal.flatMapLatest {
try {
Expand Down Expand Up @@ -254,6 +270,16 @@ class SearchViewModel @Inject constructor(
}
}

fun storeRecentSearchedDepartments() {
_selectedTags.value.filter { it.type == TagType.DEPARTMENT }.forEach { tag ->
lectureSearchRepository.storeRecentSearchedDepartment(tag)
}
}

fun removeRecentSearchedDepartment(tag: TagDto) {
lectureSearchRepository.removeRecentSearchedDepartment(tag)
}

private suspend fun clear() {
_searchTitle.emit("")
_selectedLecture.emit(null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.wafflestudio.snutt2.views.logged_in.home.search.search_option

import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
Expand All @@ -14,7 +15,10 @@ import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.SubcomposeLayout
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import com.wafflestudio.snutt2.components.compose.ExitIcon
import com.wafflestudio.snutt2.components.compose.clicks
import com.wafflestudio.snutt2.model.TagDto
import com.wafflestudio.snutt2.ui.SNUTTColors
import com.wafflestudio.snutt2.views.logged_in.home.search.SearchViewModel
Expand All @@ -28,11 +32,13 @@ private enum class OptionSheetMode {
@Composable
fun SearchOptionSheet(
applyOption: () -> Unit,
hideBottomSheet: () -> Unit,
draggedTimeBlock: State<List<List<Boolean>>>,
) {
val viewModel = hiltViewModel<SearchViewModel>()
val tagsByTagType by viewModel.tagsByTagType.collectAsState()
val selectedTagType by viewModel.selectedTagType.collectAsState()
val recentSearchedDepartments by viewModel.selectableRecentSearchedDepartments.collectAsState()
val scope = rememberCoroutineScope()

var optionSheetMode by remember {
Expand Down Expand Up @@ -79,6 +85,7 @@ fun SearchOptionSheet(
// tag column의 높이를 tagType column의 높이로 설정
height = tagTypePlaceable.height.toDp(),
),
recentSearchedDepartments = recentSearchedDepartments,
tagsByTagType = tagsByTagType,
selectedTimes = draggedTimeBlock,
baseAnimatedFloat = baseAnimatedFloat,
Expand All @@ -92,6 +99,9 @@ fun SearchOptionSheet(
viewModel.toggleTag(it)
}
},
onRemoveRecent = {
viewModel.removeRecentSearchedDepartment(it)
},
openTimeSelectSheet = {
optionSheetMode = OptionSheetMode.TimeSelect
},
Expand Down Expand Up @@ -128,6 +138,14 @@ fun SearchOptionSheet(
SearchOptionConfirmButton(baseAnimatedFloat, applyOption)
}.first().measure(constraints)

val closeBottomSheetPlaceable = subcompose(slotId = 5) {
Row(
modifier = Modifier.clicks { hideBottomSheet() },
) {
ExitIcon()
}
}.first().measure(constraints)

// 한번만 계산, 할당
if (normalSheetHeightPx == 0 && maxSheetHeightPx == 0) {
normalSheetHeightPx =
Expand All @@ -153,6 +171,10 @@ fun SearchOptionSheet(
tagTypePlaceable.height + SearchOptionSheetConstants.TopMargin.toPx()
.roundToInt(),
)
closeBottomSheetPlaceable.placeRelative(
tagTypePlaceable.width + tagListPlaceable.width - 52.dp.toPx().roundToInt(),
(SearchOptionSheetConstants.TopMargin.toPx().roundToInt() - 32.dp.toPx().roundToInt()) / 2,
)
if (baseAnimatedFloat.value != 0f) dragSheetPlaceable.placeRelative(0, 0)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import com.wafflestudio.snutt2.ui.isDarkMode
object SearchOptionSheetConstants {
const val TagColumnWidthDp = 120
const val MaxHeightRatio = 0.85f
val TopMargin = 40.dp
val TopMargin = 68.dp
val AnimationSpec = spring(
visibilityThreshold = 1f,
stiffness = 200f,
Expand Down
Loading

0 comments on commit f5eee38

Please sign in to comment.