diff --git a/.idea/misc.xml b/.idea/misc.xml
index 52292e5..c7b43db 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -26,6 +26,10 @@
+
+
+
+
diff --git a/app/src/main/java/eu/toldi/balazs/anotherfeedreader/MainActivity.kt b/app/src/main/java/eu/toldi/balazs/anotherfeedreader/MainActivity.kt
index 20b992d..4630091 100644
--- a/app/src/main/java/eu/toldi/balazs/anotherfeedreader/MainActivity.kt
+++ b/app/src/main/java/eu/toldi/balazs/anotherfeedreader/MainActivity.kt
@@ -29,7 +29,6 @@ import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
-import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import coil.compose.rememberImagePainter
@@ -38,16 +37,10 @@ import com.google.accompanist.swiperefresh.rememberSwipeRefreshState
import eu.toldi.balazs.anotherfeedreader.entities.Article
import eu.toldi.balazs.anotherfeedreader.entities.Feed
import eu.toldi.balazs.anotherfeedreader.entities.FeedGroup
-import eu.toldi.balazs.anotherfeedreader.sqlite.Repo
import eu.toldi.balazs.anotherfeedreader.ui.theme.AnotherFeedReaderTheme
import eu.toldi.balazs.anotherfeedreader.viewmodel.FeedViewModel
-import kotlinx.coroutines.Dispatchers.IO
-import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
-import java.net.URL
-import java.time.LocalDateTime
-import java.time.ZoneOffset
import java.time.format.DateTimeFormatter
import java.time.format.FormatStyle
@@ -104,8 +97,11 @@ class MainActivity : ComponentActivity() {
) {
items(articleList.value.size) { index ->
- val article = articleList.value[index]
- showArticle(article = article)
+ val articleAndFeed = articleList.value[index]
+ articleAndFeed.articles.sortedByDescending { it.pubDate }
+ .forEach {
+ showArticle(articleAndFeed.feed, article = it)
+ }
}
}
}
@@ -150,7 +146,7 @@ class MainActivity : ComponentActivity() {
) {
Text(
- text = if (selectedIndex == 0) "None" else viewModel.feedsState.value.filterIsInstance()[selectedIndex - 1].name.toString(),
+ text = if (selectedIndex == 0) "None" else viewModel.feedsState.value!!.filterIsInstance()[selectedIndex - 1].name.toString(),
modifier = Modifier
.fillMaxWidth()
.clickable(onClick = { expanded = true })
@@ -166,13 +162,14 @@ class MainActivity : ComponentActivity() {
}) {
Text(text = "None")
}
- viewModel.feedsState.value.filterIsInstance()
+
+ viewModel.feedsState.value!!.filterIsInstance()
.forEachIndexed { index, s ->
DropdownMenuItem(onClick = {
selectedIndex = index + 1
expanded = false
}) {
- viewModel.feedsState.value[index].name?.let {
+ viewModel.feedsState.value!![index].name?.let {
Text(text = it)
}
}
@@ -196,12 +193,11 @@ class MainActivity : ComponentActivity() {
onClick = {
try {
val feed = Feed(null,text)
- syncJob = GlobalScope.launch(IO) { feed.updateFeed() }
if (selectedIndex == 0)
viewModel.addFeed(feed)
else {
var counter = 0
- viewModel.feedsState.value.forEachIndexed { index, feedGroup ->
+ viewModel.feedsState.value!!.forEachIndexed { index, feedGroup ->
if (feedGroup is FeedGroup) {
counter++
if (counter == selectedIndex) {
@@ -260,12 +256,23 @@ class MainActivity : ComponentActivity() {
}
@Composable
- fun showArticle(article: Article) {
+ fun showArticle(feed: Feed, article: Article) {
val haptic = LocalHapticFeedback.current
Card(
Modifier
.pointerInput(Unit) {
detectTapGestures(
+ onTap = {
+ WebView.webURL = article.url.toString()
+ WebView.barTitle =
+ feed.name ?: ""
+ startActivity(
+ Intent(
+ baseContext,
+ WebView::class.java
+ )
+ )
+ },
onLongPress = {
val share =
Intent.createChooser(Intent().apply {
@@ -290,20 +297,7 @@ class MainActivity : ComponentActivity() {
top = 2.dp,
bottom = 6.dp,
end = 6.dp
- )
- .clickable {
-
- WebView.webURL = article.url.toString()
- WebView.barTitle =
- article.feed?.name.toString() ?: ""
- startActivity(
- Intent(
- baseContext,
- WebView::class.java
- )
- )
-
- },
+ ),
elevation = 10.dp,
backgroundColor = MaterialTheme.colors.surface,
shape = RoundedCornerShape(10.dp)
@@ -314,8 +308,8 @@ class MainActivity : ComponentActivity() {
horizontalArrangement = Arrangement.Start,
verticalAlignment = Alignment.CenterVertically
) {
- val painter = if (article.feed?.faviconURL != null) {
- rememberImagePainter(article.feed.faviconURL)
+ val painter = if (feed.faviconURL != null) {
+ rememberImagePainter(feed.faviconURL)
} else {
painterResource(id = R.drawable.ic_launcher_background)
}
@@ -337,7 +331,7 @@ class MainActivity : ComponentActivity() {
modifier = Modifier.padding(horizontal = 2.dp)
)
}
- article.feed?.name?.let {
+ feed.name?.let {
Text(
text = (fun(): String {
return if (it.length > 25)
@@ -476,7 +470,7 @@ class MainActivity : ComponentActivity() {
drawerState: DrawerState,
content: @Composable () -> Unit
) {
- val feedList = viewModel.feedsState.value
+ val feedList = viewModel.feedsState?.value ?: emptyList()
ModalDrawer(drawerState = drawerState, drawerContent = {
LazyColumn(modifier = Modifier.fillMaxHeight()) {
item {
@@ -507,7 +501,7 @@ class MainActivity : ComponentActivity() {
}, content = content)
}
-
+/*
@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
@@ -539,7 +533,7 @@ class MainActivity : ComponentActivity() {
}
}
- }
+ }*/
}
\ No newline at end of file
diff --git a/app/src/main/java/eu/toldi/balazs/anotherfeedreader/entities/Article.kt b/app/src/main/java/eu/toldi/balazs/anotherfeedreader/entities/Article.kt
index 0549980..3fedd71 100644
--- a/app/src/main/java/eu/toldi/balazs/anotherfeedreader/entities/Article.kt
+++ b/app/src/main/java/eu/toldi/balazs/anotherfeedreader/entities/Article.kt
@@ -5,8 +5,6 @@ import androidx.room.Entity
import androidx.room.Ignore
import androidx.room.PrimaryKey
import kotlinx.coroutines.Dispatchers.IO
-import kotlinx.coroutines.GlobalScope
-import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import org.jsoup.Jsoup
import org.w3c.dom.Element
@@ -74,7 +72,7 @@ data class Article(
}
- @ColumnInfo(name = "feedId")
+ @ColumnInfo(name = "containingFeedId")
var feedId: Long = 0
companion object {
/**
diff --git a/app/src/main/java/eu/toldi/balazs/anotherfeedreader/entities/Feed.kt b/app/src/main/java/eu/toldi/balazs/anotherfeedreader/entities/Feed.kt
index 06b25c5..bed7775 100644
--- a/app/src/main/java/eu/toldi/balazs/anotherfeedreader/entities/Feed.kt
+++ b/app/src/main/java/eu/toldi/balazs/anotherfeedreader/entities/Feed.kt
@@ -1,23 +1,12 @@
package eu.toldi.balazs.anotherfeedreader.entities
-import android.util.Log
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.Ignore
import androidx.room.PrimaryKey
-import eu.toldi.balazs.anotherfeedreader.MainActivity
-import eu.toldi.balazs.anotherfeedreader.sqlite.Repo
-import kotlinx.coroutines.*
-import kotlinx.coroutines.Dispatchers.IO
-import net.mm2d.touchicon.TouchIconExtractor
-import org.w3c.dom.Document
-import org.w3c.dom.Node
-import org.w3c.dom.NodeList
import java.net.URL
-import javax.xml.parsers.DocumentBuilder
-import javax.xml.parsers.DocumentBuilderFactory
-@Entity
+@Entity(tableName = "feed")
open class Feed
(
@PrimaryKey(autoGenerate = true)
@@ -34,7 +23,7 @@ open class Feed
/**
* A hírcsatorna neve
*/
- @ColumnInfo(name = "title")
+ @ColumnInfo(name = "name")
var name: String? = null
@Ignore
val link = URL(feedURL)
@@ -46,6 +35,7 @@ open class Feed
/**
* A hírcsatornához tartozó cikkek listája
*/
+ @Ignore
open var articleList: List = emptyList()
/**
@@ -64,42 +54,6 @@ open class Feed
return articleList[i]
}
- /**
- * Hírcsatorna frissítése.
- * Lekéri a hírcsatorna elérési útvonalán található összes új cikket és hozzáadja a cikkek listájához.
- *
- */
- open suspend fun updateFeed() {
- val factory: DocumentBuilderFactory = DocumentBuilderFactory.newInstance()
- val builder: DocumentBuilder = factory.newDocumentBuilder()
- var doc: Document = withContext(Dispatchers.IO) {
- try {
- builder.parse(link.toString())
- } catch (e: Exception) {
- Log.e(null, e.stackTraceToString())
- builder.newDocument()
- }
- }
- if (doc.getElementsByTagName("title").length > 0)
- name = doc.getElementsByTagName("title").item(0).getTextContent()
- val items: NodeList = doc.getElementsByTagName("item")
- for (i in 0 until items.length) {
- val article: Node = items.item(i)
- val a = withContext(Dispatchers.IO) {Article.createFromNode(article, this@Feed)}
- addArticle(a)
- }
- articleList.sortedByDescending { it.pubDate }
-
- faviconURL = withContext(Dispatchers.IO) {
- val extractor = TouchIconExtractor()
- val icons = extractor.fromPage("https://" + link.host)
- if (icons.size > 0)
- icons.maxByOrNull { it.inferArea() }?.url
- else null
- }
- Log.e(null, faviconURL.toString())
- }
-
/**
* Megnézi hogy egy magadott cikk megtalálható-e a hírcsatornán
* @param a a keresett cikk
diff --git a/app/src/main/java/eu/toldi/balazs/anotherfeedreader/entities/FeedGroup.kt b/app/src/main/java/eu/toldi/balazs/anotherfeedreader/entities/FeedGroup.kt
index 32ce0bb..743bce3 100644
--- a/app/src/main/java/eu/toldi/balazs/anotherfeedreader/entities/FeedGroup.kt
+++ b/app/src/main/java/eu/toldi/balazs/anotherfeedreader/entities/FeedGroup.kt
@@ -1,6 +1,5 @@
package eu.toldi.balazs.anotherfeedreader.entities
-import java.io.IOException
import java.util.*
@@ -45,24 +44,6 @@ open class FeedGroup(name: String) : Feed(name) {
return false
}
- /**
- * @see Feed.updateFeed
- * @throws IOException
- */
- override suspend fun updateFeed() {
- if (feedList == null) feedList = ArrayList()
- if (articleList == null) articleList = ArrayList()
-
- feedList.forEach { f ->
- f.updateFeed()
- f.articleList.forEach {
- if (!hasAricle(it))
- articleList += it
- }
- }
- articleList = articleList.sortedByDescending { it.pubDate }
- }
-
/**
* @see Feed.getArticleCount
* @return
diff --git a/app/src/main/java/eu/toldi/balazs/anotherfeedreader/repository/FeedRepository.kt b/app/src/main/java/eu/toldi/balazs/anotherfeedreader/repository/FeedRepository.kt
index 3ccd747..e10fbd2 100644
--- a/app/src/main/java/eu/toldi/balazs/anotherfeedreader/repository/FeedRepository.kt
+++ b/app/src/main/java/eu/toldi/balazs/anotherfeedreader/repository/FeedRepository.kt
@@ -1,58 +1,92 @@
package eu.toldi.balazs.anotherfeedreader.repository
+import android.util.Log
+import androidx.compose.runtime.MutableState
+import androidx.compose.runtime.State
+import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.LiveData
import eu.toldi.balazs.anotherfeedreader.entities.Article
import eu.toldi.balazs.anotherfeedreader.entities.Feed
-import eu.toldi.balazs.anotherfeedreader.entities.FeedData
-import eu.toldi.balazs.anotherfeedreader.entities.FeedGroup
-import eu.toldi.balazs.anotherfeedreader.sqlite.ArticleDAO
+import eu.toldi.balazs.anotherfeedreader.sqlite.FeedsAndArticles
+import eu.toldi.balazs.anotherfeedreader.sqlite.FeedsAndArticlesDAO
+import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.withContext
-import java.net.URL
+import net.mm2d.touchicon.TouchIconExtractor
+import org.w3c.dom.Document
+import org.w3c.dom.Node
+import org.w3c.dom.NodeList
+import javax.xml.parsers.DocumentBuilder
+import javax.xml.parsers.DocumentBuilderFactory
-class FeedRepository(private val articleDAO: ArticleDAO) {
+class FeedRepository(private val feedsAndArticleDAO: FeedsAndArticlesDAO) {
- val feedData = FeedData().apply {
- addFeed(FeedGroup("magyar").apply {
- addFeed(Feed(feedURL = "https://hvg.hu/rss"))
- addFeed(Feed(feedURL = "https://telex.hu/rss"))
- addFeed(Feed(feedURL = "https://24.hu/feed"))
- addFeed(Feed(feedURL = "https://444.hu/feed"))
- })
- addFeed(Feed(feedURL = "https://www.theguardian.com/world/rss"))
+
+ private val _isRefereshing: MutableState = mutableStateOf(false)
+
+ public val isRefeshing: State
+ get() = _isRefereshing
+
+ fun getAllArticles(): LiveData> {
+ return feedsAndArticleDAO.getAll()
}
- fun getAllArticles(): LiveData> {
- return articleDAO.getAll()
+ suspend fun instert(feed: Feed, article: Article) {
+ feedsAndArticleDAO.insertArticle(feed, article)
}
- suspend fun instert(article: Article){
- articleDAO.insertAll(article)
- }
- suspend fun delete(article: Article){
- articleDAO.delete(article)
- }
-
- fun getFeedList() : List = feedData.feedList
+ fun getFeedList(): LiveData> = feedsAndArticleDAO.getFeeds()
suspend fun updateFeeds() {
- var done = false
- feedData.limit?.let {
- it.updateFeed()
- done = true
- }
- if (!done)
- feedData.updateFeed()
+ withContext(IO) {
+ try {
+ _isRefereshing.value = true
+ val feeds = feedsAndArticleDAO.getFeedsList()
+ feeds?.forEach { feed ->
+ updateFeed(feed)
+ }
+ _isRefereshing.value = false
+ } catch (e: Exception) {
- feedData.articleList.forEach {
- withContext(IO){
- instert(it)
+ }
+
+ }
+ }
+
+ private suspend fun updateFeed(feed: Feed) {
+ val factory: DocumentBuilderFactory = DocumentBuilderFactory.newInstance()
+ val builder: DocumentBuilder = factory.newDocumentBuilder()
+ var doc: Document = withContext(Dispatchers.IO) {
+ try {
+ builder.parse(feed.link.toString())
+ } catch (e: Exception) {
+ Log.e(null, e.stackTraceToString())
+ builder.newDocument()
}
}
+ if (doc.getElementsByTagName("title").length > 0)
+ feed.name = doc.getElementsByTagName("title").item(0).getTextContent()
+ val items: NodeList = doc.getElementsByTagName("item")
+ for (i in 0 until items.length) {
+ val article: Node = items.item(i)
+ val a = withContext(Dispatchers.IO) { Article.createFromNode(article, feed = feed) }
+ feedsAndArticleDAO.insertArticle(feed, a)
+ }
+
+ feed.faviconURL = withContext(Dispatchers.IO) {
+ val extractor = TouchIconExtractor()
+ val icons = extractor.fromPage("https://" + feed.link.host)
+ if (icons.size > 0)
+ icons.maxByOrNull { it.inferArea() }?.url
+ else null
+ }
+ feedsAndArticleDAO.updateFeed(feed)
}
- fun addFeed(feed: Feed) {
- feedData.addFeed(feed)
+
+ suspend fun addFeed(feed: Feed) {
+ feedsAndArticleDAO.insertFeed(feed)
+ updateFeeds()
}
}
\ No newline at end of file
diff --git a/app/src/main/java/eu/toldi/balazs/anotherfeedreader/sqlite/AppDatabase.kt b/app/src/main/java/eu/toldi/balazs/anotherfeedreader/sqlite/AppDatabase.kt
index 0cd23dc..fed2d73 100644
--- a/app/src/main/java/eu/toldi/balazs/anotherfeedreader/sqlite/AppDatabase.kt
+++ b/app/src/main/java/eu/toldi/balazs/anotherfeedreader/sqlite/AppDatabase.kt
@@ -5,10 +5,12 @@ import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import eu.toldi.balazs.anotherfeedreader.entities.Article
+import eu.toldi.balazs.anotherfeedreader.entities.Feed
-@Database(entities = [Article::class], version = 1)
+@Database(entities = [Article::class, Feed::class], version = 4)
abstract class AppDatabase : RoomDatabase() {
abstract fun articleDao(): ArticleDAO
+ abstract fun feedsAndArticlesDao(): FeedsAndArticlesDAO
companion object {
@Volatile
diff --git a/app/src/main/java/eu/toldi/balazs/anotherfeedreader/sqlite/FeedsAndArticles.kt b/app/src/main/java/eu/toldi/balazs/anotherfeedreader/sqlite/FeedsAndArticles.kt
index 7c2480a..023a45a 100644
--- a/app/src/main/java/eu/toldi/balazs/anotherfeedreader/sqlite/FeedsAndArticles.kt
+++ b/app/src/main/java/eu/toldi/balazs/anotherfeedreader/sqlite/FeedsAndArticles.kt
@@ -9,7 +9,7 @@ data class FeedsAndArticles(
@Embedded val feed: Feed,
@Relation(
parentColumn = "feedId",
- entityColumn = "feedId"
+ entityColumn = "containingFeedId"
)
val articles: List
)
\ No newline at end of file
diff --git a/app/src/main/java/eu/toldi/balazs/anotherfeedreader/sqlite/FeedsAndArticlesDAO.kt b/app/src/main/java/eu/toldi/balazs/anotherfeedreader/sqlite/FeedsAndArticlesDAO.kt
index d9c358f..d798668 100644
--- a/app/src/main/java/eu/toldi/balazs/anotherfeedreader/sqlite/FeedsAndArticlesDAO.kt
+++ b/app/src/main/java/eu/toldi/balazs/anotherfeedreader/sqlite/FeedsAndArticlesDAO.kt
@@ -3,22 +3,35 @@ package eu.toldi.balazs.anotherfeedreader.sqlite
import androidx.lifecycle.LiveData
import androidx.room.*
import eu.toldi.balazs.anotherfeedreader.entities.Article
+import eu.toldi.balazs.anotherfeedreader.entities.Feed
@Dao
interface FeedsAndArticlesDAO {
@Transaction
- @Query("SELECT * FROM feed")
+ @Query("SELECT * FROM feed INNER JOIN article ON feed.feedId = article.containingFeedId ORDER BY article.pubDate")
fun getAll(): LiveData>
- @Query("SELECT * FROM article WHERE articleId IN (:articleIds)")
- fun loadAllByIds(articleIds: IntArray): List
+ @Query("SELECT * FROM feed")
+ fun getFeeds(): LiveData>
- @Query("SELECT * FROM article WHERE url=:url")
- fun findArticleByURL(url: String): Article?
+ @Query("SELECT * FROM feed")
+ fun getFeedsList(): List
+
+
+ fun insertArticle(feed: Feed, article: Article) {
+ feed.feedId?.let { article.feedId = it }
+ _insertArticles(listOf(article))
+ }
@Insert
- fun insertArticles(vararg articles: Article)
+ fun _insertArticles(articles: List)
+
+ @Update
+ fun updateFeed(feed: Feed)
+
+ @Insert
+ fun insertFeed(feed: Feed)
@Delete
fun deleteArticle(article: Article)
diff --git a/app/src/main/java/eu/toldi/balazs/anotherfeedreader/viewmodel/FeedViewModel.kt b/app/src/main/java/eu/toldi/balazs/anotherfeedreader/viewmodel/FeedViewModel.kt
index b098e64..38ba8d5 100644
--- a/app/src/main/java/eu/toldi/balazs/anotherfeedreader/viewmodel/FeedViewModel.kt
+++ b/app/src/main/java/eu/toldi/balazs/anotherfeedreader/viewmodel/FeedViewModel.kt
@@ -1,62 +1,55 @@
package eu.toldi.balazs.anotherfeedreader.viewmodel
import android.app.Application
-import androidx.compose.runtime.MutableState
-import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.State
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
-import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
-import eu.toldi.balazs.anotherfeedreader.entities.Article
import eu.toldi.balazs.anotherfeedreader.entities.Feed
-import eu.toldi.balazs.anotherfeedreader.entities.FeedData
-import eu.toldi.balazs.anotherfeedreader.entities.FeedGroup
import eu.toldi.balazs.anotherfeedreader.repository.FeedRepository
import eu.toldi.balazs.anotherfeedreader.sqlite.AppDatabase
+import eu.toldi.balazs.anotherfeedreader.sqlite.FeedsAndArticles
+import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
-import java.net.URL
class FeedViewModel(application: Application) : AndroidViewModel(application) {
private val feedRepo: FeedRepository
- val articles: LiveData>
- val feedsState = mutableStateOf(emptyList())
- val isRefereshing: MutableState = mutableStateOf(false)
+ val articles: LiveData>
+ val feedsState: LiveData>
+ val isRefereshing: State
init {
- val articleDAO = AppDatabase.getInstance(application).articleDao()
- feedRepo = FeedRepository(articleDAO = articleDAO)
+ val feedsAndArticlesDao = AppDatabase.getInstance(application).feedsAndArticlesDao()
+ feedRepo = FeedRepository(feedsAndArticleDAO = feedsAndArticlesDao)
articles = feedRepo.getAllArticles()
- viewModelScope.launch {
- feedsState.value = feedRepo.getFeedList()
- }
+ feedsState = feedRepo.getFeedList()
+ isRefereshing = feedRepo.isRefeshing
}
fun updateFeeds(): Job {
- return viewModelScope.launch {
- isRefereshing.value = true
+ return viewModelScope.launch(IO) {
feedRepo.updateFeeds()
- isRefereshing.value = false
}
}
fun changeFeed() {
viewModelScope.launch {
- isRefereshing.value = true
- ///articles.value = feedRepo.getFeedList()
- isRefereshing.value = false
}
}
fun changeFeedList() {
viewModelScope.launch {
- feedsState.value = feedRepo.getFeedList()
+ //feedsState.value = feedRepo.getFeedList().value
}
}
- fun addFeed(feed: Feed){
- feedRepo.addFeed(feed)
- feedsState.value = feedRepo.getFeedList()
+ fun addFeed(feed: Feed) {
+ viewModelScope.launch(IO) {
+ feedRepo.addFeed(feed)
+ }
}
+
+
}