From da496cd91a0208ffe3c2efc69e395d224429e275 Mon Sep 17 00:00:00 2001 From: Shinokuni Date: Sat, 22 Jul 2023 15:22:43 +0200 Subject: [PATCH] Initial UI for adding new feed --- .../readrops/app/compose/ComposeAppModule.kt | 11 ++++ .../app/compose/feeds/AddFeedDialog.kt | 59 +++++++++++++++++++ .../readrops/app/compose/feeds/FeedsScreen.kt | 47 +++++++++++++-- .../app/compose/feeds/FeedsViewModel.kt | 18 ++++++ .../app/compose/repositories/ARepository.kt | 2 +- .../repositories/LocalRSSRepository.kt | 15 +++-- 6 files changed, 142 insertions(+), 10 deletions(-) create mode 100644 appcompose/src/main/java/com/readrops/app/compose/feeds/AddFeedDialog.kt create mode 100644 appcompose/src/main/java/com/readrops/app/compose/feeds/FeedsViewModel.kt diff --git a/appcompose/src/main/java/com/readrops/app/compose/ComposeAppModule.kt b/appcompose/src/main/java/com/readrops/app/compose/ComposeAppModule.kt index b919ee49..e7042738 100644 --- a/appcompose/src/main/java/com/readrops/app/compose/ComposeAppModule.kt +++ b/appcompose/src/main/java/com/readrops/app/compose/ComposeAppModule.kt @@ -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 { LocalRSSRepository(get(), get(), Account(id = 1, isCurrentAccount = true, accountType = AccountType.LOCAL)) } } \ No newline at end of file diff --git a/appcompose/src/main/java/com/readrops/app/compose/feeds/AddFeedDialog.kt b/appcompose/src/main/java/com/readrops/app/compose/feeds/AddFeedDialog.kt new file mode 100644 index 00000000..d1bf7b85 --- /dev/null +++ b/appcompose/src/main/java/com/readrops/app/compose/feeds/AddFeedDialog.kt @@ -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") + } + } + } +} \ No newline at end of file diff --git a/appcompose/src/main/java/com/readrops/app/compose/feeds/FeedsScreen.kt b/appcompose/src/main/java/com/readrops/app/compose/feeds/FeedsScreen.kt index d0f463fd..48a7ba2d 100644 --- a/appcompose/src/main/java/com/readrops/app/compose/feeds/FeedsScreen.kt +++ b/appcompose/src/main/java/com/readrops/app/compose/feeds/FeedsScreen.kt @@ -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() + 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 + ) + } + } + } } \ No newline at end of file diff --git a/appcompose/src/main/java/com/readrops/app/compose/feeds/FeedsViewModel.kt b/appcompose/src/main/java/com/readrops/app/compose/feeds/FeedsViewModel.kt new file mode 100644 index 00000000..6f626a68 --- /dev/null +++ b/appcompose/src/main/java/com/readrops/app/compose/feeds/FeedsViewModel.kt @@ -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)) + } + } +} \ No newline at end of file diff --git a/appcompose/src/main/java/com/readrops/app/compose/repositories/ARepository.kt b/appcompose/src/main/java/com/readrops/app/compose/repositories/ARepository.kt index a4f40ba8..46efa7fa 100644 --- a/appcompose/src/main/java/com/readrops/app/compose/repositories/ARepository.kt +++ b/appcompose/src/main/java/com/readrops/app/compose/repositories/ARepository.kt @@ -38,7 +38,7 @@ abstract class ARepository( */ abstract suspend fun synchronize(): SyncResult - abstract suspend fun insertNewFeeds() + abstract suspend fun insertNewFeeds(urls: List) } abstract class BaseRepository( diff --git a/appcompose/src/main/java/com/readrops/app/compose/repositories/LocalRSSRepository.kt b/appcompose/src/main/java/com/readrops/app/compose/repositories/LocalRSSRepository.kt index 21fd9438..de0824c4 100644 --- a/appcompose/src/main/java/com/readrops/app/compose/repositories/LocalRSSRepository.kt +++ b/appcompose/src/main/java/com/readrops/app/compose/repositories/LocalRSSRepository.kt @@ -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) { + 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, 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 {