Skip to content

Commit

Permalink
fix: ui issues in compose (#970)
Browse files Browse the repository at this point in the history
* fix: clickable area incorrect in settings

In the settings screen the clickable area is too small, fix the order of modifiers to fix this.

* fix: hide the plus one icon on completed series

* fix: rating dialog not taking material colours

* fix: throw auth error if we get a 401

If we get a 401 during normal operation, then attempt to refresh and throw an error if we cant.

* feat: add autofill to the login screen

Add a new extension method to allow autofill and use this on the credentials screen.

* style: fix ktlint issues

* chore: add gitignore line for deployment targets

* style: fix code style difference

* fix: incorrect clickable height on rating preference

* fix: whole line not selectable in config

Update padding to include the whole line in the config screen.

* fix: rating dialog buttons in wrong location

Move the dialog buttons to be end aligned like the other dialogs.
  • Loading branch information
Chesire authored Apr 23, 2023
1 parent 4427788 commit 0f3c1aa
Show file tree
Hide file tree
Showing 9 changed files with 165 additions and 58 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ captures/
*.iml
.idea/assetWizardSettings.xml
.idea/androidTestResultsUserPreferences.xml
.idea/deploymentTargetDropDown.xml
.idea/workspace.xml
.idea/tasks.xml
.idea/gradle.xml
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
@file:OptIn(ExperimentalComposeUiApi::class)

package com.chesire.nekome.core.compose

import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.autofill.AutofillNode
import androidx.compose.ui.autofill.AutofillType
import androidx.compose.ui.composed
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.layout.boundsInWindow
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.platform.LocalAutofill
import androidx.compose.ui.platform.LocalAutofillTree

/**
* Provides autofill to a view.
* This should be removed once compose completely supports autofill nicely.
*/
fun Modifier.autofill(
autofillTypes: List<AutofillType>,
onFill: ((String) -> Unit)
) = composed {
val autofill = LocalAutofill.current
val autofillNode = AutofillNode(onFill = onFill, autofillTypes = autofillTypes)
LocalAutofillTree.current += autofillNode

this
.onGloballyPositioned { autofillNode.boundingBox = it.boundsInWindow() }
.onFocusChanged { focusState ->
autofill?.run {
if (focusState.isFocused) {
requestAutofillForNode(autofillNode)
} else {
cancelAutofillForNode(autofillNode)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.autofill.AutofillType
import androidx.compose.ui.focus.FocusDirection
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalFocusManager
Expand All @@ -58,6 +59,7 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import com.chesire.nekome.app.login.R
import com.chesire.nekome.core.compose.autofill
import com.chesire.nekome.core.compose.theme.NekomeTheme

@Composable
Expand Down Expand Up @@ -193,9 +195,12 @@ private fun UsernameInput(
isError = isUsernameError,
singleLine = true,
label = { Text(text = stringResource(id = R.string.login_username)) },
modifier = Modifier.semantics {
testTag = CredentialsTags.Username
}
modifier = Modifier
.semantics { testTag = CredentialsTags.Username }
.autofill(
autofillTypes = listOf(AutofillType.EmailAddress, AutofillType.Username),
onFill = { onUsernameChanged(it) }
)
)
}

Expand Down Expand Up @@ -248,9 +253,12 @@ private fun PasswordInput(
isError = isPasswordError,
singleLine = true,
label = { Text(text = stringResource(id = R.string.login_password)) },
modifier = Modifier.semantics {
testTag = CredentialsTags.Password
}
modifier = Modifier
.semantics { testTag = CredentialsTags.Password }
.autofill(
autofillTypes = listOf(AutofillType.Password),
onFill = { onPasswordChanged(it) }
)
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -322,21 +322,23 @@ private fun SeriesItem(
style = MaterialTheme.typography.bodyMedium,
modifier = Modifier.align(Alignment.CenterVertically)
)
IconButton(
modifier = Modifier
.alpha(if (model.isUpdating) 0.3f else 1f)
.align(Alignment.CenterVertically)
.semantics { testTag = SeriesCollectionTags.PlusOne },
enabled = !model.isUpdating,
onClick = { onIncrementSeries(model) }
) {
Icon(
imageVector = Icons.Default.PlusOne,
contentDescription = stringResource(
id = R.string.series_list_plus_one
),
tint = MaterialTheme.colorScheme.primary
)
if (model.showPlusOne) {
IconButton(
modifier = Modifier
.alpha(if (model.isUpdating) 0.3f else 1f)
.align(Alignment.CenterVertically)
.semantics { testTag = SeriesCollectionTags.PlusOne },
enabled = !model.isUpdating,
onClick = { onIncrementSeries(model) }
) {
Icon(
imageVector = Icons.Default.PlusOne,
contentDescription = stringResource(
id = R.string.series_list_plus_one
),
tint = MaterialTheme.colorScheme.primary
)
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Card
import androidx.compose.material.Slider
import androidx.compose.material.Text
import androidx.compose.material.TextButton
import androidx.compose.material3.Card
import androidx.compose.material3.Slider
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
Expand Down Expand Up @@ -79,9 +79,12 @@ private fun Render(

Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceEvenly
horizontalArrangement = Arrangement.End
) {
TextButton(onClick = { onRatingResult(null) }) {
TextButton(
modifier = Modifier.padding(horizontal = 8.dp),
onClick = { onRatingResult(null) }
) {
Text(text = stringResource(id = R.string.series_list_rate_cancel))
}
TextButton(onClick = { onRatingResult(sliderValue.roundToInt()) }) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ private fun Render(
modifier = Modifier
.padding(paddingValues)
.verticalScroll(state = scrollableState)
.padding(start = 16.dp, top = 16.dp, end = 16.dp)
.padding(top = 16.dp)
.fillMaxSize()
) {
ProfileSection(state.value.userModel, onLogoutClicked)
Expand Down Expand Up @@ -179,6 +179,7 @@ private fun ProfileSection(
if (userModel != null) {
Card(
modifier = Modifier
.padding(horizontal = 16.dp)
.fillMaxWidth()
.wrapContentHeight()
) {
Expand Down Expand Up @@ -259,11 +260,9 @@ private fun RateSeriesPreference(
) {
Row(
modifier = Modifier
.padding(vertical = 8.dp)
.fillMaxWidth()
.clickable {
onRateSeriesClicked(!shouldRateSeries)
},
.clickable { onRateSeriesClicked(!shouldRateSeries) }
.padding(horizontal = 16.dp, vertical = 8.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Expand Down Expand Up @@ -325,7 +324,7 @@ private fun PreferenceHeading(title: String) {
text = title,
style = MaterialTheme.typography.titleLarge,
modifier = Modifier
.padding(top = 16.dp)
.padding(start = 16.dp, top = 16.dp, end = 16.dp)
.fillMaxWidth(),
color = MaterialTheme.colorScheme.primary
)
Expand All @@ -339,9 +338,9 @@ private fun PreferenceSection(
) {
Column(
modifier = Modifier
.padding(vertical = 8.dp)
.fillMaxWidth()
.clickable(enabled = onClick != null) { onClick?.invoke() },
.clickable(enabled = onClick != null) { onClick?.invoke() }
.padding(horizontal = 16.dp, vertical = 8.dp),
verticalArrangement = Arrangement.Center
) {
Text(
Expand Down
1 change: 1 addition & 0 deletions libraries/datasource/auth/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ dependencies {
implementation libs.kotlin.coroutines.core
implementation libs.kotlin.result
implementation libs.squareup.retrofit2
implementation libs.timber

testImplementation project(":testing")
testImplementation libs.junit
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import javax.inject.Inject
import kotlinx.coroutines.runBlocking
import okhttp3.Interceptor
import okhttp3.Response
import timber.log.Timber

/**
* Interceptor to handle refreshing access tokens if required.
Expand All @@ -29,7 +30,8 @@ class AuthRefreshInterceptor @Inject constructor(
val originRequest = chain.request()
val response = chain.proceed(originRequest)

return if (!response.isSuccessful && response.code() == HttpURLConnection.HTTP_FORBIDDEN) {
return if (response.isAuthError) {
Timber.w("Response threw an auth error (${response.code()}), attempting to refresh")
val refreshResponse = runBlocking { repo.refresh() }
if (refreshResponse is AccessTokenResult.Success) {
chain.proceed(
Expand All @@ -39,11 +41,17 @@ class AuthRefreshInterceptor @Inject constructor(
.build()
)
} else {
Timber.w("Could not refresh the token, logging user out")
authCaster.issueRefreshingToken()
throw AuthException()
}
} else {
response
}
}

private val Response.isAuthError: Boolean
get() = !isSuccessful &&
code() == HttpURLConnection.HTTP_FORBIDDEN ||
code() == HttpURLConnection.HTTP_UNAUTHORIZED
}
Loading

0 comments on commit 0f3c1aa

Please sign in to comment.