-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
➕ Refactored code and added the first search option: regex search mode
- Loading branch information
Showing
15 changed files
with
274 additions
and
49 deletions.
There are no files selected for viewing
20 changes: 20 additions & 0 deletions
20
...in/kotlin/mikufan/cx/songfinder/backend/controller/mainpage/RegexMatchOptionController.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package mikufan.cx.songfinder.backend.controller.mainpage | ||
|
||
import androidx.compose.runtime.State | ||
import mikufan.cx.songfinder.backend.statemodel.SearchOptionsStateModel | ||
import mikufan.cx.songfinder.backend.statemodel.SearchRegexOption | ||
import org.springframework.stereotype.Controller | ||
|
||
@Controller | ||
class RegexMatchOptionController( | ||
private val searchOptionsStateModel: SearchOptionsStateModel, | ||
private val songSearchIntermediateController: SongSearchIntermediateController | ||
) { | ||
|
||
val currentRegexOptionState: State<SearchRegexOption> = searchOptionsStateModel.searchRegexOptionState | ||
|
||
suspend fun setRegexOption(newOption: SearchRegexOption) { | ||
searchOptionsStateModel.searchRegexOptionState.value = newOption | ||
songSearchIntermediateController.triggerSearch(100) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
70 changes: 70 additions & 0 deletions
70
...lin/mikufan/cx/songfinder/backend/controller/mainpage/SongSearchIntermediateController.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
package mikufan.cx.songfinder.backend.controller.mainpage | ||
|
||
import kotlinx.coroutines.* | ||
import mikufan.cx.inlinelogging.KInlineLogging | ||
import mikufan.cx.songfinder.backend.service.SongSearchService | ||
import mikufan.cx.songfinder.backend.statemodel.SearchInputStateModel | ||
import mikufan.cx.songfinder.backend.statemodel.SearchOptionsStateModel | ||
import mikufan.cx.songfinder.backend.statemodel.SearchResultStateModel | ||
import org.springframework.stereotype.Controller | ||
|
||
/** | ||
* Intermediate controller for song search functionality. | ||
* This class handles triggering the search and updating the search state. | ||
* @property searchInputStateModel The state model for search input. | ||
* @property searchOptionsStateModel The state model for search options. | ||
* @property searchResultStateModel The state model for search results. | ||
* @property songSearchService The service used for song search. | ||
*/ | ||
@Controller | ||
class SongSearchIntermediateController( | ||
private val searchInputStateModel: SearchInputStateModel, | ||
private val searchOptionsStateModel: SearchOptionsStateModel, | ||
private val searchResultStateModel: SearchResultStateModel, | ||
private val songSearchService: SongSearchService, | ||
) { | ||
|
||
/** | ||
* The current search job. | ||
*/ | ||
var searchJob: Job? = null | ||
|
||
/** | ||
* Triggers a search operation with an optional delay. | ||
* | ||
* @param wait The optional delay in milliseconds before starting the search. | ||
*/ | ||
suspend fun triggerSearch(wait: Long = 500) = coroutineScope { | ||
searchJob?.cancel() | ||
searchJob = launch { | ||
try { | ||
delay(wait) // do a small delay waiting for any rapid user input | ||
doSearch() | ||
} catch (e: CancellationException) { | ||
log.info { "Previous job is cancelled" } | ||
} catch (e: Exception) { | ||
log.warn(e) { "Exception happened during search, what is that?" } | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* Performs a search using the current input state and search options. | ||
* Sets the search result state model accordingly. | ||
* | ||
* @throws Exception if an error occurs during the search process. | ||
*/ | ||
private suspend fun doSearch() { | ||
searchResultStateModel.setAsSearching() | ||
val title = searchInputStateModel.currentInputState.value | ||
val regexOption = searchOptionsStateModel.searchRegexOptionState.value | ||
val results = if (title.isNotEmpty()) { | ||
songSearchService.search(title, regexOption) | ||
} else { | ||
emptyList() | ||
} | ||
searchResultStateModel.setAsDoneWith(results) | ||
} | ||
} | ||
|
||
private val log = KInlineLogging.logger() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
43 changes: 43 additions & 0 deletions
43
...r-app/src/main/kotlin/mikufan/cx/songfinder/backend/statemodel/SearchOptionsStateModel.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package mikufan.cx.songfinder.backend.statemodel | ||
|
||
import androidx.compose.runtime.MutableState | ||
import androidx.compose.runtime.mutableStateOf | ||
import org.springframework.stereotype.Component | ||
|
||
|
||
/** | ||
* This class represents the state model for search options. | ||
* | ||
* @property searchRegexOptionState The state of the search regex option. | ||
*/ | ||
@Component | ||
class SearchOptionsStateModel { | ||
|
||
/** | ||
* Mutable state variable representing the search regex option state. | ||
* | ||
* This variable holds the current value of the search regex option state, which determines how the search is performed. | ||
* It is declared with a `MutableState` type, allowing it to be changed and observed by other parts of the codebase. | ||
* | ||
* @property searchRegexOptionState The mutable state object holding the search regex option. | ||
* | ||
* @see SearchRegexOption | ||
* | ||
*/ | ||
val searchRegexOptionState: MutableState<SearchRegexOption> = mutableStateOf(SearchRegexOption.Contains) | ||
} | ||
|
||
/** | ||
* Enum class representing different search options for regular expressions. | ||
* | ||
* @property pattern The regular expression pattern for the search option. | ||
* @property description The description of the search option. | ||
* @property displayName The formatted display name of the search option. | ||
*/ | ||
enum class SearchRegexOption(val pattern: String, val description: String) { | ||
Exact("^%s$", "Exact Match"), | ||
StartWith("^%s.*", "Start With"), | ||
Contains(".*%s.*", "Contains"); | ||
|
||
val displayName: String = "$description (${pattern.format("title")})" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
76 changes: 76 additions & 0 deletions
76
...inder-app/src/main/kotlin/mikufan/cx/songfinder/ui/component/mainpage/RegexMatchOption.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
package mikufan.cx.songfinder.ui.component.mainpage | ||
|
||
import androidx.compose.foundation.ExperimentalFoundationApi | ||
import androidx.compose.foundation.layout.Arrangement | ||
import androidx.compose.foundation.layout.Row | ||
import androidx.compose.foundation.onClick | ||
import androidx.compose.material3.MaterialTheme | ||
import androidx.compose.material3.RadioButton | ||
import androidx.compose.material3.Text | ||
import androidx.compose.runtime.Composable | ||
import androidx.compose.runtime.getValue | ||
import androidx.compose.runtime.rememberCoroutineScope | ||
import androidx.compose.ui.Alignment | ||
import androidx.compose.ui.Modifier | ||
import kotlinx.coroutines.launch | ||
import mikufan.cx.songfinder.backend.controller.mainpage.RegexMatchOptionController | ||
import mikufan.cx.songfinder.backend.statemodel.SearchRegexOption | ||
import mikufan.cx.songfinder.getSpringBean | ||
import mikufan.cx.songfinder.ui.common.RowCentralizedWithSpacing | ||
import mikufan.cx.songfinder.ui.theme.spacing | ||
|
||
/** | ||
* Composable function for handling regex match options. | ||
* | ||
*/ | ||
@Composable | ||
fun RegexMatchOption() { | ||
val controller = getSpringBean<RegexMatchOptionController>() | ||
val option by controller.currentRegexOptionState | ||
RealRegexMatchOption(option, controller::setRegexOption) | ||
} | ||
|
||
|
||
/** | ||
* Composable function to render a row of regex match options. | ||
* | ||
* @param option The currently selected search regex option. | ||
* @param onOptionSet The callback function called when a regex option is selected. | ||
*/ | ||
@Composable | ||
fun RealRegexMatchOption(option: SearchRegexOption, onOptionSet: suspend (SearchRegexOption) -> Unit) = RowCentralizedWithSpacing( | ||
horizontalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.spacing) | ||
) { | ||
Text("Regex Match Option: ") | ||
RegexMatchOptionButton(SearchRegexOption.Exact, option, onOptionSet) | ||
RegexMatchOptionButton(SearchRegexOption.StartWith, option, onOptionSet) | ||
RegexMatchOptionButton(SearchRegexOption.Contains, option, onOptionSet) | ||
} | ||
|
||
/** | ||
* Composable function to render a single regex match option. | ||
* | ||
* @param renderedOption The regex option to render. | ||
* @param selectedOption The currently selected regex option. | ||
* @param onOptionSet The callback function called when a regex option is selected. | ||
*/ | ||
@OptIn(ExperimentalFoundationApi::class) | ||
@Composable | ||
fun RegexMatchOptionButton( | ||
renderedOption: SearchRegexOption, | ||
selectedOption: SearchRegexOption, | ||
onOptionSet: suspend (SearchRegexOption) -> Unit | ||
) = Row( | ||
modifier = Modifier, | ||
verticalAlignment = Alignment.CenterVertically | ||
) { | ||
val scope = rememberCoroutineScope() | ||
RadioButton( | ||
selected = renderedOption == selectedOption, | ||
onClick = { scope.launch { onOptionSet(renderedOption) } } | ||
) | ||
Text( | ||
text = renderedOption.displayName, | ||
modifier = Modifier.onClick { scope.launch { onOptionSet(renderedOption) } } | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.