Skip to content

Commit

Permalink
Add search
Browse files Browse the repository at this point in the history
- Add search box to App
- Add Online mine checkbox
- Make search case-insensitive
  • Loading branch information
DRSchlaubi committed May 23, 2023
1 parent 48c9bea commit ecc5813
Show file tree
Hide file tree
Showing 9 changed files with 163 additions and 13 deletions.
2 changes: 2 additions & 0 deletions app/shared/src/commonMain/kotlin/ColorScheme.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import androidx.compose.ui.graphics.Color
object ColorScheme {
val container = Color(17, 18, 20)
val secondaryContainer = Color(43, 45, 49)
val searchBarColor = Color(30, 31, 34)
val textColor = Color.White
val active = Color(87, 242, 135)
val disabled = Color.LightGray
val blurple = Color(88, 101, 242)
}
128 changes: 128 additions & 0 deletions app/shared/src/commonMain/kotlin/components/SearchBar.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package dev.schlaubi.tonbrett.app.components

import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Search
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import dev.schlaubi.tonbrett.app.ColorScheme
import dev.schlaubi.tonbrett.app.api.IO
import dev.schlaubi.tonbrett.app.api.LocalContext
import dev.schlaubi.tonbrett.app.strings.LocalStrings
import dev.schlaubi.tonbrett.common.Sound
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlin.time.Duration.Companion.milliseconds

typealias SoundUpdater = (List<Sound>) -> Unit

@Composable
fun SearchBar(updateSounds: SoundUpdater) {
var onlineMine by remember { mutableStateOf(false) }
var value by remember { mutableStateOf("") }
val strings = LocalStrings.current

fun updateOnlineMine(to: Boolean) {
onlineMine = to
}

fun updateSearch(to: String) {
value = to
}

Row(
horizontalArrangement = Arrangement.SpaceAround,
modifier = Modifier.padding(vertical = 10.dp, horizontal = 15.dp)
) {
SearchField(value, onlineMine, updateSounds, ::updateSearch)
Spacer(Modifier.padding(horizontal = 5.dp))
Row(verticalAlignment = Alignment.CenterVertically) {
OnlineMineCheckbox(onlineMine, updateSounds, ::updateOnlineMine)
Spacer(Modifier.padding(horizontal = 2.dp))
Text(strings.onlineMine, color = ColorScheme.textColor)
}
}
}

@OptIn(FlowPreview::class)
@Composable
private fun SearchField(value: String, onlyMine: Boolean, updateSounds: SoundUpdater, updateSearch: (String) -> Unit) {
val updates = remember { MutableStateFlow(value) }
val scope = rememberCoroutineScope()
val strings = LocalStrings.current
val api = LocalContext.current.api

fun handleInput(input: String) {
updateSearch(input)
scope.launch {
updates.emit(input)
}
}

DisposableEffect(Unit) {
val job = updates
.debounce(300.milliseconds)
.onEach {
withContext(Dispatchers.IO) {
updateSounds(api.getSounds(onlyMine, it.ifBlank { null }))
}
}
.launchIn(scope)
onDispose { job.cancel() }
}

OutlinedTextField(
value,
::handleInput,
placeholder = { Text(strings.searchExplainer) },
colors = TextFieldDefaults.outlinedTextFieldColors(
containerColor = ColorScheme.searchBarColor,
placeholderColor = ColorScheme.secondaryContainer,
textColor = ColorScheme.textColor,
focusedBorderColor = ColorScheme.searchBarColor,
disabledBorderColor = ColorScheme.searchBarColor,
errorBorderColor = ColorScheme.searchBarColor,
unfocusedBorderColor = ColorScheme.searchBarColor
),
shape = RoundedCornerShape(10.dp),
trailingIcon = { Icon(Icons.Default.Search, strings.search) },
singleLine = true,
modifier = Modifier.fillMaxWidth(.8f)
)

}

@Composable
private fun OnlineMineCheckbox(checked: Boolean, updateSounds: SoundUpdater, updateValue: (Boolean) -> Unit) {
var disabled by remember { mutableStateOf(false) }
val scope = rememberCoroutineScope()
val api = LocalContext.current.api

fun update(to: Boolean) {
if (disabled) return
disabled = true
updateValue(to)
scope.launch(Dispatchers.IO) {
val newSounds = api.getSounds(onlyMine = checked)
updateSounds(newSounds)
disabled = false
}
}

Checkbox(
checked, ::update,
colors = CheckboxDefaults.colors(
checkedColor = if (disabled) ColorScheme.secondaryContainer else ColorScheme.blurple
)
)
}
23 changes: 16 additions & 7 deletions app/shared/src/commonMain/kotlin/components/SoundContainer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,23 @@ import io.ktor.client.plugins.*
import kotlinx.coroutines.launch

@Composable
fun SoundContainer(sounds: List<Sound>, errorReporter: ErrorReporter, playingSound: Id<Sound>?, disabled: Boolean) {
LazyVerticalGrid(GridCells.Adaptive(160.dp)) {
items(sounds) { (id, name, _, description, emoji) ->
SoundCard(id, name, emoji, description, id == playingSound, errorReporter, disabled)
fun SoundContainer(
sounds: List<Sound>,
errorReporter: ErrorReporter,
playingSound: Id<Sound>?,
disabled: Boolean,
soundUpdater: SoundUpdater
) {
Column {
SearchBar(soundUpdater)
LazyVerticalGrid(GridCells.Adaptive(160.dp)) {
items(sounds) { (id, name, _, description, emoji) ->
SoundCard(id, name, emoji, description, id == playingSound, errorReporter, disabled)
}
}
if (disabled) {
Box(modifier = Modifier.fillMaxSize().background(ColorScheme.disabled.copy(alpha = .4f))) {}
}
}
if (disabled) {
Box(modifier = Modifier.fillMaxSize().background(ColorScheme.disabled.copy(alpha = .4f))) {}
}
}

Expand Down
4 changes: 3 additions & 1 deletion app/shared/src/commonMain/kotlin/components/SoundList.kt
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,9 @@ fun SoundList(errorReporter: ErrorReporter) {
}

if (!loading && !channelMismatch && !offline) {
SoundContainer(sounds, errorReporter, playingSound, !available)
SoundContainer(sounds, errorReporter, playingSound, !available) {
sounds = it
}
}
}

Expand Down
5 changes: 4 additions & 1 deletion app/shared/src/commonMain/kotlin/strings/DeStrings.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,8 @@ val DeStrings = Strings(
noSounds = "Es gibt keine Sounds in dieser traurigen Welt",
offline = "Du bist derzeit in keinem Sprachkanal",
sessionExpiredExplainer = "Deine derzeitige Sitzung ist abgelaufen, bitte melde dich neu an",
reAuthorize = "Neu anmelden"
reAuthorize = "Neu anmelden",
searchExplainer = "Nach Sounds suchen",
search = "Suche",
onlineMine = "Nur eigene"
)
5 changes: 4 additions & 1 deletion app/shared/src/commonMain/kotlin/strings/EnStrings.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,8 @@ val EnStrings = Strings(
noSounds = "There are no sounds in this sad world :(",
offline = "You are currently not connected to a voice channel",
sessionExpiredExplainer = "Your session expired! Please sign in again",
reAuthorize = "Re-login"
reAuthorize = "Re-login",
searchExplainer = "Search for sounds",
search = "Search",
onlineMine = "Only mine"
)
5 changes: 4 additions & 1 deletion app/shared/src/commonMain/kotlin/strings/Strings.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,8 @@ data class Strings(
val noSounds: String,
val offline: String,
val sessionExpiredExplainer: String,
val reAuthorize: String
val reAuthorize: String,
val searchExplainer: String,
val search: String,
val onlineMine: String
)
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ fun Route.sounds() {
val query = if (queryString.isNullOrBlank()) {
null
} else {
KMongoUtil.toBson("{name: /$queryString/}")
KMongoUtil.toBson("{name: /$queryString/i}")
}

@Language("MongoDB-JSON")
Expand Down
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

allprojects {
group = "dev.schlaubi.tonbrett"
version = "1.5.1"
version = "1.6.0"

repositories {
mavenCentral()
Expand Down

0 comments on commit ecc5813

Please sign in to comment.