mirror of https://github.com/readrops/Readrops.git
Implement FreshRSS update/delete folder
This commit is contained in:
parent
064d588b28
commit
219d816483
|
@ -102,7 +102,12 @@ class FeedScreenModel(
|
|||
_updateFeedDialogState.update {
|
||||
it.copy(
|
||||
folders = if (!it.isNoFolderCase) { // TODO implement no folder case properly
|
||||
folders + listOf(Folder(id = 0, name = context.resources.getString(R.string.no_folder)))
|
||||
folders + listOf(
|
||||
Folder(
|
||||
id = 0,
|
||||
name = context.resources.getString(R.string.no_folder)
|
||||
)
|
||||
)
|
||||
} else {
|
||||
folders
|
||||
}
|
||||
|
@ -128,6 +133,7 @@ class FeedScreenModel(
|
|||
it.copy(
|
||||
folder = Folder(),
|
||||
nameError = null,
|
||||
exception = null
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -166,7 +172,11 @@ class FeedScreenModel(
|
|||
|
||||
fun deleteFolder(folder: Folder) {
|
||||
screenModelScope.launch(Dispatchers.IO) {
|
||||
repository?.deleteFolder(folder)
|
||||
try {
|
||||
repository?.deleteFolder(folder)
|
||||
} catch (e: Exception) {
|
||||
_feedState.update { it.copy(exception = e) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -340,17 +350,24 @@ class FeedScreenModel(
|
|||
}
|
||||
|
||||
screenModelScope.launch(Dispatchers.IO) {
|
||||
if (updateFolder) {
|
||||
repository?.updateFolder(_folderState.value.folder)
|
||||
} else {
|
||||
repository?.addFolder(_folderState.value.folder.apply {
|
||||
accountId = currentAccount!!.id
|
||||
})
|
||||
try {
|
||||
if (updateFolder) {
|
||||
repository?.updateFolder(_folderState.value.folder)
|
||||
} else {
|
||||
repository?.addFolder(_folderState.value.folder.apply {
|
||||
accountId = currentAccount!!.id
|
||||
})
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
_folderState.update { it.copy(exception = e) }
|
||||
return@launch
|
||||
}
|
||||
|
||||
closeDialog(DialogState.AddFolder)
|
||||
}
|
||||
}
|
||||
|
||||
fun resetException() = _feedState.update { it.copy(exception = null) }
|
||||
|
||||
// add/update folder
|
||||
}
|
|
@ -9,7 +9,8 @@ data class FeedState(
|
|||
val foldersAndFeeds: FolderAndFeedsState = FolderAndFeedsState.InitialState,
|
||||
val dialog: DialogState? = null,
|
||||
val areFoldersExpanded: Boolean = false,
|
||||
val displayFolderCreationButton: Boolean = false
|
||||
val displayFolderCreationButton: Boolean = false,
|
||||
val exception: Exception? = null
|
||||
)
|
||||
|
||||
sealed interface DialogState {
|
||||
|
@ -61,8 +62,9 @@ data class UpdateFeedDialogState(
|
|||
data class FolderState(
|
||||
val folder: Folder = Folder(),
|
||||
val nameError: TextFieldError? = null,
|
||||
val exception: Exception? = null
|
||||
) {
|
||||
val name = folder.name
|
||||
|
||||
val isError = nameError != null
|
||||
val isTextFieldError = nameError != null
|
||||
}
|
|
@ -17,13 +17,18 @@ import androidx.compose.material3.IconButton
|
|||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.SmallFloatingActionButton
|
||||
import androidx.compose.material3.SnackbarHost
|
||||
import androidx.compose.material3.SnackbarHostState
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.vector.rememberVectorPainter
|
||||
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||
import androidx.compose.ui.platform.LocalUriHandler
|
||||
import androidx.compose.ui.res.painterResource
|
||||
|
@ -38,6 +43,7 @@ import com.readrops.app.compose.feeds.dialogs.AddFeedDialog
|
|||
import com.readrops.app.compose.feeds.dialogs.FeedModalBottomSheet
|
||||
import com.readrops.app.compose.feeds.dialogs.FolderDialog
|
||||
import com.readrops.app.compose.feeds.dialogs.UpdateFeedDialog
|
||||
import com.readrops.app.compose.util.ErrorMessage
|
||||
import com.readrops.app.compose.util.components.CenteredProgressIndicator
|
||||
import com.readrops.app.compose.util.components.ErrorMessage
|
||||
import com.readrops.app.compose.util.components.Placeholder
|
||||
|
@ -59,11 +65,20 @@ object FeedTab : Tab {
|
|||
override fun Content() {
|
||||
val haptic = LocalHapticFeedback.current
|
||||
val uriHandler = LocalUriHandler.current
|
||||
val context = LocalContext.current
|
||||
|
||||
val viewModel = getScreenModel<FeedScreenModel>()
|
||||
|
||||
val state by viewModel.feedsState.collectAsStateWithLifecycle()
|
||||
|
||||
val snackbarHostState = remember { SnackbarHostState() }
|
||||
|
||||
LaunchedEffect(state.exception) {
|
||||
if (state.exception != null) {
|
||||
snackbarHostState.showSnackbar(ErrorMessage.get(state.exception!!, context))
|
||||
viewModel.resetException()
|
||||
}
|
||||
}
|
||||
|
||||
when (val dialog = state.dialog) {
|
||||
is DialogState.AddFeed -> {
|
||||
AddFeedDialog(
|
||||
|
@ -204,7 +219,8 @@ object FeedTab : Tab {
|
|||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
snackbarHost = { SnackbarHost(snackbarHostState) }
|
||||
) { paddingValues ->
|
||||
Box(
|
||||
modifier = Modifier
|
||||
|
|
|
@ -4,16 +4,19 @@ import androidx.compose.material.icons.Icons
|
|||
import androidx.compose.material.icons.filled.Clear
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.OutlinedTextField
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.readrops.app.compose.R
|
||||
import com.readrops.app.compose.feeds.FeedScreenModel
|
||||
import com.readrops.app.compose.util.ErrorMessage
|
||||
import com.readrops.app.compose.util.components.BaseDialog
|
||||
import com.readrops.app.compose.util.theme.LargeSpacer
|
||||
|
||||
|
@ -50,10 +53,17 @@ fun FolderDialog(
|
|||
}
|
||||
}
|
||||
},
|
||||
isError = state.isError,
|
||||
isError = state.isTextFieldError,
|
||||
supportingText = { Text(text = state.nameError?.errorText().orEmpty()) }
|
||||
)
|
||||
|
||||
if (state.exception != null) {
|
||||
Text(
|
||||
text = ErrorMessage.get(state.exception!!, LocalContext.current),
|
||||
color = MaterialTheme.colorScheme.error
|
||||
)
|
||||
}
|
||||
|
||||
LargeSpacer()
|
||||
|
||||
TextButton(
|
||||
|
|
|
@ -85,8 +85,18 @@ class FreshRSSRepository(
|
|||
override suspend fun insertNewFeeds(
|
||||
newFeeds: List<Feed>,
|
||||
onUpdate: (Feed) -> Unit
|
||||
): ErrorResult {
|
||||
TODO("Not yet implemented")
|
||||
): ErrorResult = TODO("Not yet implemented")
|
||||
|
||||
override suspend fun updateFolder(folder: Folder) {
|
||||
dataSource.updateFolder(account.writeToken!!, folder.remoteId!!, folder.name!!)
|
||||
folder.remoteId = NewFreshRSSDataSource.FOLDER_PREFIX + folder.name
|
||||
|
||||
super.updateFolder(folder)
|
||||
}
|
||||
|
||||
override suspend fun deleteFolder(folder: Folder) {
|
||||
dataSource.deleteFolder(account.writeToken!!, folder.remoteId!!)
|
||||
super.deleteFolder(folder)
|
||||
}
|
||||
|
||||
private suspend fun insertFeeds(feeds: List<Feed>) {
|
||||
|
|
|
@ -25,6 +25,7 @@ class GetFoldersWithFeeds(
|
|||
Folder(
|
||||
id = it.folderId!!,
|
||||
name = it.folderName,
|
||||
remoteId = it.folderRemoteId,
|
||||
accountId = it.accountId
|
||||
)
|
||||
} else {
|
||||
|
|
|
@ -13,14 +13,14 @@ interface NewFolderDao : NewBaseDao<Folder> {
|
|||
|
||||
@Query("""
|
||||
Select Feed.id As feedId, Feed.name As feedName, Feed.icon_url As feedIcon, Feed.url As feedUrl,
|
||||
Feed.siteUrl As feedSiteUrl, Feed.description as feedDescription,
|
||||
Folder.id As folderId, Folder.name As folderName, Feed.account_id as accountId
|
||||
Feed.siteUrl As feedSiteUrl, Feed.description as feedDescription, Folder.id As folderId,
|
||||
Folder.name As folderName, Feed.account_id as accountId, Folder.remoteId as folderRemoteId
|
||||
From Feed Left Join Folder On Folder.id = Feed.folder_id
|
||||
Where Feed.folder_id is NULL OR Feed.folder_id is NOT NULL And Feed.id is NULL Or Feed.id is NOT NULL And Feed.account_id = :accountId Group By Feed.id
|
||||
UNION ALL
|
||||
Select Feed.id As feedId, Feed.name As feedName, Feed.icon_url As feedIcon, Feed.url As feedUrl,
|
||||
Feed.siteUrl As feedSiteUrl, Feed.description as feedDescription,
|
||||
Folder.id As folderId, Folder.name As folderName, Folder.account_id as accountId
|
||||
Feed.siteUrl As feedSiteUrl, Feed.description as feedDescription,Folder.id As folderId,
|
||||
Folder.name As folderName, Folder.account_id as accountId, Folder.remoteId as folderRemoteId
|
||||
From Folder Left Join Feed On Folder.id = Feed.folder_id
|
||||
Where Feed.id is NULL And Folder.account_id = :accountId
|
||||
""")
|
||||
|
|
|
@ -15,6 +15,7 @@ data class FeedWithFolder(
|
|||
data class FolderWithFeed(
|
||||
val folderId: Int?,
|
||||
val folderName: String?,
|
||||
val folderRemoteId: String?,
|
||||
val feedId: Int = 0,
|
||||
val feedName: String? = null,
|
||||
val feedIcon: String? = null,
|
||||
|
|
Loading…
Reference in New Issue