Skip to content

Commit

Permalink
Add update auth dialog (#111)
Browse files Browse the repository at this point in the history
  • Loading branch information
jocmp committed Jun 22, 2024
1 parent 7cb566f commit cd2f0e0
Show file tree
Hide file tree
Showing 25 changed files with 556 additions and 152 deletions.
1 change: 1 addition & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ dependencies {

implementation("androidx.activity:activity-compose:1.9.0")
implementation("androidx.compose.material3:material3")
implementation("androidx.compose.material:material-icons-extended")
implementation("androidx.compose.material3.adaptive:adaptive:1.0.0-alpha11")
implementation("androidx.compose.material3.adaptive:adaptive-layout:1.0.0-alpha11")
implementation("androidx.compose.material3.adaptive:adaptive-navigation:1.0.0-alpha11")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,14 @@ fun ArticleLayout(
onMarkAllRead: (range: MarkRead) -> Unit,
onRemoveFeed: (feedID: String, onSuccess: () -> Unit, onFailure: () -> Unit) -> Unit,
drawerValue: DrawerValue = DrawerValue.Closed,
showUnauthorizedMessage: Boolean,
onUnauthorizedDismissRequest: () -> Unit
) {
val templateColors = articleTemplateColors()
val (isInitialized, setInitialized) = rememberSaveable { mutableStateOf(false) }
val (isUpdatePasswordDialogOpen, setUpdatePasswordDialogOpen) = rememberSaveable {
mutableStateOf(false)
}
val drawerState = rememberDrawerState(drawerValue)
val coroutineScope = rememberCoroutineScope()
val scaffoldNavigator = rememberListDetailPaneScaffoldNavigator()
Expand All @@ -100,6 +105,11 @@ fun ArticleLayout(
val unsubscribeErrorMessage = stringResource(R.string.unsubscribe_error)
val currentFeed = findCurrentFeed(filter, allFeeds)

val openUpdatePasswordDialog = {
onUnauthorizedDismissRequest()
setUpdatePasswordDialogOpen(true)
}

val navigateToDetail = {
scaffoldNavigator.navigateTo(ListDetailPaneScaffoldRole.Detail)
}
Expand Down Expand Up @@ -276,6 +286,25 @@ fun ArticleLayout(
}
)

if (showUnauthorizedMessage) {
UnauthorizedAlertDialog(
onConfirm = openUpdatePasswordDialog,
onDismissRequest = onUnauthorizedDismissRequest,
)
}

if (isUpdatePasswordDialogOpen) {
UpdateAuthDialog(
onSuccess = { message ->
setUpdatePasswordDialogOpen(false)
showSnackbar(message)
},
onDismissRequest = {
setUpdatePasswordDialogOpen(false)
}
)
}

LaunchedEffect(Unit) {
if (!isInitialized) {
state.startRefresh()
Expand Down Expand Up @@ -329,6 +358,8 @@ fun ArticleLayoutPreview() {
onToggleArticleStar = {},
onMarkAllRead = {},
drawerValue = DrawerValue.Open,
showUnauthorizedMessage = false,
onUnauthorizedDismissRequest = {}
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,7 @@ fun ArticleScreen(
onToggleArticleRead = viewModel::toggleArticleRead,
onToggleArticleStar = viewModel::toggleArticleStar,
onMarkAllRead = viewModel::markAllRead,
showUnauthorizedMessage = viewModel.showUnauthorizedMessage,
onUnauthorizedDismissRequest = viewModel::dismissUnauthorizedMessage
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ package com.jocmp.capyreader.ui.articles

import android.app.Application
import android.content.Context
import android.util.Log
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.viewModelScope
import androidx.paging.PagingData
Expand All @@ -16,6 +19,7 @@ import com.jocmp.capy.Feed
import com.jocmp.capy.Folder
import com.jocmp.capy.MarkRead
import com.jocmp.capy.buildPager
import com.jocmp.capy.common.UnauthorizedError
import com.jocmp.capy.countAll
import com.jocmp.capyreader.common.AppPreferences
import com.jocmp.capyreader.sync.addStarAsync
Expand All @@ -42,7 +46,9 @@ class ArticleScreenViewModel(

val filter = MutableStateFlow(appPreferences.filter.get())

private val articleState = mutableStateOf(account.findArticle(appPreferences.articleID.get()))
private var _article by mutableStateOf(account.findArticle(appPreferences.articleID.get()))

private var _showUnauthorizedMessage by mutableStateOf(UnauthorizedMessageState.HIDE)

private val _counts = filter.flatMapLatest { latestFilter ->
account.countAll(latestFilter.status)
Expand All @@ -68,8 +74,11 @@ class ArticleScreenViewModel(
it.values.sum()
}

val showUnauthorizedMessage: Boolean
get() = _showUnauthorizedMessage == UnauthorizedMessageState.SHOW

val article: Article?
get() = articleState.value
get() = _article

private val filterStatus: ArticleStatus
get() = filter.value.status
Expand Down Expand Up @@ -130,30 +139,33 @@ class ArticleScreenViewModel(
}
)
}

}

fun refreshFeed(onComplete: () -> Unit) {
refreshJob?.cancel()

refreshJob = viewModelScope.launch(Dispatchers.IO) {
account.refresh()
account.refresh().onFailure { throwable ->
if (throwable is UnauthorizedError && _showUnauthorizedMessage == UnauthorizedMessageState.HIDE) {
_showUnauthorizedMessage = UnauthorizedMessageState.SHOW
}
}

onComplete()
}
}

fun selectArticle(articleID: String, completion: (article: Article) -> Unit) {
viewModelScope.launch {
articleState.value = account.findArticle(articleID = articleID)?.copy(read = true)
articleState.value?.let(completion)
_article = account.findArticle(articleID = articleID)?.copy(read = true)
_article?.let(completion)
appPreferences.articleID.set(articleID)
markRead(articleID)
}
}

fun toggleArticleRead() {
articleState.value?.let { article ->
_article?.let { article ->
viewModelScope.launch {
if (article.read) {
markUnread(article.id)
Expand All @@ -162,26 +174,30 @@ class ArticleScreenViewModel(
}
}

articleState.value = article.copy(read = !article.read)
_article = article.copy(read = !article.read)
}
}

fun toggleArticleStar() {
articleState.value?.let { article ->
_article?.let { article ->
viewModelScope.launch {
if (article.starred) {
removeStar(article.id)
} else {
addStar(article.id)
}

articleState.value = article.copy(starred = !article.starred)
_article = article.copy(starred = !article.starred)
}
}
}

fun dismissUnauthorizedMessage() {
_showUnauthorizedMessage = UnauthorizedMessageState.LATER
}

fun clearArticle() {
articleState.value = null
_article = null

viewModelScope.launch {
appPreferences.articleID.delete()
Expand Down Expand Up @@ -246,6 +262,12 @@ class ArticleScreenViewModel(

private val context: Context
get() = application.applicationContext

enum class UnauthorizedMessageState {
HIDE,
SHOW,
LATER,
}
}

private fun <T : Countable> List<T>.withPositiveCount(status: ArticleStatus): List<T> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,7 @@ internal val articlesModule = module {
appPreferences = get()
)
}
viewModel {
UpdateAuthViewModel(get())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,7 @@ fun EditFeedDialog(
}

Dialog(onDismissRequest = onCancel) {
Card(
shape = RoundedCornerShape(16.dp)
) {
Card {
EditFeedView(
feed = feed,
folders = folders,
Expand Down
26 changes: 17 additions & 9 deletions app/src/main/java/com/jocmp/capyreader/ui/articles/EditFeedView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,16 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Button
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Switch
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TextField
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
Expand All @@ -26,7 +28,6 @@ import com.jocmp.capy.EditFeedFormEntry
import com.jocmp.capy.Feed
import com.jocmp.capy.Folder
import com.jocmp.capyreader.R
import com.jocmp.capyreader.ui.components.TextField
import com.jocmp.capyreader.ui.fixtures.FeedPreviewFixture

@Composable
Expand Down Expand Up @@ -65,10 +66,12 @@ fun EditFeedView(
}

Column(
Modifier
.padding(16.dp)
verticalArrangement = Arrangement.spacedBy(8.dp),
modifier = Modifier
.verticalScroll(scrollState)
.padding(16.dp)
) {

TextField(
value = name,
onValueChange = setName,
Expand All @@ -79,7 +82,8 @@ fun EditFeedView(
keyboardOptions = KeyboardOptions(
capitalization = KeyboardCapitalization.Words,
autoCorrect = false
)
),
modifier = Modifier.fillMaxWidth()
)
TextField(
value = addedFolder,
Expand All @@ -90,9 +94,13 @@ fun EditFeedView(
keyboardOptions = KeyboardOptions(
capitalization = KeyboardCapitalization.Words,
autoCorrect = false
)
),
modifier = Modifier.fillMaxWidth()
)
Column(modifier = Modifier.padding(horizontal = 16.dp)) {
Column(
modifier = Modifier
.padding(horizontal = 8.dp)
) {
displaySwitchFolders.forEach { (folderTitle, checked) ->
Row(
horizontalArrangement = Arrangement.SpaceBetween,
Expand All @@ -108,13 +116,13 @@ fun EditFeedView(
}
}
Row(
horizontalArrangement = Arrangement.End,
horizontalArrangement = Arrangement.spacedBy(8.dp, alignment = Alignment.End),
modifier = Modifier.fillMaxWidth()
) {
TextButton(onClick = onCancel) {
Text(stringResource(R.string.feed_form_cancel))
}
Button(onClick = { submitFeed() }) {
TextButton(onClick = { submitFeed() }) {
Text(stringResource(R.string.edit_feed_submit))
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,15 @@ fun FilterAppBarTitle(
allFeeds: List<Feed>,
folders: List<Folder>,
) {
val articleStatusTitle = (filter as? ArticleFilter.Articles)?.run {
stringResource(articleStatus.navigationTitle)
}

val text = remember(filter) {
when (filter) {
is ArticleFilter.Articles -> articleStatusTitle
is ArticleFilter.Feeds -> {
allFeeds.find { it.id == filter.feedID }?.title
}

is ArticleFilter.Folders -> {
folders.find { it.title == filter.folderTitle }?.title
}
}.orEmpty()
}
val text = when (filter) {
is ArticleFilter.Articles -> stringResource(filter.articleStatus.navigationTitle)
is ArticleFilter.Feeds -> {
allFeeds.find { it.id == filter.feedID }?.title
}
is ArticleFilter.Folders -> {
folders.find { it.title == filter.folderTitle }?.title
}
}.orEmpty()

Text(
text,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.jocmp.capyreader.ui.articles

import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import com.jocmp.capyreader.R

@Composable
fun UnauthorizedAlertDialog(
onConfirm: () -> Unit,
onDismissRequest: () -> Unit,
) {
AlertDialog(
title = {
Text(stringResource(R.string.unauthorized_dialog_title))
},
text = {
Text(stringResource(R.string.unauthorized_dialog_description))
},
onDismissRequest = onDismissRequest,
dismissButton = {
TextButton(onClick = onDismissRequest) {
Text(stringResource(R.string.unauthorized_dialog_dismiss_text))
}
},
confirmButton = {
TextButton(onClick = onConfirm) {
Text(stringResource(R.string.unauthorized_dialog_confirm_text))
}
}
)
}
Loading

0 comments on commit cd2f0e0

Please sign in to comment.