From 0534fef9ff65ef904ab5596d412c0b0f7cde85f9 Mon Sep 17 00:00:00 2001 From: CXwudi Date: Thu, 30 Nov 2023 22:34:34 -0500 Subject: [PATCH] :heavy_plus_sign: Refactored code and added the first search option: regex search mode --- .../mainpage/RegexMatchOptionController.kt | 20 +++++ .../mainpage/SearchBarController.kt | 23 +----- .../SongSearchIntermediateController.kt | 70 +++++++++++++++++ .../backend/db/repository/SongRepository.kt | 10 +-- .../backend/service/SongSearchService.kt | 14 ++-- .../statemodel/SearchInputStateModel.kt | 12 +++ .../statemodel/SearchOptionsStateModel.kt | 43 +++++++++++ .../cx/songfinder/ui/component/MainScreen.kt | 8 +- .../ui/component/mainpage/RegexMatchOption.kt | 76 +++++++++++++++++++ .../ui/component/mainpage/ResultPanel.kt | 4 +- .../ui/component/mainpage/SearchBar.kt | 17 ++--- .../cx/songfinder/ui/test/TestCellCard.kt | 6 +- .../mikufan/cx/songfinder/ui/theme/Spacing.kt | 5 +- .../db/repository/SongRepositoryTest.kt | 2 +- .../cx/songfinder/poc/JvmPatternPoc.kt | 13 ++++ 15 files changed, 274 insertions(+), 49 deletions(-) create mode 100644 songfinder-app/src/main/kotlin/mikufan/cx/songfinder/backend/controller/mainpage/RegexMatchOptionController.kt create mode 100644 songfinder-app/src/main/kotlin/mikufan/cx/songfinder/backend/controller/mainpage/SongSearchIntermediateController.kt create mode 100644 songfinder-app/src/main/kotlin/mikufan/cx/songfinder/backend/statemodel/SearchOptionsStateModel.kt create mode 100644 songfinder-app/src/main/kotlin/mikufan/cx/songfinder/ui/component/mainpage/RegexMatchOption.kt create mode 100644 songfinder-app/src/test/kotlin/mikufan/cx/songfinder/poc/JvmPatternPoc.kt diff --git a/songfinder-app/src/main/kotlin/mikufan/cx/songfinder/backend/controller/mainpage/RegexMatchOptionController.kt b/songfinder-app/src/main/kotlin/mikufan/cx/songfinder/backend/controller/mainpage/RegexMatchOptionController.kt new file mode 100644 index 0000000..2defcc8 --- /dev/null +++ b/songfinder-app/src/main/kotlin/mikufan/cx/songfinder/backend/controller/mainpage/RegexMatchOptionController.kt @@ -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 = searchOptionsStateModel.searchRegexOptionState + + suspend fun setRegexOption(newOption: SearchRegexOption) { + searchOptionsStateModel.searchRegexOptionState.value = newOption + songSearchIntermediateController.triggerSearch(100) + } +} \ No newline at end of file diff --git a/songfinder-app/src/main/kotlin/mikufan/cx/songfinder/backend/controller/mainpage/SearchBarController.kt b/songfinder-app/src/main/kotlin/mikufan/cx/songfinder/backend/controller/mainpage/SearchBarController.kt index 4d1c73e..99d0fe1 100644 --- a/songfinder-app/src/main/kotlin/mikufan/cx/songfinder/backend/controller/mainpage/SearchBarController.kt +++ b/songfinder-app/src/main/kotlin/mikufan/cx/songfinder/backend/controller/mainpage/SearchBarController.kt @@ -1,8 +1,6 @@ package mikufan.cx.songfinder.backend.controller.mainpage import androidx.compose.runtime.State -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.SearchResultStateModel import mikufan.cx.songfinder.backend.statemodel.SearchStatus @@ -11,8 +9,8 @@ import org.springframework.stereotype.Controller @Controller class SearchBarController( private val searchInputStateModel: SearchInputStateModel, - private val searchResultStateModel: SearchResultStateModel, - private val songSearchService: SongSearchService, + searchResultStateModel: SearchResultStateModel, + private val songSearchIntermediateController: SongSearchIntermediateController ) { val currentInputState: State get() = searchInputStateModel.currentInputState @@ -23,19 +21,6 @@ class SearchBarController( } suspend fun search() { - try { - val title = searchInputStateModel.currentInputState.value - searchResultStateModel.setAsSearching() - val results = if (title.isNotEmpty()) { - songSearchService.search(title) - } else { - emptyList() - } - searchResultStateModel.setAsDoneWith(results) - } catch (e: Exception) { - log.warn(e) { "Exception happened during search, what is that?" } - } + songSearchIntermediateController.triggerSearch() } -} - -private val log = KInlineLogging.logger() \ No newline at end of file +} \ No newline at end of file diff --git a/songfinder-app/src/main/kotlin/mikufan/cx/songfinder/backend/controller/mainpage/SongSearchIntermediateController.kt b/songfinder-app/src/main/kotlin/mikufan/cx/songfinder/backend/controller/mainpage/SongSearchIntermediateController.kt new file mode 100644 index 0000000..64c19a5 --- /dev/null +++ b/songfinder-app/src/main/kotlin/mikufan/cx/songfinder/backend/controller/mainpage/SongSearchIntermediateController.kt @@ -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() \ No newline at end of file diff --git a/songfinder-app/src/main/kotlin/mikufan/cx/songfinder/backend/db/repository/SongRepository.kt b/songfinder-app/src/main/kotlin/mikufan/cx/songfinder/backend/db/repository/SongRepository.kt index d35051a..001acd3 100644 --- a/songfinder-app/src/main/kotlin/mikufan/cx/songfinder/backend/db/repository/SongRepository.kt +++ b/songfinder-app/src/main/kotlin/mikufan/cx/songfinder/backend/db/repository/SongRepository.kt @@ -11,10 +11,10 @@ interface SongRepository : VocaDbRepository { FROM songs s JOIN song_names sn ON s.id = sn.song_id WHERE - s.japanese_name LIKE concat('%', :title, '%') - OR s.english_name LIKE concat('%', :title, '%') - OR s.romaji_name LIKE concat('%', :title, '%') - OR sn.value LIKE concat('%', :title, '%') + s.japanese_name REGEXP :title + OR s.english_name REGEXP :title + OR s.romaji_name REGEXP :title + OR sn.value REGEXP :title """) - fun findByAllPossibleNamesContain(title: String): List + fun findByAllPossibleNames(title: String): List } diff --git a/songfinder-app/src/main/kotlin/mikufan/cx/songfinder/backend/service/SongSearchService.kt b/songfinder-app/src/main/kotlin/mikufan/cx/songfinder/backend/service/SongSearchService.kt index 48e556d..9d3da16 100644 --- a/songfinder-app/src/main/kotlin/mikufan/cx/songfinder/backend/service/SongSearchService.kt +++ b/songfinder-app/src/main/kotlin/mikufan/cx/songfinder/backend/service/SongSearchService.kt @@ -9,6 +9,7 @@ import mikufan.cx.songfinder.backend.db.projection.ArtistInSong import mikufan.cx.songfinder.backend.db.repository.* import mikufan.cx.songfinder.backend.model.PVInfo import mikufan.cx.songfinder.backend.model.SongSearchResult +import mikufan.cx.songfinder.backend.statemodel.SearchRegexOption import org.springframework.stereotype.Service /** @@ -50,16 +51,19 @@ class SongSearchService( * @param title The title to search for. * @return A list of SongSearchResult objects matching the search criteria. */ - suspend fun search(title: String): List { - log.info { "Searching '$title'" } + suspend fun search(title: String, regexOption: SearchRegexOption): List { + val regexOptionDescription = regexOption.description + val pattern = regexOption.pattern + log.info { "Searching '$title' with $regexOptionDescription" } // search steps: // 1. search songs by title + val formattedTitle = pattern.format(title) val songs = withContext(ioDispatcher) { - songRepo.findByAllPossibleNamesContain(title) + songRepo.findByAllPossibleNames(formattedTitle) } log.debug { "found ${songs.size} entries" } if (songs.isEmpty()) { - log.info { "No song found for '$title'" } + log.info { "No song found for '$formattedTitle'" } return emptyList() } val songIds = songs.map { it.id } @@ -122,7 +126,7 @@ class SongSearchService( .sortedBy { it.publishDate } } - log.info { "Found ${results.size} results for '$title'" } + log.info { "Found ${results.size} results for '$title' with $regexOptionDescription" } return results } diff --git a/songfinder-app/src/main/kotlin/mikufan/cx/songfinder/backend/statemodel/SearchInputStateModel.kt b/songfinder-app/src/main/kotlin/mikufan/cx/songfinder/backend/statemodel/SearchInputStateModel.kt index b859ef2..2171662 100644 --- a/songfinder-app/src/main/kotlin/mikufan/cx/songfinder/backend/statemodel/SearchInputStateModel.kt +++ b/songfinder-app/src/main/kotlin/mikufan/cx/songfinder/backend/statemodel/SearchInputStateModel.kt @@ -6,10 +6,22 @@ import androidx.compose.runtime.mutableStateOf class SearchInputStateModel( initialInput: String ) { + /** + * To record the current line of input from file + */ +// var currentInputFromFile = initialInput + /** + * To record the current input content from the search bar + */ var currentInputState: MutableState = mutableStateOf(initialInput) fun update(newInput: String) { currentInputState.value = newInput } + +// fun setToNext(newInput: String) { +// currentInputState.value = newInput +// currentInputFromFile = newInput +// } } \ No newline at end of file diff --git a/songfinder-app/src/main/kotlin/mikufan/cx/songfinder/backend/statemodel/SearchOptionsStateModel.kt b/songfinder-app/src/main/kotlin/mikufan/cx/songfinder/backend/statemodel/SearchOptionsStateModel.kt new file mode 100644 index 0000000..71455fe --- /dev/null +++ b/songfinder-app/src/main/kotlin/mikufan/cx/songfinder/backend/statemodel/SearchOptionsStateModel.kt @@ -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 = 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")})" +} diff --git a/songfinder-app/src/main/kotlin/mikufan/cx/songfinder/ui/component/MainScreen.kt b/songfinder-app/src/main/kotlin/mikufan/cx/songfinder/ui/component/MainScreen.kt index 2fe86de..2c9e8e5 100644 --- a/songfinder-app/src/main/kotlin/mikufan/cx/songfinder/ui/component/MainScreen.kt +++ b/songfinder-app/src/main/kotlin/mikufan/cx/songfinder/ui/component/MainScreen.kt @@ -6,6 +6,7 @@ import androidx.compose.material3.Divider import androidx.compose.runtime.Composable import androidx.compose.runtime.State import androidx.compose.runtime.mutableStateOf +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import mikufan.cx.songfinder.backend.controller.MainScreenController import mikufan.cx.songfinder.backend.db.entity.PvService @@ -13,6 +14,7 @@ import mikufan.cx.songfinder.backend.db.entity.PvType import mikufan.cx.songfinder.backend.db.entity.SongType import mikufan.cx.songfinder.backend.model.PVInfo import mikufan.cx.songfinder.backend.model.SongSearchResult +import mikufan.cx.songfinder.backend.statemodel.SearchRegexOption import mikufan.cx.songfinder.backend.statemodel.SearchStatus import mikufan.cx.songfinder.getSpringBean import mikufan.cx.songfinder.ui.common.ColumnCentralizedWithSpacing @@ -28,11 +30,14 @@ fun MainScreen() { @Composable -fun RealMainScreen(isAllFinished: State) = ColumnCentralizedWithSpacing { +fun RealMainScreen(isAllFinished: State) = ColumnCentralizedWithSpacing( + horizontalAlignment = Alignment.Start +) { ProgressBar() Divider() RestOfPart(isAllFinished.value, { FinishMessagePanel() }, { SearchBar() + RegexMatchOption() ResultPanel() }) } @@ -62,6 +67,7 @@ fun PreviewMainScreen() { {}, ) ) + RealRegexMatchOption(SearchRegexOption.Exact, {}) RealResultPanel( listOf( SongSearchResult( diff --git a/songfinder-app/src/main/kotlin/mikufan/cx/songfinder/ui/component/mainpage/RegexMatchOption.kt b/songfinder-app/src/main/kotlin/mikufan/cx/songfinder/ui/component/mainpage/RegexMatchOption.kt new file mode 100644 index 0000000..b1dd360 --- /dev/null +++ b/songfinder-app/src/main/kotlin/mikufan/cx/songfinder/ui/component/mainpage/RegexMatchOption.kt @@ -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() + 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) } } + ) +} diff --git a/songfinder-app/src/main/kotlin/mikufan/cx/songfinder/ui/component/mainpage/ResultPanel.kt b/songfinder-app/src/main/kotlin/mikufan/cx/songfinder/ui/component/mainpage/ResultPanel.kt index b6eb37c..bce408b 100644 --- a/songfinder-app/src/main/kotlin/mikufan/cx/songfinder/ui/component/mainpage/ResultPanel.kt +++ b/songfinder-app/src/main/kotlin/mikufan/cx/songfinder/ui/component/mainpage/ResultPanel.kt @@ -81,8 +81,8 @@ fun ResultPanelGrid( ) { LazyVerticalGrid( columns = GridCells.Adaptive(256.dp), - horizontalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.spacingSmaller), - verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.spacingSmaller), + horizontalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.spacingSmall), + verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.spacingSmall), // modifier = modifier.padding(end = MaterialTheme.spacing.paddingLarge), state = gridState, ) { diff --git a/songfinder-app/src/main/kotlin/mikufan/cx/songfinder/ui/component/mainpage/SearchBar.kt b/songfinder-app/src/main/kotlin/mikufan/cx/songfinder/ui/component/mainpage/SearchBar.kt index 6a6c019..adfdae6 100644 --- a/songfinder-app/src/main/kotlin/mikufan/cx/songfinder/ui/component/mainpage/SearchBar.kt +++ b/songfinder-app/src/main/kotlin/mikufan/cx/songfinder/ui/component/mainpage/SearchBar.kt @@ -11,10 +11,10 @@ import androidx.compose.material3.Icon import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.State +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Modifier -import kotlinx.coroutines.delay +import kotlinx.coroutines.launch import mikufan.cx.songfinder.backend.controller.mainpage.SearchBarController import mikufan.cx.songfinder.backend.statemodel.SearchStatus import mikufan.cx.songfinder.getSpringBean @@ -31,30 +31,25 @@ fun SearchBar(modifier: Modifier = Modifier) { val controller = getSpringBean() val inputState = controller.currentInputState val searchStatusState = controller.currentSearchStatusState - val searchFunc = controller::search val model = SearchBarModel( inputState, searchStatusState, controller::setInput, ) - DoSearchComposition(inputState.value, searchFunc) + DoSearchComposition(inputState.value, controller::search) RealSearchBar(model, modifier) } /** - * Performs a search operation after a small delay for user input. + * Performs a search operation upon entering this composable or recomposition + * (which is when the input value changes) * * @param value the search value provided by the user. * @param searchFunc the suspend function to execute the search operation. */ @Composable fun DoSearchComposition(value: String, searchFunc: suspend () -> Unit) { -// val scope = rememberCoroutineScope() - LaunchedEffect(value) { -// println("start $value") -// delay(1300) -// println("end $value") - delay(500) // still do a small delay waiting for user input + rememberCoroutineScope().launch { searchFunc() } } diff --git a/songfinder-app/src/main/kotlin/mikufan/cx/songfinder/ui/test/TestCellCard.kt b/songfinder-app/src/main/kotlin/mikufan/cx/songfinder/ui/test/TestCellCard.kt index 1c1a8cf..3930a40 100644 --- a/songfinder-app/src/main/kotlin/mikufan/cx/songfinder/ui/test/TestCellCard.kt +++ b/songfinder-app/src/main/kotlin/mikufan/cx/songfinder/ui/test/TestCellCard.kt @@ -38,8 +38,8 @@ fun main() = application { Text("Hello World") LazyVerticalGrid( columns = GridCells.Adaptive(300.dp), - horizontalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.spacingSmaller), - verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.spacingSmaller), + horizontalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.spacingSmall), + verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.spacingSmall), modifier = Modifier.padding(horizontal = MaterialTheme.spacing.padding), ) { item { @@ -134,7 +134,7 @@ fun MusicCard(onCardClicked: suspend () -> Unit) { @Composable private fun PvRows() { Row( - horizontalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.spacingSmaller), + horizontalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.spacingSmall), verticalAlignment = Alignment.CenterVertically, ) { val uriHandler = LocalUriHandler.current diff --git a/songfinder-app/src/main/kotlin/mikufan/cx/songfinder/ui/theme/Spacing.kt b/songfinder-app/src/main/kotlin/mikufan/cx/songfinder/ui/theme/Spacing.kt index b46fdd2..a1d5d9f 100644 --- a/songfinder-app/src/main/kotlin/mikufan/cx/songfinder/ui/theme/Spacing.kt +++ b/songfinder-app/src/main/kotlin/mikufan/cx/songfinder/ui/theme/Spacing.kt @@ -24,11 +24,12 @@ internal val LocalSpacing: ProvidableCompositionLocal = staticCompositi data class Spacing( val spacing: Dp = 5.dp, - val spacingSmaller: Dp = 4.dp, + val spacingSmall: Dp = 4.dp, val spacingLarge: Dp = 8.dp, - val cornerShape: Dp = spacingSmaller, + val cornerShape: Dp = spacingSmall, val cornerShapeLarge: Dp = cornerShape * 2, val cornerShapeExtraLarge: Dp = cornerShape * 4, val padding: Dp = 5.dp, + val paddingSmall: Dp = 4.dp, val paddingLarge: Dp = 8.dp, ) diff --git a/songfinder-app/src/test/kotlin/mikufan/cx/songfinder/backend/db/repository/SongRepositoryTest.kt b/songfinder-app/src/test/kotlin/mikufan/cx/songfinder/backend/db/repository/SongRepositoryTest.kt index a49bdb9..e5a8a0c 100644 --- a/songfinder-app/src/test/kotlin/mikufan/cx/songfinder/backend/db/repository/SongRepositoryTest.kt +++ b/songfinder-app/src/test/kotlin/mikufan/cx/songfinder/backend/db/repository/SongRepositoryTest.kt @@ -29,7 +29,7 @@ class SongRepositoryTest( should("find all songs that contains a string in any naming") { val title = "shinagawa" - val songs = songRepository.findByAllPossibleNamesContain(title) + val songs = songRepository.findByAllPossibleNames(title) println("songs = ${songs.joinToString("\n", "[\n", "\n]")}") songs.size shouldBe 4 } diff --git a/songfinder-app/src/test/kotlin/mikufan/cx/songfinder/poc/JvmPatternPoc.kt b/songfinder-app/src/test/kotlin/mikufan/cx/songfinder/poc/JvmPatternPoc.kt new file mode 100644 index 0000000..51f5eb8 --- /dev/null +++ b/songfinder-app/src/test/kotlin/mikufan/cx/songfinder/poc/JvmPatternPoc.kt @@ -0,0 +1,13 @@ +package mikufan.cx.songfinder.poc + +import io.kotest.core.spec.style.ShouldSpec + +class JvmPatternPoc : ShouldSpec({ + context("pattern") { + should("get the string") { + val pattern = ".*%s.*".format("test") + val regex = pattern.toRegex() + println(regex.pattern) + } + } +}) \ No newline at end of file