mirror of
https://github.com/austinried/subtracks.git
synced 2026-11-11 07:29:14 +01:00
search: require three characters and play songs in album context
Drop the library-wide instr fallback: below three characters the cross-type search now returns nothing instead of scanning every table, and the screen asks for more input. Lock in that a song result plays its album context rather than a search queue.
This commit is contained in:
@@ -128,33 +128,23 @@ internal const val PLAYLIST_ORDER_BY_ADDED_REVERSED = "created ASC, name COLLATE
|
||||
internal const val PLAYLIST_ORDER_BY_UPDATED = "changed DESC, name COLLATE NOCASE, id"
|
||||
internal const val PLAYLIST_ORDER_BY_UPDATED_REVERSED = "changed ASC, name COLLATE NOCASE DESC, id DESC"
|
||||
|
||||
// Cross-type search: a three-character-or-longer query runs through the trigram index and anything
|
||||
// shorter falls back to the instr scan, mirroring the per-tab filters above.
|
||||
// Cross-type search only runs from three characters, since a shorter term cannot use the trigram
|
||||
// index and scanning the whole library for it is not worth it.
|
||||
internal const val ALBUM_SEARCH_FILTER =
|
||||
"(:search <> '' AND (" +
|
||||
"(length(:search) >= 3 AND rowid IN (SELECT rowid FROM album_search " +
|
||||
"WHERE album_search MATCH '\"' || replace(:search, '\"', '\"\"') || '\"')) " +
|
||||
"OR (length(:search) < 3 AND (instr(lower(name), lower(:search)) > 0 " +
|
||||
"OR instr(lower(albumArtist), lower(:search)) > 0))))"
|
||||
"(length(:search) >= 3 AND rowid IN (SELECT rowid FROM album_search " +
|
||||
"WHERE album_search MATCH '\"' || replace(:search, '\"', '\"\"') || '\"'))"
|
||||
|
||||
internal const val ARTIST_SEARCH_FILTER =
|
||||
"(:search <> '' AND (" +
|
||||
"(length(:search) >= 3 AND rowid IN (SELECT rowid FROM artist_search " +
|
||||
"WHERE artist_search MATCH '\"' || replace(:search, '\"', '\"\"') || '\"')) " +
|
||||
"OR (length(:search) < 3 AND instr(lower(name), lower(:search)) > 0)))"
|
||||
"(length(:search) >= 3 AND rowid IN (SELECT rowid FROM artist_search " +
|
||||
"WHERE artist_search MATCH '\"' || replace(:search, '\"', '\"\"') || '\"'))"
|
||||
|
||||
internal const val PLAYLIST_SEARCH_FILTER =
|
||||
"(:search <> '' AND (" +
|
||||
"(length(:search) >= 3 AND rowid IN (SELECT rowid FROM playlist_search " +
|
||||
"WHERE playlist_search MATCH '\"' || replace(:search, '\"', '\"\"') || '\"')) " +
|
||||
"OR (length(:search) < 3 AND instr(lower(name), lower(:search)) > 0)))"
|
||||
"(length(:search) >= 3 AND rowid IN (SELECT rowid FROM playlist_search " +
|
||||
"WHERE playlist_search MATCH '\"' || replace(:search, '\"', '\"\"') || '\"'))"
|
||||
|
||||
internal const val SONG_SEARCH_FILTER =
|
||||
"(:search <> '' AND (" +
|
||||
"(length(:search) >= 3 AND songs.rowid IN (SELECT rowid FROM song_search " +
|
||||
"WHERE song_search MATCH '\"' || replace(:search, '\"', '\"\"') || '\"')) " +
|
||||
"OR (length(:search) < 3 AND (instr(lower(songs.title), lower(:search)) > 0 " +
|
||||
"OR instr(lower(songs.artist), lower(:search)) > 0))))"
|
||||
"(length(:search) >= 3 AND songs.rowid IN (SELECT rowid FROM song_search " +
|
||||
"WHERE song_search MATCH '\"' || replace(:search, '\"', '\"\"') || '\"'))"
|
||||
|
||||
@Dao
|
||||
@DaoReturnTypeConverters(PagingSourceDaoReturnTypeConverter::class)
|
||||
|
||||
@@ -510,4 +510,6 @@ const val REDISCOVER_WINDOW_MS = 60L * 24 * 60 * 60 * 1000
|
||||
|
||||
const val SEARCH_RESULT_LIMIT = 50
|
||||
|
||||
const val SEARCH_MIN_LENGTH = 3
|
||||
|
||||
fun rediscoverCutoff(): Long = System.currentTimeMillis() - REDISCOVER_WINDOW_MS
|
||||
|
||||
@@ -37,6 +37,7 @@ import com.subtracks.data.model.Artist
|
||||
import com.subtracks.data.model.CoverArtRef
|
||||
import com.subtracks.data.model.Playlist
|
||||
import com.subtracks.data.model.Song
|
||||
import com.subtracks.data.repo.SEARCH_MIN_LENGTH
|
||||
import com.subtracks.data.source.StarType
|
||||
import com.subtracks.playback.PlaybackController
|
||||
import com.subtracks.ui.components.ContextMenuHost
|
||||
@@ -144,9 +145,9 @@ fun SearchScreen(
|
||||
},
|
||||
) { padding ->
|
||||
when {
|
||||
query.isBlank() -> {
|
||||
query.length < SEARCH_MIN_LENGTH -> {
|
||||
EmptyState(
|
||||
text = "Search for songs, albums, artists and playlists.",
|
||||
text = "Type at least $SEARCH_MIN_LENGTH characters to search.",
|
||||
modifier = Modifier.padding(padding),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import com.subtracks.data.model.CoverArtRef
|
||||
import com.subtracks.data.model.Playlist
|
||||
import com.subtracks.data.model.Song
|
||||
import com.subtracks.data.repo.LibraryRepository
|
||||
import com.subtracks.data.repo.SEARCH_MIN_LENGTH
|
||||
import com.subtracks.data.repo.SourceRepository
|
||||
import com.subtracks.playback.PlaybackController
|
||||
import com.subtracks.ui.home.playSongInContext
|
||||
@@ -45,7 +46,7 @@ class SearchViewModel(
|
||||
libraryRepository.activeSourceId
|
||||
.flatMapLatest { sourceId ->
|
||||
_query.flatMapLatest { text ->
|
||||
if (sourceId == null || text.isBlank()) {
|
||||
if (sourceId == null || text.length < SEARCH_MIN_LENGTH) {
|
||||
flowOf(SearchResults())
|
||||
} else {
|
||||
combine(
|
||||
|
||||
Reference in New Issue
Block a user