Skip to content

Commit

Permalink
Merge branch 'main' into context_menu
Browse files Browse the repository at this point in the history
  • Loading branch information
JunkFood02 committed Mar 8, 2024
2 parents 50faa47 + 6b29a81 commit dcf0b01
Show file tree
Hide file tree
Showing 13 changed files with 263 additions and 28 deletions.
3 changes: 2 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28" />
<queries>
<intent>
<action android:name="android.intent.action.MAIN" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,12 @@ abstract class AbstractRssRepository(
supervisorScope {
coroutineWorker.setProgress(SyncWorker.setIsSyncing(true))
val preTime = System.currentTimeMillis()
val preDate = Date(preTime)
val accountId = context.currentAccountId
feedDao.queryAll(accountId)
.chunked(16)
.forEach {
it.map { feed -> async { syncFeed(feed) } }
it.map { feed -> async { syncFeed(feed, preDate) } }
.awaitAll()
.forEach {
if (it.feed.isNotification) {
Expand Down Expand Up @@ -173,9 +174,9 @@ abstract class AbstractRssRepository(
articleDao.markAsStarredByArticleId(accountId, articleId, isStarred)
}

private suspend fun syncFeed(feed: Feed): FeedWithArticle {
private suspend fun syncFeed(feed: Feed, preDate: Date = Date()): FeedWithArticle {
val latest = articleDao.queryLatestByFeedId(context.currentAccountId, feed.id)
val articles = rssHelper.queryRssXml(feed, latest?.link)
val articles = rssHelper.queryRssXml(feed, latest?.link, preDate)
if (feed.icon == null) {
val iconLink = rssHelper.queryRssIconLink(feed.url)
if (iconLink != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import me.ash.reader.infrastructure.rss.provider.fever.FeverDTO
import me.ash.reader.ui.ext.currentAccountId
import me.ash.reader.ui.ext.decodeHTML
import me.ash.reader.ui.ext.dollarLast
import me.ash.reader.ui.ext.isFuture
import me.ash.reader.ui.ext.showToast
import me.ash.reader.ui.ext.spacerDollar
import java.util.Date
Expand Down Expand Up @@ -140,6 +141,7 @@ class FeverRssService @Inject constructor(

try {
val preTime = System.currentTimeMillis()
val preDate = Date(preTime)
val accountId = context.currentAccountId
val account = accountDao.queryById(accountId)!!
val feverAPI = getFeverAPI()
Expand Down Expand Up @@ -196,7 +198,10 @@ class FeverRssService @Inject constructor(
*itemsBody.items?.map {
Article(
id = accountId.spacerDollar(it.id!!),
date = it.created_on_time?.run { Date(this * 1000) } ?: Date(),
date = it.created_on_time
?.run { Date(this * 1000) }
?.takeIf { !it.isFuture(preDate) }
?: preDate,
title = it.title.decodeHTML() ?: context.getString(R.string.empty),
author = it.author,
rawDescription = it.html ?: "",
Expand All @@ -209,7 +214,7 @@ class FeverRssService @Inject constructor(
accountId = accountId,
isUnread = (it.is_read ?: 0) <= 0,
isStarred = (it.is_saved ?: 0) > 0,
updateAt = Date(),
updateAt = preDate,
).also {
sinceId = it.id.dollarLast()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import me.ash.reader.infrastructure.rss.provider.greader.GoogleReaderDTO
import me.ash.reader.ui.ext.currentAccountId
import me.ash.reader.ui.ext.decodeHTML
import me.ash.reader.ui.ext.dollarLast
import me.ash.reader.ui.ext.isFuture
import me.ash.reader.ui.ext.showToast
import me.ash.reader.ui.ext.spacerDollar
import java.util.Calendar
Expand Down Expand Up @@ -405,7 +406,10 @@ class GoogleReaderRssService @Inject constructor(
val articleId = it.id!!.ofItemStreamIdToId()
Article(
id = accountId.spacerDollar(articleId),
date = it.published?.run { Date(this * 1000) } ?: preDate,
date = it.published
?.run { Date(this * 1000) }
?.takeIf { !it.isFuture(preDate) }
?: preDate,
title = it.title.decodeHTML() ?: context.getString(R.string.empty),
author = it.author,
rawDescription = it.summary?.content ?: "",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import me.ash.reader.infrastructure.di.IODispatcher
import me.ash.reader.infrastructure.net.NetworkDataSource
import me.ash.reader.infrastructure.rss.OPMLDataSource
import me.ash.reader.infrastructure.rss.RssHelper
import me.ash.reader.infrastructure.storage.AndroidImageDownloader
import me.ash.reader.ui.ext.del
import me.ash.reader.ui.ext.getLatestApk
import me.ash.reader.ui.ext.isGitHub
Expand Down Expand Up @@ -92,6 +93,9 @@ class AndroidApp : Application(), Configuration.Provider {
@Inject
lateinit var imageLoader: ImageLoader

@Inject
lateinit var imageDownloader: AndroidImageDownloader

/**
* When the application startup.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import me.ash.reader.infrastructure.di.IODispatcher
import me.ash.reader.infrastructure.html.Readability
import me.ash.reader.ui.ext.currentAccountId
import me.ash.reader.ui.ext.decodeHTML
import me.ash.reader.ui.ext.isFuture
import me.ash.reader.ui.ext.spacerDollar
import okhttp3.OkHttpClient
import okhttp3.Request
Expand Down Expand Up @@ -67,6 +68,7 @@ class RssHelper @Inject constructor(
suspend fun queryRssXml(
feed: Feed,
latestLink: String?,
preDate: Date = Date(),
): List<Article> =
try {
val accountId = context.currentAccountId
Expand All @@ -76,7 +78,7 @@ class RssHelper @Inject constructor(
.entries
.asSequence()
.takeWhile { latestLink == null || latestLink != it.link }
.map { buildArticleFromSyndEntry(feed, accountId, it) }
.map { buildArticleFromSyndEntry(feed, accountId, it, preDate) }
.toList()
}
} catch (e: Exception) {
Expand All @@ -89,6 +91,7 @@ class RssHelper @Inject constructor(
feed: Feed,
accountId: Int,
syndEntry: SyndEntry,
preDate: Date = Date(),
): Article {
val desc = syndEntry.description?.value
val content = syndEntry.contents
Expand All @@ -108,15 +111,15 @@ class RssHelper @Inject constructor(
id = accountId.spacerDollar(UUID.randomUUID().toString()),
accountId = accountId,
feedId = feed.id,
date = syndEntry.publishedDate ?: syndEntry.updatedDate ?: Date(),
date = (syndEntry.publishedDate ?: syndEntry.updatedDate).takeIf { !it.isFuture(preDate) } ?: preDate,
title = syndEntry.title.decodeHTML() ?: feed.name,
author = syndEntry.author,
rawDescription = (content ?: desc) ?: "",
shortDescription = Readability.parseToText(desc ?: content, syndEntry.link).take(110),
fullContent = content,
img = findImg((content ?: desc) ?: ""),
link = syndEntry.link ?: "",
updateAt = Date(),
updateAt = preDate,
)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package me.ash.reader.infrastructure.storage

import android.content.Context
import android.media.MediaScannerConnection
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.provider.MediaStore
import android.webkit.URLUtil
import androidx.annotation.CheckResult
import androidx.annotation.DeprecatedSinceApi
import androidx.core.content.contentValuesOf
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.withContext
import me.ash.reader.R
import me.ash.reader.infrastructure.di.IODispatcher
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import java.io.FileOutputStream
import java.io.IOException
import javax.inject.Inject
import kotlin.io.path.Path
import kotlin.io.path.createFile
import kotlin.io.path.createParentDirectories

private const val TAG = "AndroidImageDownloader"

class AndroidImageDownloader @Inject constructor(
@ApplicationContext private val context: Context,
@IODispatcher private val ioDispatcher: CoroutineDispatcher,
private val okHttpClient: OkHttpClient,
) {
@CheckResult
suspend fun downloadImage(imageUrl: String): Result<Uri> {
return withContext(ioDispatcher) {
Request.Builder().url(imageUrl).build().runCatching {
okHttpClient.newCall(this).execute().run {

val fileName = URLUtil.guessFileName(
imageUrl, header("Content-Disposition"), body.contentType()?.toString()
)

val relativePath =
Environment.DIRECTORY_PICTURES + "/" + context.getString(R.string.read_you)

val resolver = context.contentResolver

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val imageCollection =
MediaStore.Images.Media.getContentUri(
MediaStore.VOLUME_EXTERNAL_PRIMARY
)


val imageDetails = contentValuesOf(
MediaStore.Images.Media.DISPLAY_NAME to fileName,
MediaStore.Images.Media.RELATIVE_PATH to relativePath,
MediaStore.Images.Media.IS_PENDING to 1
)

val imageUri = resolver.insert(imageCollection, imageDetails)
?: return@withContext Result.failure(IOException("Cannot create image"))

resolver.openFileDescriptor(imageUri, "w", null).use { pfd ->
body.byteStream().use {
it.copyTo(
FileOutputStream(
pfd?.fileDescriptor ?: return@withContext Result.failure(
IOException("Null fd")
)
)
)
}
}
imageDetails.run {
clear()
put(MediaStore.Images.Media.IS_PENDING, 0)
resolver.update(imageUri, this, null, null)
}
imageUri
} else {
saveImageForAndroidP(
fileName,
Environment.getExternalStoragePublicDirectory(relativePath).path
)
}
}
}
}

}

@DeprecatedSinceApi(29)
private fun Response.saveImageForAndroidP(
fileName: String,
imageDirectory: String,
): Uri {
val file = Path(imageDirectory, fileName).createParentDirectories().createFile().toFile()

body.byteStream().use {
it.copyTo(file.outputStream())
}

var contentUri: Uri = Uri.fromFile(file)

MediaScannerConnection.scanFile(context, arrayOf(file.path), null) { _, uri ->
contentUri = uri
}

return contentUri
}
}
2 changes: 2 additions & 0 deletions app/src/main/java/me/ash/reader/ui/ext/DateExt.kt
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,5 @@ private fun String.parseToDate(
}
return null
}

fun Date.isFuture(staticDate: Date = Date()): Boolean = this.time > staticDate.time
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ fun LazyListScope.ArticleList(
onShare: ((ArticleWithFeed) -> Unit)? = null,
) {
for (index in 0 until pagingItems.itemCount) {
when (val item = pagingItems.peek(index)) {
when (val item = pagingItems[index]) {
is ArticleFlowItem.Article -> {
item(key = item.articleWithFeed.article.id) {
SwipeableArticleItem(
Expand Down
Loading

0 comments on commit dcf0b01

Please sign in to comment.