Skip to content

Commit

Permalink
Merge branch 'trunk' of github.com:wordpress-mobile/WordPress-Android…
Browse files Browse the repository at this point in the history
… into analysis/use-updated-and-null-proof-media-model-class

# Conflicts:
#	build.gradle
  • Loading branch information
ParaskP7 committed Nov 8, 2023
2 parents 3b3e5a6 + 73d4204 commit 7e568f5
Show file tree
Hide file tree
Showing 35 changed files with 634 additions and 243 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -415,13 +415,15 @@ public static Intent createOpenEditorWithBloggingPromptIntent(
public static Intent openEditorWithPromptAndDismissNotificationIntent(
@NonNull final Context context,
final int notificationId,
final BloggingPromptModel bloggingPrompt,
@Nullable final BloggingPromptModel bloggingPrompt,
@Nullable final Stat stat,
final EntryPoint entryPoint
) {
int promptId = bloggingPrompt != null ? bloggingPrompt.getId() : -1;

final Intent intent = getMainActivityInNewStack(context);
intent.putExtra(WPMainActivity.ARG_OPEN_PAGE, WPMainActivity.ARG_EDITOR);
intent.putExtra(WPMainActivity.ARG_EDITOR_PROMPT_ID, bloggingPrompt.getId());
intent.putExtra(WPMainActivity.ARG_EDITOR_PROMPT_ID, promptId);
intent.putExtra(WPMainActivity.ARG_DISMISS_NOTIFICATION, notificationId);
intent.putExtra(WPMainActivity.ARG_EDITOR_ORIGIN, entryPoint);
intent.putExtra(WPMainActivity.ARG_STAT_TO_TRACK, stat);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,26 @@ package org.wordpress.android.ui.bloggingprompts

import org.wordpress.android.models.ReaderTag
import org.wordpress.android.models.ReaderTagType
import org.wordpress.android.ui.reader.services.post.ReaderPostLogic
import org.wordpress.android.ui.reader.utils.ReaderUtilsWrapper
import javax.inject.Inject

object BloggingPromptsPostTagProvider {
const val BLOGGING_PROMPT_TAG = "dailyprompt"
private const val BLOGGING_PROMPT_ID_TAG = "dailyprompt-%s"
class BloggingPromptsPostTagProvider @Inject constructor(
private val readerUtilsWrapper: ReaderUtilsWrapper,
) {
fun promptIdTag(
tagUrl: String
): String = readerUtilsWrapper.getTagFromTagUrl(tagUrl)
.takeIf { it.isNotBlank() }
?: BLOGGING_PROMPT_TAG

fun promptIdTag(promptId: Int): String = BLOGGING_PROMPT_ID_TAG.format(promptId)

fun promptIdSearchReaderTag(promptId: Int): ReaderTag = ReaderTag(
promptIdTag(promptId),
promptIdTag(promptId),
promptIdTag(promptId),
ReaderPostLogic.formatFullEndpointForTag(promptIdTag(promptId)),
fun promptIdSearchReaderTag(
tagUrl: String
): ReaderTag = readerUtilsWrapper.getTagFromTagName(
promptIdTag(tagUrl),
ReaderTagType.FOLLOWED,
)

companion object {
const val BLOGGING_PROMPT_TAG = "dailyprompt"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@ class DomainManagementActivity : AppCompatActivity() {
val uiState by viewModel.uiStateFlow.collectAsState()
MyDomainsScreen(
uiState = uiState,
onSearchQueryChanged = viewModel::onSearchQueryChanged,
onDomainTapped = viewModel::onDomainTapped,
onAddDomainTapped = viewModel::onAddDomainClicked,
onFindDomainTapped = viewModel::onAddDomainClicked,
onBackTapped = viewModel::onBackTapped
onBackTapped = viewModel::onBackTapped,
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,22 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import org.wordpress.android.R
import org.wordpress.android.analytics.AnalyticsTracker.Stat
import org.wordpress.android.fluxc.network.rest.wpcom.site.AllDomainsDomain
import org.wordpress.android.fluxc.network.rest.wpcom.site.DomainStatus
import org.wordpress.android.fluxc.network.rest.wpcom.site.StatusType
import org.wordpress.android.modules.UI_THREAD
import org.wordpress.android.ui.domains.management.util.DomainLocalSearchEngine
import org.wordpress.android.ui.domains.usecases.AllDomains
import org.wordpress.android.ui.domains.usecases.FetchAllDomainsUseCase
import org.wordpress.android.util.analytics.AnalyticsTrackerWrapper
Expand All @@ -32,26 +36,53 @@ class DomainManagementViewModel @Inject constructor(
@Named(UI_THREAD) private val mainDispatcher: CoroutineDispatcher,
private val analyticsTracker: AnalyticsTrackerWrapper,
private val fetchAllDomainsUseCase: FetchAllDomainsUseCase,
private val domainLocalSearchEngine: DomainLocalSearchEngine,
) : ScopedViewModel(mainDispatcher) {
private val _actionEvents = MutableSharedFlow<ActionEvent>()
val actionEvents: Flow<ActionEvent> = _actionEvents

private val _uiStateFlow: MutableStateFlow<UiState> = MutableStateFlow(UiState.PopulatedList.Initial)
val uiStateFlow = _uiStateFlow.asStateFlow()

private val searchQuery = MutableStateFlow("")

init {
analyticsTracker.track(Stat.DOMAIN_MANAGEMENT_MY_DOMAINS_SCREEN_SHOWN)
launch {
fetchAllDomainsUseCase.execute().let {
_uiStateFlow.value = when (it) {
AllDomains.Empty -> UiState.Empty
AllDomains.Error -> UiState.Error
is AllDomains.Success -> UiState.PopulatedList.Loaded(it.domains)
}
fetchAllDomains()
}
launch {
searchQuery
.onEach(::filterDomains)
.launchIn(viewModelScope)
}
}

private suspend fun fetchAllDomains() {
fetchAllDomainsUseCase.execute().let {
_uiStateFlow.value = when (it) {
AllDomains.Empty -> UiState.Empty
AllDomains.Error -> UiState.Error
is AllDomains.Success -> UiState.PopulatedList.Loaded.Complete(it.domains)
}
}
}

private fun filterDomains(query: String) {
val domains = when (val state = _uiStateFlow.value) {
is UiState.PopulatedList.Loaded -> state.allDomains
else -> return
}
_uiStateFlow.value = if (query.isBlank()) {
UiState.PopulatedList.Loaded.Complete(allDomains = domains)
} else {
UiState.PopulatedList.Loaded.Filtered(
filtered = domainLocalSearchEngine.filter(domains, query),
allDomains = domains
)
}
}

fun onDomainTapped(detailUrl: String) {
analyticsTracker.track(Stat.DOMAIN_MANAGEMENT_MY_DOMAINS_SCREEN_DOMAIN_TAPPED)
launch {
Expand All @@ -72,6 +103,12 @@ class DomainManagementViewModel @Inject constructor(
}
}

fun onSearchQueryChanged(query: String) {
launch {
searchQuery.emit(query.trim())
}
}

sealed class ActionEvent {
data class DomainTapped(val detailUrl: String): ActionEvent()
object AddDomainTapped: ActionEvent()
Expand All @@ -81,12 +118,15 @@ class DomainManagementViewModel @Inject constructor(
sealed class UiState {
sealed class PopulatedList: UiState() {
object Initial: PopulatedList()
data class Loaded(val domains: List<AllDomainsDomain>): PopulatedList()

fun filter(query: String): PopulatedList = if (this is Loaded) {
copy(domains = domains.filter { domain -> domain.matches(query) })
} else {
this
sealed class Loaded : PopulatedList() {
abstract val allDomains: List<AllDomainsDomain>
data class Complete(
override val allDomains: List<AllDomainsDomain>
): Loaded()
data class Filtered(
override val allDomains: List<AllDomainsDomain>,
val filtered: List<AllDomainsDomain>
) : Loaded()
}
}
object Empty: UiState()
Expand Down Expand Up @@ -169,7 +209,3 @@ val DomainStatus.isBold
null -> true
else -> false
}

private fun AllDomainsDomain.matches(query: String) =
domain?.contains(query, true) ?: false
|| siteSlug?.contains(query, true) ?: false
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,8 @@ import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
Expand All @@ -39,16 +36,17 @@ import androidx.compose.ui.zIndex
import org.wordpress.android.R
import org.wordpress.android.ui.compose.components.MainTopAppBar
import org.wordpress.android.ui.compose.components.NavigationIcons
import org.wordpress.android.ui.compose.theme.AppColor
import org.wordpress.android.ui.domains.management.DomainManagementViewModel.UiState
import org.wordpress.android.ui.domains.management.DomainManagementViewModel.UiState.Empty
import org.wordpress.android.ui.domains.management.DomainManagementViewModel.UiState.Error
import org.wordpress.android.ui.domains.management.DomainManagementViewModel.UiState.PopulatedList
import org.wordpress.android.ui.domains.management.composable.DomainsSearchTextField
import org.wordpress.android.ui.domains.management.composable.PrimaryButton

@Composable
fun MyDomainsScreen(
uiState: UiState,
onSearchQueryChanged: (String) -> Unit,
onDomainTapped: (detailUrl: String) -> Unit,
onAddDomainTapped: () -> Unit,
onFindDomainTapped: () -> Unit,
Expand Down Expand Up @@ -87,12 +85,15 @@ fun MyDomainsScreen(
MyDomainsSearchInput(
elevation.value,
queryString = queryString,
onQueryStringChanged = { queryString = it },
onQueryStringChanged = {
queryString = it
onSearchQueryChanged(it)
},
enabled = uiState is PopulatedList.Loaded,
)
when (uiState) {
is PopulatedList -> MyDomainsList(
listUiState = uiState.filter(queryString),
listUiState = uiState,
listState = listState,
onDomainTapped,
)
Expand Down Expand Up @@ -151,27 +152,6 @@ fun EmptyScreen(onFindDomainTapped: () -> Unit) {
}
}

@Composable
fun PrimaryButton(
onClick: () -> Unit,
text: String,
modifier: Modifier = Modifier,
) {
Button(
onClick = onClick,
modifier = modifier,
shape = RoundedCornerShape(4.dp),
colors = ButtonDefaults.buttonColors(
contentColor = AppColor.White,
),
) {
Text(
text = text,
style = MaterialTheme.typography.labelLarge,
)
}
}


@Composable
fun MyDomainsSearchInput(
Expand Down Expand Up @@ -211,8 +191,14 @@ fun MyDomainsList(
}
}

is PopulatedList.Loaded -> {
items(items = listUiState.domains) {
is PopulatedList.Loaded.Complete -> {
items(items = listUiState.allDomains) {
DomainListCard(uiState = DomainCardUiState.fromDomain(domain = it), onDomainTapped)
}
}

is PopulatedList.Loaded.Filtered -> {
items(items = listUiState.filtered) {
DomainListCard(uiState = DomainCardUiState.fromDomain(domain = it), onDomainTapped)
}
}
Expand All @@ -227,6 +213,7 @@ fun PreviewMyDomainsScreen() {
M3Theme {
MyDomainsScreen(
uiState = PopulatedList.Initial,
onSearchQueryChanged = {},
onAddDomainTapped = {},
onDomainTapped = {},
onFindDomainTapped = {},
Expand All @@ -242,6 +229,7 @@ fun PreviewMyDomainsScreenError() {
M3Theme {
MyDomainsScreen(
uiState = Error,
onSearchQueryChanged = {},
onAddDomainTapped = {},
onDomainTapped = {},
onFindDomainTapped = {},
Expand All @@ -257,6 +245,7 @@ fun PreviewMyDomainsScreenEmpty() {
M3Theme {
MyDomainsScreen(
uiState = Empty,
onSearchQueryChanged = {},
onAddDomainTapped = {},
onDomainTapped = {},
onFindDomainTapped = {},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package org.wordpress.android.ui.domains.management.composable

import android.content.res.Configuration
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.CircularProgressIndicator
import androidx.compose.material.LocalContentColor
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import org.wordpress.android.ui.compose.theme.AppColor
import org.wordpress.android.ui.domains.management.M3Theme

@Composable
fun PrimaryButton(
onClick: () -> Unit,
text: String,
modifier: Modifier = Modifier,
isEnabled: Boolean = true,
isInProgress: Boolean = false,
) {
Button(
onClick = onClick,
enabled = isEnabled,
modifier = modifier,
shape = RoundedCornerShape(4.dp),
colors = ButtonDefaults.buttonColors(
contentColor = AppColor.White,
),
) {
if (isInProgress) {
CircularProgressIndicator(
color = LocalContentColor.current,
strokeWidth = 2.dp,
modifier = Modifier.size(20.dp),
)
} else {
Text(
text = text,
style = MaterialTheme.typography.labelLarge,
)
}
}
}

@Preview
@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
private fun PrimaryButtonPreview() {
M3Theme {
PrimaryButton(text = "Continue", onClick = {})
}
}

@Preview
@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
private fun PrimaryButtonInProgressPreview() {
M3Theme {
PrimaryButton(text = "Continue", onClick = {}, isInProgress = true)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class NewDomainSearchActivity : AppCompatActivity() {
onSearchQueryChanged = viewModel::onSearchQueryChanged,
onTransferDomainClicked = viewModel::onTransferDomainClicked,
onDomainTapped = viewModel::onDomainTapped,
onBackPressed = viewModel::onBackPressed
onBackPressed = viewModel::onBackPressed,
)
}
}
Expand Down
Loading

0 comments on commit 7e568f5

Please sign in to comment.