mirror of
https://github.com/readrops/Readrops.git
synced 2025-02-03 20:17:35 +01:00
Add AddFolderDialog in FeedTab
This commit is contained in:
parent
caf55451d3
commit
2631712361
@ -87,3 +87,9 @@ data class UpdateFeedDialogState(
|
||||
get() = accountType != null && !accountType.accountConfig!!.isFeedUrlEditable
|
||||
|
||||
}
|
||||
|
||||
data class AddFolderState(
|
||||
val name: String = "",
|
||||
val isEmpty: Boolean = false,
|
||||
val errorText: String = "Field can't be empty"
|
||||
)
|
@ -1,8 +1,10 @@
|
||||
package com.readrops.app.compose.feeds
|
||||
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material.icons.Icons
|
||||
@ -12,12 +14,12 @@ import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.FloatingActionButton
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||
@ -29,10 +31,12 @@ import cafe.adriel.voyager.navigator.tab.Tab
|
||||
import cafe.adriel.voyager.navigator.tab.TabOptions
|
||||
import com.readrops.app.compose.R
|
||||
import com.readrops.app.compose.feeds.dialogs.AddFeedDialog
|
||||
import com.readrops.app.compose.feeds.dialogs.AddFolderDialog
|
||||
import com.readrops.app.compose.feeds.dialogs.DeleteFeedDialog
|
||||
import com.readrops.app.compose.feeds.dialogs.FeedModalBottomSheet
|
||||
import com.readrops.app.compose.feeds.dialogs.UpdateFeedDialog
|
||||
import com.readrops.app.compose.util.components.Placeholder
|
||||
import com.readrops.app.compose.util.theme.spacing
|
||||
import com.readrops.db.entities.Feed
|
||||
import org.koin.androidx.compose.getViewModel
|
||||
|
||||
@ -85,7 +89,14 @@ object FeedTab : Tab {
|
||||
uriHandler.openUri(dialog.feed.siteUrl!!)
|
||||
viewModel.closeDialog()
|
||||
},
|
||||
onUpdate = { viewModel.openDialog(DialogState.UpdateFeed(dialog.feed, dialog.folder)) },
|
||||
onUpdate = {
|
||||
viewModel.openDialog(
|
||||
DialogState.UpdateFeed(
|
||||
dialog.feed,
|
||||
dialog.folder
|
||||
)
|
||||
)
|
||||
},
|
||||
onUpdateColor = {},
|
||||
onDelete = { viewModel.openDialog(DialogState.DeleteFeed(dialog.feed)) },
|
||||
)
|
||||
@ -98,7 +109,17 @@ object FeedTab : Tab {
|
||||
)
|
||||
}
|
||||
|
||||
DialogState.AddFolder -> {}
|
||||
DialogState.AddFolder -> {
|
||||
AddFolderDialog(
|
||||
viewModel = viewModel,
|
||||
onDismiss = {
|
||||
viewModel.closeDialog()
|
||||
viewModel.resetAddFolderState()
|
||||
}
|
||||
|
||||
)
|
||||
}
|
||||
|
||||
is DialogState.DeleteFolder -> {}
|
||||
is DialogState.UpdateFolder -> {}
|
||||
null -> {}
|
||||
@ -122,6 +143,34 @@ object FeedTab : Tab {
|
||||
}
|
||||
)
|
||||
},
|
||||
floatingActionButton = {
|
||||
Column {
|
||||
FloatingActionButton(
|
||||
modifier = Modifier
|
||||
.padding(
|
||||
end = 0.dp,
|
||||
bottom = MaterialTheme.spacing.mediumSpacing
|
||||
)
|
||||
.size(40.dp),
|
||||
onClick = { viewModel.openDialog(DialogState.AddFolder) }
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.ic_new_folder),
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(16.dp)
|
||||
)
|
||||
}
|
||||
|
||||
FloatingActionButton(
|
||||
onClick = { viewModel.openDialog(DialogState.AddFeed) }
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Add,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
) { paddingValues ->
|
||||
Box(
|
||||
modifier = Modifier
|
||||
@ -191,18 +240,6 @@ object FeedTab : Tab {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
FloatingActionButton(
|
||||
modifier = Modifier
|
||||
.align(Alignment.BottomEnd)
|
||||
.padding(16.dp),
|
||||
onClick = { viewModel.openDialog(DialogState.AddFeed) }
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Add,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -35,6 +35,9 @@ class FeedViewModel(
|
||||
private val _updateFeedDialogState = MutableStateFlow(UpdateFeedDialogState())
|
||||
val updateFeedDialogState = _updateFeedDialogState.asStateFlow()
|
||||
|
||||
private val _addFolderState = MutableStateFlow(AddFolderState())
|
||||
val addFolderState = _addFolderState.asStateFlow()
|
||||
|
||||
init {
|
||||
viewModelScope.launch(context = Dispatchers.IO) {
|
||||
accountEvent
|
||||
@ -245,10 +248,47 @@ class FeedViewModel(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// update feed
|
||||
|
||||
// add folder
|
||||
|
||||
fun setFolderName(name: String) = _addFolderState.update {
|
||||
it.copy(
|
||||
name = name,
|
||||
isEmpty = false
|
||||
)
|
||||
}
|
||||
|
||||
fun addFolderValidate() {
|
||||
val name = _addFolderState.value.name
|
||||
|
||||
if (name.isEmpty()) {
|
||||
_addFolderState.update {
|
||||
it.copy(isEmpty = true)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
repository?.addFolder(Folder(name = name, accountId = currentAccount?.id!!))
|
||||
|
||||
closeDialog()
|
||||
resetAddFolderState()
|
||||
}
|
||||
}
|
||||
|
||||
fun resetAddFolderState() {
|
||||
_addFolderState.update {
|
||||
it.copy(
|
||||
name = "",
|
||||
isEmpty = false
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// add folder
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,57 @@
|
||||
package com.readrops.app.compose.feeds.dialogs
|
||||
|
||||
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.OutlinedTextField
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.readrops.app.compose.R
|
||||
import com.readrops.app.compose.feeds.FeedViewModel
|
||||
import com.readrops.app.compose.util.components.BaseDialog
|
||||
|
||||
@Composable
|
||||
fun AddFolderDialog(
|
||||
viewModel: FeedViewModel,
|
||||
onDismiss: () -> Unit
|
||||
) {
|
||||
val state by viewModel.addFolderState.collectAsStateWithLifecycle()
|
||||
|
||||
BaseDialog(
|
||||
title = "Add Folder",
|
||||
icon = painterResource(id = R.drawable.ic_new_folder),
|
||||
onDismiss = { onDismiss() },
|
||||
onValidate = { viewModel.addFolderValidate() }
|
||||
) {
|
||||
OutlinedTextField(
|
||||
value = state.name,
|
||||
label = {
|
||||
Text(text = "URL")
|
||||
},
|
||||
onValueChange = { viewModel.setFolderName(it) },
|
||||
singleLine = true,
|
||||
trailingIcon = {
|
||||
if (state.name.isNotEmpty()) {
|
||||
IconButton(
|
||||
onClick = { viewModel.setFolderName("") }
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Clear,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
isError = state.isEmpty,
|
||||
supportingText = {
|
||||
if (state.isEmpty) {
|
||||
Text(text = state.errorText)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
@ -47,13 +47,13 @@ abstract class BaseRepository(
|
||||
account: Account,
|
||||
) : ARepository(database, account) {
|
||||
|
||||
open suspend fun updateFeed(feed: Feed) {}
|
||||
open suspend fun updateFeed(feed: Feed) = database.newFeedDao().updateFeedFields(feed.id, feed.name!!, feed.url!!, feed.folderId!!)
|
||||
|
||||
open suspend fun deleteFeed(feed: Feed) {}
|
||||
open suspend fun deleteFeed(feed: Feed) = database.newFeedDao().delete(feed)
|
||||
|
||||
open suspend fun addFolder(folder: Folder) {}
|
||||
open suspend fun addFolder(folder: Folder) = database.newFolderDao().insert(folder)
|
||||
|
||||
open suspend fun deleteFolder(folder: Folder) {}
|
||||
open suspend fun deleteFolder(folder: Folder) = database.newFolderDao().delete(folder)
|
||||
|
||||
open suspend fun setItemReadState(item: Item) {
|
||||
database.newItemDao().updateReadState(item.id, item.isRead)
|
||||
|
@ -0,0 +1,74 @@
|
||||
package com.readrops.app.compose.util.components
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.Card
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.painter.Painter
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.window.Dialog
|
||||
import com.readrops.app.compose.util.theme.LargeSpacer
|
||||
import com.readrops.app.compose.util.theme.MediumSpacer
|
||||
import com.readrops.app.compose.util.theme.spacing
|
||||
|
||||
@Composable
|
||||
fun BaseDialog(
|
||||
title: String,
|
||||
icon: Painter,
|
||||
onDismiss: () -> Unit,
|
||||
onValidate: () -> Unit,
|
||||
content: @Composable () -> Unit
|
||||
) {
|
||||
Dialog(
|
||||
onDismissRequest = onDismiss
|
||||
) {
|
||||
Card(
|
||||
shape = RoundedCornerShape(16.dp)
|
||||
) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.Center,
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.background(MaterialTheme.colorScheme.background)
|
||||
.padding(MaterialTheme.spacing.largeSpacing)
|
||||
) {
|
||||
Icon(
|
||||
painter = icon,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(MaterialTheme.spacing.largeSpacing)
|
||||
)
|
||||
|
||||
MediumSpacer()
|
||||
|
||||
Text(
|
||||
text = title,
|
||||
style = MaterialTheme.typography.headlineSmall
|
||||
)
|
||||
|
||||
MediumSpacer()
|
||||
|
||||
content()
|
||||
|
||||
LargeSpacer()
|
||||
|
||||
TextButton(
|
||||
onClick = { onValidate() },
|
||||
) {
|
||||
Text(text = "Validate")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
5
appcompose/src/main/res/drawable/ic_new_folder.xml
Normal file
5
appcompose/src/main/res/drawable/ic_new_folder.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FF000000" android:pathData="M20,6h-8l-2,-2L4,4c-1.11,0 -1.99,0.89 -1.99,2L2,18c0,1.11 0.89,2 2,2h16c1.11,0 2,-0.89 2,-2L22,8c0,-1.11 -0.89,-2 -2,-2zM19,14h-3v3h-2v-3h-3v-2h3L14,9h2v3h3v2z"/>
|
||||
</vector>
|
@ -25,4 +25,7 @@ abstract class NewFeedDao : NewBaseDao<Feed> {
|
||||
"Where Feed.folder_id is Null And Item.read = 0 And Feed.account_id = :accountId Group by Feed.id")
|
||||
abstract fun selectFeedsWithoutFolder(accountId: Int): Flow<List<FeedWithCount>>
|
||||
|
||||
@Query("Update Feed set name = :feedName, url = :feedUrl, folder_id = :folderId Where id = :feedId")
|
||||
abstract fun updateFeedFields(feedId: Int, feedName: String, feedUrl: String, folderId: Int)
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user