Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add update auth dialog #111

Merged
merged 1 commit into from
Jun 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
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
Loading