Skip to content

Commit

Permalink
[Release] v1.4.1
Browse files Browse the repository at this point in the history
[UX] Disable search button if input is blank or is in searching state.
[UX] Change UI behavior while searching.
[Code] Optimize code structure.
[Code] Update dependencies.
  • Loading branch information
Konyaco committed Dec 9, 2021
1 parent 9d7222e commit 97ea52f
Show file tree
Hide file tree
Showing 14 changed files with 136 additions and 122 deletions.
8 changes: 4 additions & 4 deletions android/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ android {
minSdk = 21
targetSdk = 31
versionCode = 3
versionName = "1.4.0"
versionName = rootProject.version as String
}

buildTypes {
Expand All @@ -37,9 +37,9 @@ android {
dependencies {
implementation(project(":common"))
implementation("org.jsoup:jsoup:${rootProject.extra["jsoup_version"]}")
implementation("androidx.core:core-ktx:1.6.0")
implementation("androidx.activity:activity-compose:1.3.1")
implementation("androidx.appcompat:appcompat:1.3.1")
implementation("androidx.core:core-ktx:1.7.0")
implementation("androidx.activity:activity-compose:1.4.0")
implementation("androidx.appcompat:appcompat:1.4.0")
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.3")
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import android.os.Bundle
import androidx.activity.compose.setContent
import androidx.appcompat.app.AppCompatActivity
import me.konyaco.collinsdictionary.ui.App
import me.konyaco.collinsdictionary.ui.AppViewModel
import me.konyaco.collinsdictionary.ui.MyTheme
import me.konyaco.collinsdictionary.viewmodel.AppViewModel

class MainActivity : AppCompatActivity() {
private val component by lazy { AppViewModel() }
Expand Down
9 changes: 4 additions & 5 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
plugins {
id("com.android.application") version "7.2.0-alpha02" apply false
id("com.android.library") version "7.2.0-alpha02" apply false
id("com.android.application") version "7.2.0-alpha03" apply false
id("com.android.library") version "7.2.0-alpha03" apply false
kotlin("android") version "1.5.31" apply false
kotlin("multiplatform") version "1.5.31" apply false
id("org.jetbrains.compose") version "1.0.0-alpha4-build398" apply false
id("org.jetbrains.compose") version "1.0.0" apply false
}

allprojects {
repositories {
mavenCentral()
google()
maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
}
extra["jsoup_version"] = "1.13.1"
}

group = "me.konyaco.collinsdictionary"
version = "1.4.0"
version = "1.4.1"
4 changes: 2 additions & 2 deletions common/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ kotlin {
val androidMain by getting {
dependencies {
implementation("org.jsoup:jsoup:${extra["jsoup_version"]}")
api("androidx.appcompat:appcompat:1.3.1")
api("androidx.core:core-ktx:1.6.0")
api("androidx.appcompat:appcompat:1.4.0")
api("androidx.core:core-ktx:1.7.0")
}
}
val jvmMain by getting {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package me.konyaco.collinsdictionary.ui
package me.konyaco.collinsdictionary.ui.component

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
Expand Down
84 changes: 39 additions & 45 deletions common/src/commonMain/kotlin/me/konyaco/collinsdictionary/ui/App.kt
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package me.konyaco.collinsdictionary.ui

import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.animation.*
import androidx.compose.foundation.Image
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.material.Divider
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
Expand All @@ -21,7 +22,9 @@ import androidx.compose.ui.unit.sp
import me.konyaco.collinsdictionary.service.ProvideSoundPlayer
import me.konyaco.collinsdictionary.service.Word
import me.konyaco.collinsdictionary.ui.component.CobuildDictionarySection
import me.konyaco.collinsdictionary.ui.component.ColumnWithScrollBar
import me.konyaco.collinsdictionary.ui.component.SearchBox
import me.konyaco.collinsdictionary.viewmodel.AppViewModel

val LocalScreenSize = compositionLocalOf { ScreenSize.PHONE }

Expand Down Expand Up @@ -49,20 +52,14 @@ fun ProvideLocalScreenSize(content: @Composable () -> Unit) {

@Composable
fun App(viewModel: AppViewModel) {
App(viewModel.queryState.collectAsState().value) { viewModel.search(it) }
App(
viewModel.queryResult.collectAsState().value,
viewModel.isSearching.collectAsState().value
) { viewModel.search(it) }
}

sealed class State {
object None : State()
object Searching : State()
data class Succeed(val data: Word) : State()
object WordNotFound : State()
data class Failed(val message: String) : State()
}

@OptIn(ExperimentalAnimationApi::class)
@Composable
fun App(uiState: State, onSearch: (text: String) -> Unit) {
fun App(data: AppViewModel.Result?, isSearching: Boolean, onSearch: (text: String) -> Unit) {
ProvideSoundPlayer {
ProvideLocalScreenSize {
Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colors.background) {
Expand All @@ -78,50 +75,47 @@ fun App(uiState: State, onSearch: (text: String) -> Unit) {
horizontalAlignment = Alignment.Start,
verticalArrangement = Arrangement.Top
) {
Banner(uiState is State.None, padding)

Banner(display = data == null, padding)
Spacer(Modifier.height(32.dp))

var input by remember { mutableStateOf("") }
SearchBox(
modifier = Modifier.padding(horizontal = padding).fillMaxWidth(),
value = input,
onValueChange = { input = it },
onSearchClick = { onSearch(input) }
onSearchClick = { onSearch(input) },
isSearching = isSearching
)

AnimatedContent(
modifier = Modifier.weight(1f).fillMaxWidth(),
targetState = uiState
) { state ->
when (state) {
State.None -> {
}
is State.Succeed -> {
Content(state.data, padding)
}
is State.Failed -> {
ErrorPage(state.message, Modifier.fillMaxWidth())
}
State.Searching -> {
Box(Modifier.fillMaxWidth().padding(horizontal = padding)) {
LinearProgressIndicator(Modifier.fillMaxWidth())
}
}
State.WordNotFound -> {
WordNotFound(Modifier.fillMaxSize().padding(vertical = 32.dp))
}
}
}
Result(Modifier.weight(1f).fillMaxWidth(), data, padding)
}
}
}
}
}

@OptIn(ExperimentalAnimationApi::class)
@Composable
private fun Result(modifier: Modifier, data: AppViewModel.Result?, contentPadding: Dp) {
AnimatedContent(modifier = modifier, targetState = data) { data ->
when (data) {
is AppViewModel.Result.Succeed -> Content(data.data, contentPadding)
AppViewModel.Result.WordNotFound -> WordNotFound(
Modifier.fillMaxSize().padding(vertical = 32.dp)
)
is AppViewModel.Result.Failed -> ErrorPage(
data.message,
Modifier.fillMaxWidth()
)
}
}
}

@Composable
private fun Banner(display: Boolean, contentPadding: Dp) {
AnimatedVisibility(display) {
AnimatedVisibility(
display,
enter = fadeIn() + expandVertically(),
exit = fadeOut() + shrinkVertically()
) {
Box(Modifier.fillMaxHeight(0.5f), contentAlignment = Alignment.BottomStart) {
Column(Modifier.padding(vertical = 16.dp, horizontal = contentPadding)) {
Title()
Expand Down Expand Up @@ -152,7 +146,7 @@ private fun CollinsDivider() {

@Composable
private fun Content(word: Word, contentPadding: Dp) {
ColumnWithScrollBar(Modifier.fillMaxWidth()) {
ColumnWithScrollBar(Modifier.fillMaxSize()) {
Spacer(Modifier.height(4.dp))
word.cobuildDictionary.sections.forEach { section ->
CobuildDictionarySection(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package me.konyaco.collinsdictionary.ui
package me.konyaco.collinsdictionary.ui.component

import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package me.konyaco.collinsdictionary.ui.component

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
Expand All @@ -13,7 +13,6 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.platform.LocalTextInputService
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.ImeAction
Expand All @@ -28,51 +27,67 @@ fun SearchBox(
modifier: Modifier,
value: String,
onValueChange: (newValue: String) -> Unit,
isSearching: Boolean,
onSearchClick: () -> Unit
) {
Surface(modifier, color = myColors.searchBoxBackground) {
Box(contentAlignment = Alignment.CenterStart) {
BasicTextField(
modifier = Modifier.matchParentSize(),
value = value,
onValueChange = onValueChange,
singleLine = true,
cursorBrush = SolidColor(MaterialTheme.colors.primary),
keyboardActions = KeyboardActions(
onDone = { onSearchClick() },
onSearch = { onSearchClick() }
),
keyboardOptions = KeyboardOptions(
capitalization = KeyboardCapitalization.None,
keyboardType = KeyboardType.Ascii,
imeAction = ImeAction.Search
),
textStyle = TextStyle(
color = myColors.onSearchBox.copy(0.6f),
fontSize = 16.sp,
fontWeight = FontWeight.Normal
),
maxLines = 1,
decorationBox = {
Box(
modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp),
contentAlignment = Alignment.CenterStart
) {
it()
if (value.isEmpty()) Text(
"Search...",
fontSize = 16.sp,
color = myColors.onSearchBox.copy(0.6f)
)
Column(modifier.fillMaxWidth()) {
Surface(Modifier.fillMaxWidth().wrapContentHeight(), color = myColors.searchBoxBackground) {
Box(modifier = Modifier.fillMaxWidth(), contentAlignment = Alignment.CenterStart) {
BasicTextField(
modifier = Modifier.matchParentSize(),
value = value,
onValueChange = onValueChange,
singleLine = true,
cursorBrush = SolidColor(MaterialTheme.colors.primary),
keyboardActions = KeyboardActions(
onDone = { onSearchClick() },
onSearch = { onSearchClick() }
),
keyboardOptions = KeyboardOptions(
capitalization = KeyboardCapitalization.None,
keyboardType = KeyboardType.Ascii,
imeAction = ImeAction.Search
),
textStyle = TextStyle(
color = myColors.onSearchBox.copy(0.6f),
fontSize = 16.sp,
fontWeight = FontWeight.Normal
),
maxLines = 1,
decorationBox = {
Box(
modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp),
contentAlignment = Alignment.CenterStart
) {
it()
if (value.isEmpty()) Text(
"Search...",
fontSize = 16.sp,
color = myColors.onSearchBox.copy(0.6f)
)
}
}
}
)
)

IconButton(
modifier = Modifier.align(Alignment.CenterEnd),
onClick = onSearchClick
IconButton(
modifier = Modifier.align(Alignment.CenterEnd),
onClick = onSearchClick,
enabled = !isSearching && value.isNotBlank()
) {
Icon(
Icons.Filled.Search, "Search", tint = myColors.onSearchBox
.copy(LocalContentAlpha.current)
)
}
}
}
Box(Modifier.height(4.dp).fillMaxWidth()) {
androidx.compose.animation.AnimatedVisibility(
isSearching,
enter = fadeIn(),
exit = fadeOut()
) {
Icon(Icons.Filled.Search, "Search", tint = myColors.onSearchBox)
LinearProgressIndicator(Modifier.fillMaxWidth())
}
}
}
Expand Down
Loading

0 comments on commit 97ea52f

Please sign in to comment.