Initial UI for adding new feed

This commit is contained in:
Shinokuni 2023-07-22 15:22:43 +02:00
parent f7d1eea3ec
commit da496cd91a
6 changed files with 142 additions and 10 deletions

View File

@ -1,10 +1,21 @@
package com.readrops.app.compose
import com.readrops.app.compose.feeds.FeedsViewModel
import com.readrops.app.compose.repositories.BaseRepository
import com.readrops.app.compose.repositories.LocalRSSRepository
import com.readrops.app.compose.timelime.TimelineViewModel
import com.readrops.db.entities.account.Account
import com.readrops.db.entities.account.AccountType
import org.koin.androidx.viewmodel.dsl.viewModel
import org.koin.dsl.module
val composeAppModule = module {
viewModel { TimelineViewModel(get()) }
viewModel { FeedsViewModel(get()) }
// repositories
single<BaseRepository> { LocalRSSRepository(get(), get(), Account(id = 1, isCurrentAccount = true, accountType = AccountType.LOCAL)) }
}

View File

@ -0,0 +1,59 @@
package com.readrops.app.compose.feeds
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
@Composable
fun AddFeedDialog(
onDismiss: () -> Unit,
onValidate: (String) -> Unit,
) {
var url by remember { mutableStateOf("") }
Dialog(
onDismissRequest = onDismiss
) {
Column(
modifier = Modifier
.background(MaterialTheme.colorScheme.background)
.padding(16.dp)
) {
Text(
text = "Add new feed",
style = MaterialTheme.typography.headlineSmall
)
Spacer(modifier = Modifier.size(8.dp))
TextField(
value = url,
onValueChange = { url = it }
)
Spacer(modifier = Modifier.size(8.dp))
Button(
onClick = { onValidate(url) },
modifier = Modifier.align(Alignment.CenterHorizontally)
) {
Text(text = "Validate")
}
}
}
}

View File

@ -1,18 +1,55 @@
package com.readrops.app.compose.feeds
import androidx.compose.foundation.layout.Column
import androidx.compose.material3.Text
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.Icon
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import cafe.adriel.voyager.androidx.AndroidScreen
import org.koin.androidx.compose.getViewModel
class FeedsScreen : AndroidScreen() {
@Composable
override fun Content() {
Column {
Text(
text = "Feeds"
val viewModel = getViewModel<FeedsViewModel>()
var showDialog by remember { mutableStateOf(false) }
if (showDialog) {
AddFeedDialog(
onDismiss = { showDialog = false },
onValidate = {
showDialog = false
viewModel.insertFeed(it)
}
)
}
Box(
modifier = Modifier.fillMaxSize()
) {
FloatingActionButton(
modifier = Modifier
.align(Alignment.BottomEnd)
.padding(16.dp),
onClick = { showDialog = true }
) {
Icon(
imageVector = Icons.Default.Add,
contentDescription = null
)
}
}
}
}

View File

@ -0,0 +1,18 @@
package com.readrops.app.compose.feeds
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.readrops.app.compose.repositories.BaseRepository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
class FeedsViewModel(
private val repository: BaseRepository,
) : ViewModel() {
fun insertFeed(url: String) {
viewModelScope.launch(context = Dispatchers.IO) {
repository.insertNewFeeds(listOf(url))
}
}
}

View File

@ -38,7 +38,7 @@ abstract class ARepository(
*/
abstract suspend fun synchronize(): SyncResult
abstract suspend fun insertNewFeeds()
abstract suspend fun insertNewFeeds(urls: List<String>)
}
abstract class BaseRepository(

View File

@ -48,8 +48,15 @@ class LocalRSSRepository(
override suspend fun synchronize(): SyncResult = throw NotImplementedError("This method can't be called here")
override suspend fun insertNewFeeds() {
/*TODO("Not yet implemented")*/
override suspend fun insertNewFeeds(urls: List<String>) {
for (url in urls) {
try {
val result = dataSource.queryRSSResource(url, null)!!
insertFeed(result.first)
} catch (e: Exception) {
throw e
}
}
}
private suspend fun insertNewItems(items: List<Item>, feed: Feed) {
@ -77,8 +84,8 @@ class LocalRSSRepository(
}
private suspend fun insertFeed(feed: Feed): Feed {
if (database.newFeedDao().feedExists(feed.url!!, account.id)) {
throw IllegalStateException("Feed already exists for account ${account.accountName}")
require(!database.newFeedDao().feedExists(feed.url!!, account.id)) {
"Feed already exists for account ${account.accountName}"
}
return feed.apply {