Skip to content

Commit

Permalink
Refactor: Improved UI of Quick Search Page
Browse files Browse the repository at this point in the history
- Added monospace font for timestamps in lyrics to improve readability.
- Changed timestamp color to better contrast with the background.
- Added song name validation to prevent crashes from invalid intent data.
- Improved the UI of the QuickLyricsSearchPage for better clarity and accessibility.
- Added content descriptions to icons for improved accessibility.

Signed-off-by: Gabriel Fontán <gabilessto@gmail.com>
  • Loading branch information
BobbyESP committed Nov 15, 2024
1 parent 33bb6f6 commit 63ee215
Show file tree
Hide file tree
Showing 6 changed files with 160 additions and 134 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package pl.lambada.songsync.activities.quicksearch

import android.content.Intent
import android.os.Bundle
import android.widget.Toast
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.activity.viewModels
Expand All @@ -15,6 +16,7 @@ import coil.ImageLoader
import coil.disk.DiskCache
import coil.memory.MemoryCache
import kotlinx.coroutines.Dispatchers
import pl.lambada.songsync.R
import pl.lambada.songsync.activities.quicksearch.viewmodel.QuickLyricsSearchViewModel
import pl.lambada.songsync.activities.quicksearch.viewmodel.QuickLyricsSearchViewModelFactory
import pl.lambada.songsync.data.UserSettingsController
Expand Down Expand Up @@ -54,7 +56,6 @@ class QuickLyricsSearchActivity : AppCompatActivity() {
.dispatcher(Dispatchers.IO)
.build()


enableEdgeToEdge()
handleShareIntent(intent)

Expand All @@ -65,7 +66,7 @@ class QuickLyricsSearchActivity : AppCompatActivity() {
ModalBottomSheet(
sheetState = sheetState,
properties = ModalBottomSheetDefaults.properties,
onDismissRequest = { this.finish() }
onDismissRequest = { finish() }
) {
QuickLyricsSearchPage(
state = viewModelState,
Expand All @@ -89,14 +90,24 @@ class QuickLyricsSearchActivity : AppCompatActivity() {
when (intent.action) {
Intent.ACTION_SEND -> {
val songName =
intent.getStringExtra("songName") ?: "" //TODO: Change to a exception in the VM
intent.getStringExtra("songName")
val artistName = intent.getStringExtra("artistName")
?: "" //TODO: Change to a exception in the VM
?: "" // Artist name is optional. This may be misleading sometimes.

if (songName.isNullOrBlank()) {
Toast.makeText(
this,
this.getString(R.string.song_name_not_provided),
Toast.LENGTH_SHORT
).show()
finish()
return
}

viewModel.onEvent(
QuickLyricsSearchViewModel.Event.Fetch(
songName to artistName,
this
song = songName to artistName,
context = this
)
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,155 +48,153 @@ fun QuickLyricsSearchPage(
.padding(16.dp)
) {
Crossfade(state.value.screenState) { pageState ->
Row {
Column(
modifier = Modifier.fillMaxWidth(),
verticalArrangement = Arrangement.spacedBy(8.dp)
Column(
modifier = Modifier.fillMaxWidth(),
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
Row(
modifier = Modifier.fillMaxWidth()
) {
Row(
modifier = Modifier.fillMaxWidth()
Column(
modifier = Modifier.weight(1f),
verticalArrangement = Arrangement.spacedBy(4.dp)
) {
Column(
modifier = Modifier.weight(1f),
verticalArrangement = Arrangement.spacedBy(4.dp)
) {
Text(
text = stringResource(R.string.showing_lyrics_for).uppercase(),
style = MaterialTheme.typography.labelLarge.copy(
color = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.5f),
letterSpacing = 2.sp
)
Text(
text = stringResource(R.string.showing_lyrics_for).uppercase(),
style = MaterialTheme.typography.labelLarge.copy(
color = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.5f),
letterSpacing = 2.sp
)
)

state.value.song?.let { song ->
Text(
text = song.first,
style = MaterialTheme.typography.headlineSmall
)
Text(
text = buildAnnotatedString {
append(stringResource(R.string.by))
append(" ")
withStyle(MaterialTheme.typography.titleMedium.toSpanStyle()) {
append(song.second)
}
},
)
}
}
Row(
modifier = Modifier
.weight(1f)
.padding(8.dp),
horizontalArrangement = Arrangement.SpaceEvenly,
verticalAlignment = Alignment.CenterVertically
) {
ButtonWithIconAndText(
icon = Icons.AutoMirrored.Rounded.Send,
text = stringResource(R.string.accept),
modifier = Modifier
.weight(1f),
onClick = { onSendLyrics(state.value.lyricsState.data!!) },
enabled = state.value.lyricsState is ResourceState.Success,
shape = RoundedCornerShape(topStart = 8.dp, bottomStart = 8.dp)
state.value.song?.let { song ->
Text(
text = song.first,
style = MaterialTheme.typography.headlineSmall
)
ButtonWithIconAndText(
icon = Icons.Filled.Settings,
text = stringResource(R.string.settings),
modifier = Modifier
.weight(1f),
shape = RoundedCornerShape(topEnd = 8.dp, bottomEnd = 8.dp)
Text(
text = buildAnnotatedString {
append(stringResource(R.string.by))
append(" ")
withStyle(MaterialTheme.typography.titleMedium.toSpanStyle()) {
append(song.second)
}
},
)
}
}
Row(
modifier = Modifier
.weight(1f)
.padding(8.dp),
horizontalArrangement = Arrangement.SpaceEvenly,
verticalAlignment = Alignment.CenterVertically
) {
ButtonWithIconAndText(
icon = Icons.AutoMirrored.Rounded.Send,
text = stringResource(R.string.accept),
modifier = Modifier
.weight(1f),
onClick = { onSendLyrics(state.value.lyricsState.data!!) },
enabled = state.value.lyricsState is ResourceState.Success,
shape = RoundedCornerShape(topStart = 8.dp, bottomStart = 8.dp)
)
ButtonWithIconAndText(
icon = Icons.Filled.Settings,
text = stringResource(R.string.settings),
modifier = Modifier
.weight(1f),
shape = RoundedCornerShape(topEnd = 8.dp, bottomEnd = 8.dp)
)
}
}

HorizontalDivider()
HorizontalDivider()

when (pageState) {
is ScreenState.Loading -> {
Box(
modifier = Modifier.fillMaxWidth(),
contentAlignment = Alignment.Center
) {
CircularProgressIndicator()
}
when (pageState) {
is ScreenState.Loading -> {
Box(
modifier = Modifier.fillMaxWidth(),
contentAlignment = Alignment.Center
) {
CircularProgressIndicator()
}
}

is ScreenState.Success -> {
Column(
modifier = Modifier.fillMaxWidth(),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
pageState.data?.let {
Column(
is ScreenState.Success -> {
Column(
modifier = Modifier.fillMaxWidth(),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
pageState.data?.let {
Column(
modifier = Modifier.fillMaxWidth(),
verticalArrangement = Arrangement.spacedBy(4.dp)
) {
Row(
modifier = Modifier.fillMaxWidth(),
verticalArrangement = Arrangement.spacedBy(4.dp)
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(6.dp)
) {
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(6.dp)
) {
Icon(
imageVector = Icons.Filled.Cloud,
contentDescription = null,
)
Text(
text = stringResource(R.string.cloud_song).uppercase(),
style = MaterialTheme.typography.bodyMedium.copy(
letterSpacing = 1.sp,
fontWeight = FontWeight.SemiBold
)
Icon(
imageVector = Icons.Filled.Cloud,
contentDescription = null,
)
Text(
text = stringResource(R.string.cloud_song).uppercase(),
style = MaterialTheme.typography.bodyMedium.copy(
letterSpacing = 1.sp,
fontWeight = FontWeight.SemiBold
)
}

QuickLyricsSongInfo(
songInfo = pageState.data,
modifier = Modifier.fillMaxWidth()
)
}
when (state.value.lyricsState) {
is ResourceState.Loading<*> -> {
Box(
modifier = Modifier.fillMaxWidth(),
contentAlignment = Alignment.Center
) {
CircularProgressIndicator()
}

QuickLyricsSongInfo(
songInfo = pageState.data,
modifier = Modifier.fillMaxWidth()
)
}
when (state.value.lyricsState) {
is ResourceState.Loading<*> -> {
Box(
modifier = Modifier.fillMaxWidth(),
contentAlignment = Alignment.Center
) {
CircularProgressIndicator()
}
}

is ResourceState.Success<*> -> {
state.value.lyricsState.data?.let { _ -> //This crunches the animation lol
ExpandableOutlinedCard(
title = stringResource(R.string.song_lyrics),
subtitle = stringResource(R.string.lyrics_subtitle),
icon = Icons.Rounded.Subtitles,
isExpanded = false,
modifier = Modifier.fillMaxWidth()
) {
SyncedLyricsColumn(
lyricsList = state.value.parsedLyrics,
modifier = Modifier
.fillMaxWidth()
.padding(8.dp)
)
}
is ResourceState.Success<*> -> {
state.value.lyricsState.data?.let { _ -> //This crunches the animation lol
ExpandableOutlinedCard(
title = stringResource(R.string.song_lyrics),
subtitle = stringResource(R.string.lyrics_subtitle),
icon = Icons.Rounded.Subtitles,
isExpanded = false,
modifier = Modifier.fillMaxWidth()
) {
SyncedLyricsColumn(
lyricsList = state.value.parsedLyrics,
modifier = Modifier
.fillMaxWidth()
.padding(8.dp)
)
}
}
}

is ResourceState.Error<*> -> {
Text("Error: ${state.value.lyricsState.message}")
}
is ResourceState.Error<*> -> {
Text("Error: ${state.value.lyricsState.message}")
}
}

}
}

is ScreenState.Error -> {
Text("Error: ${pageState.exception.message}")
}
}

is ScreenState.Error -> {
Text("Error: ${pageState.exception.message}")
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,11 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.rotate
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import pl.lambada.songsync.R

@Composable
fun ExpandableOutlinedCard(
Expand Down Expand Up @@ -62,7 +64,7 @@ fun ExpandableOutlinedCard(
Icon(
modifier = Modifier.weight(0.1f),
imageVector = icon,
contentDescription = null,
contentDescription = stringResource(R.string.song_lyrics),
)
Column(
modifier = Modifier
Expand All @@ -87,8 +89,8 @@ fun ExpandableOutlinedCard(
onClick = { expanded = !expanded }
) {
Icon(
Icons.Outlined.ExpandLess,
null,
imageVector = Icons.Outlined.ExpandLess,
contentDescription = null,
tint = MaterialTheme.colorScheme.onPrimaryContainer,
modifier = Modifier.rotate(animatedDegree.value)
)
Expand Down
Loading

0 comments on commit 63ee215

Please sign in to comment.