Created
April 20, 2022 16:32
-
-
Save morganbovi/7abebad65f49638947cc9d16e28c08cb to your computer and use it in GitHub Desktop.
Presenter using callbacks instead of and event bus
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// VIEW | |
@Composable | |
fun ArticleScreen() { | |
val presenter: ArticlePresenter by inject() // koin compose ext | |
val model = presenter.present() | |
ArticleView(model, presenter) | |
} | |
@Composable | |
fun ArticleView(uiModel: ArticleUiModel, uiActions: ArticleUiActions) { | |
when (uiModel) { | |
is ArticleUiModel.Loading -> Shimmer() | |
is ArticleUiModel.Data -> { | |
Row { | |
Text(uiModel.title) | |
Button(onClick = { uiActions.onShareArticle() }) { | |
Text(stringResource(R.string.share_article)) | |
} | |
ContentView(uiModel.content) | |
} | |
} | |
} | |
} | |
@Composable | |
fun ContentView(uiModel: ContentUiModel) { | |
when (uiModel) { | |
is ContentUiModel.Error -> Unit // nothing to render | |
is ContentUiModel.Data -> Text(uiModel.content) | |
} | |
} | |
// PRESENTATION | |
sealed interface ArticleUiModel : UiModel { | |
object Loading : ArticleUiModel | |
data class Data(val title: String, val content: ContentUiModel) : ArticleUiModel | |
} | |
class ArticlePresenter( | |
private val resourceFetcher: ResourceFetcher, | |
private val navigator: Navigator, | |
private val getLatestArticleUseCase: GetLatestArticleUseCase, | |
private val contentPresenter: ContentPresenter | |
) : ArticleUiActions, ResourceFetcher by resourceFetcher { | |
@Composable | |
fun present(): ArticleUiModel { | |
val latestArticleResult by getLatestArticleUseCase.toFlow().collectAsState(initial = null) | |
val latestArticle = latestArticleResult?.getOrNull() ?: return ArticleUiModel.Loading | |
return ArticleUiModel.Data( | |
title = latestArticle.title, | |
content = contentPresenter.present(latestArticle.content) | |
) | |
} | |
override fun onShareArticle() { | |
val message = getString(R.string.share_article_message, latestArticle.title) | |
navigator.navigate(IntentTarget.Share(message)) | |
} | |
} | |
interface ArticleUiActions { | |
fun onShareArticle() | |
} | |
sealed interface ContentUiModel : UiModel { | |
object Error : ContentUiModel | |
data class Data(val content: String) : ContentUiModel | |
} | |
class ContentPresenter( | |
private val formatArticleContentUseCase: FormatArticleContentUseCase | |
) { | |
@Composable | |
fun present(articleContent: String): ContentUiModel { | |
// cache result from SynchronousUseCase | |
val formattedContentResult = remember(articleContent) { | |
formartArticleContentUseCase(FormartArticleContentUseCase.Params(articleContent)) | |
} | |
return formattedContentResult.getOrNull()?.let { formattedContent -> | |
ContentUiModel.Data(formattedContent) | |
} ?: ContentUiModel.Error | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment