Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
da67a85
RS Post Settings: Add polish and error handling
nbradbury Mar 12, 2026
fe8fd09
RS Post Settings: Fix review issues from polish PR
nbradbury Mar 12, 2026
13ed3a1
RS Post Settings: Fix detekt and checkstyle issues
nbradbury Mar 12, 2026
f12e57a
RS Post Settings: Fix snackbar navbar overlap and center error content
nbradbury Mar 12, 2026
8f71432
RS Post Settings: Center error content on term selection screen
nbradbury Mar 12, 2026
f3d8f2c
RS Post Settings: Add retry action to save network error snackbar
nbradbury Mar 12, 2026
a6024a6
RS Post Settings: Use primary color for snackbar action button
nbradbury Mar 12, 2026
517eb35
RS Post Settings: Remove pre-flight network check from save to avoid …
nbradbury Mar 12, 2026
8cdf3af
RS Post Settings: Simplify code and remove status bar hiding
nbradbury Mar 12, 2026
d927a7c
RS Post Settings: Use named exception to satisfy detekt
nbradbury Mar 12, 2026
01339c5
RS Post Settings: Cache WpApiClient to avoid repeated instantiation
nbradbury Mar 12, 2026
744858d
RS Post Settings: Remove dead parameters and redundant client cache
nbradbury Mar 12, 2026
71c07f1
RS Post Settings: Fix import ordering, replace crash with handled exc…
nbradbury Mar 12, 2026
54dd368
RS Post Settings: Fix detekt ThrowsCount and ReturnCount violations
nbradbury Mar 12, 2026
0ff0162
Merge trunk into feature/rsposts-settings-performance
nbradbury Mar 13, 2026
5fb0844
RS Post Settings: Replace loading spinner with shimmer skeleton
nbradbury Mar 13, 2026
78ec06d
RS Post Settings: Simplify code and remove redundant null checks
nbradbury Mar 13, 2026
f24dbd0
RS Post Settings: Add author search to author dialog
nbradbury Mar 13, 2026
aee728f
RS Post Settings: Simplify author dialog and deduplicate constant
nbradbury Mar 13, 2026
75355d1
RS Post Settings: Clear author search state when dialog closes
nbradbury Mar 13, 2026
6a94cc0
RS Post Settings: Remove redundant state clearing in onAuthorClicked
nbradbury Mar 13, 2026
d5afc03
Merge trunk into feature/rsposts-author-search
nbradbury Mar 17, 2026
35d91cd
Fix detekt issues: remove unused import and extract hideStatusBar()
nbradbury Mar 17, 2026
b1517e1
Author search: reset pagination on dismiss and show error snackbar
nbradbury Mar 17, 2026
cf58a93
Merge trunk into feature/rsposts-author-search
nbradbury Mar 17, 2026
ff47df2
Author search: disable OK when no results and clear search on confirm
nbradbury Mar 17, 2026
908df5f
Merge trunk into feature/rsposts-author-search
nbradbury Mar 18, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package org.wordpress.android.ui.postsrs

import android.app.Activity
import android.content.Context
import android.content.Intent
import android.os.Bundle
Expand Down Expand Up @@ -33,7 +32,7 @@ class PostRsListActivity : BaseAppCompatActivity() {
private val settingsLauncher = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { result ->
if (result.resultCode == Activity.RESULT_OK) {
if (result.resultCode == RESULT_OK) {
viewModel.refreshAllTabs()
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,16 +52,7 @@ class PostRsSettingsActivity : BaseAppCompatActivity() {
super.onCreate(savedInstanceState)
registerMediaPickerLauncher()
registerTermSelectionLaunchers()

WindowInsetsControllerCompat(
window, window.decorView
).apply {
hide(WindowInsetsCompat.Type.statusBars())
systemBarsBehavior =
WindowInsetsControllerCompat
.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
}

hideStatusBar()
observeEvents()

setContent {
Expand Down Expand Up @@ -101,6 +92,8 @@ class PostRsSettingsActivity : BaseAppCompatActivity() {
onFeaturedImageRemoved =
viewModel::onFeaturedImageRemoved,
onLoadMoreAuthors = viewModel::loadMoreAuthors,
onAuthorSearchQueryChanged =
viewModel::onAuthorSearchQueryChanged,
onSaveClicked = viewModel::onSaveClicked,
onDismissDialog = viewModel::onDismissDialog,
onDiscardConfirmed = viewModel::onDiscardConfirmed,
Expand All @@ -109,6 +102,17 @@ class PostRsSettingsActivity : BaseAppCompatActivity() {
}
}

private fun hideStatusBar() {
WindowInsetsControllerCompat(
window, window.decorView
).apply {
hide(WindowInsetsCompat.Type.statusBars())
systemBarsBehavior =
WindowInsetsControllerCompat
.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
}
}

private fun observeEvents() {
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ data class PostRsSettingsUiState(
val siteAuthors: List<AuthorInfo> = emptyList(),
val isLoadingMoreAuthors: Boolean = false,
val canLoadMoreAuthors: Boolean = false,
val authorSearchQuery: String = "",
val isSearchingAuthors: Boolean = false,
val canEditAuthor: Boolean = false,
val password: String? = null,
val authorName: FieldState = FieldState.Empty,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
Expand All @@ -20,6 +22,7 @@ import org.wordpress.android.fluxc.model.SiteModel
import org.wordpress.android.fluxc.network.rest.wpapi.rs.WpApiClientProvider
import org.wordpress.android.ui.mysite.SelectedSiteRepository
import org.wordpress.android.ui.postsrs.data.PostRsRestClient
import org.wordpress.android.ui.postsrs.data.PostRsRestClient.Companion.AUTHORS_PER_PAGE
import org.wordpress.android.util.AppLog
import org.wordpress.android.util.NetworkUtilsWrapper
import org.wordpress.android.viewmodel.ResourceProvider
Expand Down Expand Up @@ -77,6 +80,7 @@ class PostRsSettingsViewModel @Inject constructor(

private var lastPost: AnyPostWithEditContext? = null
private var nextAuthorPageParams: UserListParams? = null
private var authorSearchJob: Job? = null

init {
if (site == null) {
Expand Down Expand Up @@ -357,6 +361,8 @@ class PostRsSettingsViewModel @Inject constructor(
val current = _uiState.value
val authorName = current.siteAuthors
.firstOrNull { it.id == authorId }?.name
authorSearchJob?.cancel()
nextAuthorPageParams = null
_uiState.update {
it.copy(
editedAuthor = authorId.takeIf { ea ->
Expand All @@ -367,7 +373,11 @@ class PostRsSettingsViewModel @Inject constructor(
} else {
it.authorName
},
dialogState = DialogState.None
dialogState = DialogState.None,
authorSearchQuery = "",
isSearchingAuthors = false,
siteAuthors = emptyList(),
canLoadMoreAuthors = false,
)
}
}
Expand Down Expand Up @@ -663,9 +673,84 @@ class PostRsSettingsViewModel @Inject constructor(
}
}

fun onAuthorSearchQueryChanged(query: String) {
_uiState.update {
it.copy(authorSearchQuery = query)
}
authorSearchJob?.cancel()
val trimmed = query.trim()
if (trimmed.isNotEmpty() &&
trimmed.length < MIN_AUTHOR_SEARCH_LENGTH
) {
return
}
authorSearchJob = viewModelScope.launch {
delay(AUTHOR_SEARCH_DEBOUNCE_MS)
_uiState.update {
it.copy(isSearchingAuthors = true)
}
searchAuthors(trimmed)
}
}

@Suppress("TooGenericExceptionCaught")
private suspend fun searchAuthors(query: String) {
val currentSite = site ?: return
try {
val params = UserListParams(
search = query.ifEmpty { null },
perPage = AUTHORS_PER_PAGE,
)
val page = withContext(Dispatchers.IO) {
restClient.fetchSiteAuthors(
currentSite, params
)
}
nextAuthorPageParams = page.nextPageParams
_uiState.update {
it.copy(
siteAuthors = page.authors,
isSearchingAuthors = false,
canLoadMoreAuthors =
page.nextPageParams != null,
)
}
} catch (e: CancellationException) {
throw e
} catch (e: Exception) {
AppLog.e(
AppLog.T.POSTS,
"Failed to search authors",
e
)
_uiState.update {
it.copy(isSearchingAuthors = false)
}
_snackbarMessages.trySend(
SnackbarMessage(
PostRsErrorUtils.friendlyErrorMessage(
e = e,
resourceProvider =
resourceProvider,
networkUtilsWrapper =
networkUtilsWrapper,
)
)
)
}
}

fun onDismissDialog() {
authorSearchJob?.cancel()
nextAuthorPageParams = null
_uiState.update {
it.copy(dialogState = DialogState.None)
it.copy(
dialogState = DialogState.None,
authorSearchQuery = "",
isSearchingAuthors = false,
siteAuthors = emptyList(),
canLoadMoreAuthors = false,
)
}
}

Expand Down Expand Up @@ -1055,6 +1140,8 @@ class PostRsSettingsViewModel @Inject constructor(

companion object {
const val EXTRA_POST_ID = "extra_post_id"
private const val AUTHOR_SEARCH_DEBOUNCE_MS = 500L
private const val MIN_AUTHOR_SEARCH_LENGTH = 3
private const val ERROR_NO_SITE =
"No site selected"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,7 @@ class PostRsRestClient @Inject constructor(
}

companion object {
private const val AUTHORS_PER_PAGE: UInt = 20u
internal const val AUTHORS_PER_PAGE: UInt = 20u
private const val PER_PAGE = 100u
}
}
Loading
Loading