Use account configuration in FeedTab

This commit is contained in:
Shinokuni 2024-05-19 22:17:34 +02:00
parent ffe2d5cffb
commit 351409bb26
8 changed files with 62 additions and 40 deletions

View File

@ -59,7 +59,7 @@ public class ManageFeedsFoldersActivity extends AppCompatActivity {
@Override @Override
public boolean onCreateOptionsMenu(Menu menu) { public boolean onCreateOptionsMenu(Menu menu) {
if (account.getAccountType().getAccountConfig().isFolderCreation()) if (account.getAccountType().getAccountConfig().getCanCreateFolder())
getMenuInflater().inflate(R.menu.feeds_menu, menu); getMenuInflater().inflate(R.menu.feeds_menu, menu);
return super.onCreateOptionsMenu(menu); return super.onCreateOptionsMenu(menu);

View File

@ -116,7 +116,7 @@ public class EditFeedDialogFragment extends DialogFragment implements AdapterVie
feedUrl = v.findViewById(R.id.edit_feed_url_edit_text); feedUrl = v.findViewById(R.id.edit_feed_url_edit_text);
folder = v.findViewById(R.id.edit_feed_folder_spinner); folder = v.findViewById(R.id.edit_feed_folder_spinner);
if (!account.getAccountType().getAccountConfig().isFeedUrlEditable()) if (!account.getAccountType().getAccountConfig().isFeedUrlReadOnly())
feedUrl.setEnabled(false); feedUrl.setEnabled(false);
feedName.setText(feedWithFolder.getFeed().getName()); feedName.setText(feedWithFolder.getFeed().getName());

View File

@ -23,7 +23,7 @@ val composeAppModule = module {
factory { TimelineScreenModel(get(), get()) } factory { TimelineScreenModel(get(), get()) }
factory { FeedScreenModel(get(), get(), get()) } factory { FeedScreenModel(get(), get(), get(), androidContext()) }
factory { AccountSelectionScreenModel(get()) } factory { AccountSelectionScreenModel(get()) }

View File

@ -1,9 +1,11 @@
package com.readrops.app.compose.feeds package com.readrops.app.compose.feeds
import android.content.Context
import android.util.Patterns import android.util.Patterns
import cafe.adriel.voyager.core.model.screenModelScope import cafe.adriel.voyager.core.model.screenModelScope
import com.readrops.api.localfeed.LocalRSSDataSource import com.readrops.api.localfeed.LocalRSSDataSource
import com.readrops.api.utils.HtmlParser import com.readrops.api.utils.HtmlParser
import com.readrops.app.compose.R
import com.readrops.app.compose.base.TabScreenModel import com.readrops.app.compose.base.TabScreenModel
import com.readrops.app.compose.repositories.GetFoldersWithFeeds import com.readrops.app.compose.repositories.GetFoldersWithFeeds
import com.readrops.app.compose.util.components.TextFieldError import com.readrops.app.compose.util.components.TextFieldError
@ -29,6 +31,7 @@ class FeedScreenModel(
database: Database, database: Database,
private val getFoldersWithFeeds: GetFoldersWithFeeds, private val getFoldersWithFeeds: GetFoldersWithFeeds,
private val localRSSDataSource: LocalRSSDataSource, private val localRSSDataSource: LocalRSSDataSource,
private val context: Context
) : TabScreenModel(database), KoinComponent { ) : TabScreenModel(database), KoinComponent {
private val _feedState = MutableStateFlow(FeedState()) private val _feedState = MutableStateFlow(FeedState())
@ -47,6 +50,14 @@ class FeedScreenModel(
screenModelScope.launch(context = Dispatchers.IO) { screenModelScope.launch(context = Dispatchers.IO) {
accountEvent accountEvent
.flatMapConcat { account -> .flatMapConcat { account ->
_feedState.update { it.copy(displayFolderCreationButton = account.config.canCreateFolder) }
_updateFeedDialogState.update {
it.copy(
isFeedUrlReadOnly = account.config.isFeedUrlReadOnly,
isNoFolderCase = account.config.isNoFolderCase
)
}
getFoldersWithFeeds.get(account.id, MainFilter.ALL) getFoldersWithFeeds.get(account.id, MainFilter.ALL)
} }
.catch { throwable -> .catch { throwable ->
@ -77,14 +88,24 @@ class FeedScreenModel(
screenModelScope.launch(context = Dispatchers.IO) { screenModelScope.launch(context = Dispatchers.IO) {
accountEvent accountEvent
.flatMapConcat { account -> .flatMapConcat { account ->
_updateFeedDialogState.update {
it.copy(
isFeedUrlReadOnly = account.config.isFeedUrlReadOnly,
isNoFolderCase = account.config.isNoFolderCase
)
}
database.newFolderDao() database.newFolderDao()
.selectFolders(account.id) .selectFolders(account.id)
} }
.collect { folders -> .collect { folders ->
_updateFeedDialogState.update { _updateFeedDialogState.update {
it.copy( it.copy(
folders = folders, folders = if (!it.isNoFolderCase) { // TODO implement no folder case properly
accountType = currentAccount!!.accountType folders + listOf(Folder(id = 0, name = context.resources.getString(R.string.no_folder)))
} else {
folders
}
) )
} }
} }

View File

@ -4,12 +4,12 @@ import com.readrops.app.compose.util.components.TextFieldError
import com.readrops.db.entities.Feed import com.readrops.db.entities.Feed
import com.readrops.db.entities.Folder import com.readrops.db.entities.Folder
import com.readrops.db.entities.account.Account import com.readrops.db.entities.account.Account
import com.readrops.db.entities.account.AccountType
data class FeedState( data class FeedState(
val foldersAndFeeds: FolderAndFeedsState = FolderAndFeedsState.InitialState, val foldersAndFeeds: FolderAndFeedsState = FolderAndFeedsState.InitialState,
val dialog: DialogState? = null, val dialog: DialogState? = null,
val areFoldersExpanded: Boolean = false val areFoldersExpanded: Boolean = false,
val displayFolderCreationButton: Boolean = false
) )
sealed interface DialogState { sealed interface DialogState {
@ -43,10 +43,11 @@ data class UpdateFeedDialogState(
val feedNameError: TextFieldError? = null, val feedNameError: TextFieldError? = null,
val feedUrl: String = "", val feedUrl: String = "",
val feedUrlError: TextFieldError? = null, val feedUrlError: TextFieldError? = null,
val accountType: AccountType? = null,
val selectedFolder: Folder? = null, val selectedFolder: Folder? = null,
val folders: List<Folder> = listOf(), val folders: List<Folder> = listOf(),
val isAccountDropDownExpanded: Boolean = false, val isAccountDropDownExpanded: Boolean = false,
val isFeedUrlReadOnly: Boolean = true,
val isNoFolderCase: Boolean = false
) { ) {
val isFeedNameError val isFeedNameError
get() = feedNameError != null get() = feedNameError != null
@ -54,9 +55,6 @@ data class UpdateFeedDialogState(
val isFeedUrlError val isFeedUrlError
get() = feedUrlError != null get() = feedUrlError != null
val isFeedUrlReadOnly: Boolean
get() = accountType != null && !accountType.accountConfig!!.isFeedUrlEditable
val hasFolders = folders.isNotEmpty() val hasFolders = folders.isNotEmpty()
} }

View File

@ -178,19 +178,21 @@ object FeedTab : Tab {
}, },
floatingActionButton = { floatingActionButton = {
Column { Column {
SmallFloatingActionButton( if (state.displayFolderCreationButton) {
modifier = Modifier SmallFloatingActionButton(
.padding( modifier = Modifier
start = MaterialTheme.spacing.veryShortSpacing, .padding(
bottom = MaterialTheme.spacing.shortSpacing start = MaterialTheme.spacing.veryShortSpacing,
), bottom = MaterialTheme.spacing.shortSpacing
onClick = { viewModel.openDialog(DialogState.AddFolder) } ),
) { onClick = { viewModel.openDialog(DialogState.AddFolder) }
Icon( ) {
painter = painterResource(id = R.drawable.ic_new_folder), Icon(
contentDescription = null, painter = painterResource(id = R.drawable.ic_new_folder),
modifier = Modifier.size(16.dp) contentDescription = null,
) modifier = Modifier.size(16.dp)
)
}
} }
FloatingActionButton( FloatingActionButton(

View File

@ -57,6 +57,7 @@ fun UpdateFeedDialog(
label = { Text(text = stringResource(R.string.feed_url)) }, label = { Text(text = stringResource(R.string.feed_url)) },
singleLine = true, singleLine = true,
readOnly = state.isFeedUrlReadOnly, readOnly = state.isFeedUrlReadOnly,
enabled = !state.isFeedUrlReadOnly,
isError = state.isFeedUrlError, isError = state.isFeedUrlError,
supportingText = { supportingText = {
if (state.isFeedUrlError) { if (state.isFeedUrlError) {

View File

@ -5,35 +5,35 @@ import kotlinx.parcelize.Parcelize
@Parcelize @Parcelize
data class AccountConfig( data class AccountConfig(
val isFeedUrlEditable: Boolean, // Enables or disables feed url modification in management screen val isFeedUrlReadOnly: Boolean, // Enable or disable feed url modification in Feed Tab
val isFolderCreation: Boolean, // Enables or disables folder creation in management screen val canCreateFolder: Boolean, // Enable or disable folder creation in Feed Tab
val isNoFolderCase: Boolean, // Add a "No folder" option when modifying a feed's folder val isNoFolderCase: Boolean, // Add a "No folder" option when modifying a feed's folder TODO add better name
val useSeparateState: Boolean, // Let knows if it uses ItemState table to synchronize state val useSeparateState: Boolean, // Let know if it uses ItemState table to synchronize read/star state
) : Parcelable { ) : Parcelable {
companion object { companion object {
@JvmField @JvmField
val LOCAL = AccountConfig( val LOCAL = AccountConfig(
isFeedUrlEditable = true, isFeedUrlReadOnly = false,
isFolderCreation = true, canCreateFolder = true,
isNoFolderCase = false, isNoFolderCase = false,
useSeparateState = false, useSeparateState = false,
) )
@JvmField @JvmField
val NEXTCLOUD_NEWS = AccountConfig( val NEXTCLOUD_NEWS = AccountConfig(
isFeedUrlEditable = false, isFeedUrlReadOnly = false,
isFolderCreation = true, canCreateFolder = true,
isNoFolderCase = false, isNoFolderCase = false,
useSeparateState = false, useSeparateState = false,
) )
@JvmField @JvmField
val FRESHRSS = AccountConfig( val FRESHRSS = AccountConfig(
isFeedUrlEditable = false, isFeedUrlReadOnly = true,
isFolderCreation = false, canCreateFolder = false,
isNoFolderCase = true, isNoFolderCase = true,
useSeparateState = true, useSeparateState = true,
) )
} }
} }