Skip to content

Commit 341310e

Browse files
committed
Added ability to force add a feed despite network errors
1 parent 9c0a130 commit 341310e

File tree

8 files changed

+73
-33
lines changed

8 files changed

+73
-33
lines changed

app/src/main/java/com/nononsenseapps/feeder/FeederApplication.kt

+20-3
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import com.nononsenseapps.feeder.util.FilePathProvider
3737
import com.nononsenseapps.feeder.util.ToastMaker
3838
import com.nononsenseapps.feeder.util.currentlyUnmetered
3939
import com.nononsenseapps.feeder.util.filePathProvider
40+
import com.nononsenseapps.feeder.util.logDebug
4041
import com.nononsenseapps.jsonfeed.cachingHttpClient
4142
import java.io.File
4243
import java.security.Security
@@ -104,9 +105,25 @@ class FeederApplication : Application(), DIAware, ImageLoaderFactory {
104105
val filePathProvider = instance<FilePathProvider>()
105106
cachingHttpClient(
106107
cacheDirectory = (filePathProvider.httpCacheDir),
107-
).newBuilder()
108-
.addNetworkInterceptor(UserAgentInterceptor)
109-
.build()
108+
) {
109+
addNetworkInterceptor(UserAgentInterceptor)
110+
if (BuildConfig.DEBUG) {
111+
addInterceptor { chain ->
112+
val request = chain.request()
113+
logDebug(
114+
"FEEDER",
115+
"Request ${request.url} headers [${request.headers}]",
116+
)
117+
118+
chain.proceed(request).also {
119+
logDebug(
120+
"FEEDER",
121+
"Response ${it.request.url} code ${it.networkResponse?.code} cached ${it.cacheResponse != null}",
122+
)
123+
}
124+
}
125+
}
126+
}
110127
}
111128
bind<ImageLoader>() with singleton {
112129
val filePathProvider = instance<FilePathProvider>()

app/src/main/java/com/nononsenseapps/feeder/archmodel/Repository.kt

-2
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,6 @@ class Repository(override val di: DI) : DIAware {
257257
filter = feedListFilter,
258258
)
259259
}.flatMapLatest {
260-
logDebug("JONAS", "DAMP $it")
261260
feedItemStore.getPagedFeedItemsRaw(
262261
feedId = it.feedId,
263262
tag = it.tag,
@@ -285,7 +284,6 @@ class Repository(override val di: DI) : DIAware {
285284
filter = feedListFilter,
286285
)
287286
}.flatMapLatest {
288-
logDebug("JONAS", "Fump $it")
289287
feedItemStore.getFeedItemCountRaw(
290288
feedId = it.feedId,
291289
tag = it.tag,

app/src/main/java/com/nononsenseapps/feeder/model/FeedParser.kt

+16-14
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ class FeedParser(override val di: DI) : DIAware {
272272
}
273273
}
274274

275-
internal fun parseRssAtom(
275+
private fun parseRssAtom(
276276
url: URL,
277277
responseBody: ResponseBody,
278278
): Either<FeedParserError, Feed> {
@@ -344,22 +344,24 @@ class FeedParser(override val di: DI) : DIAware {
344344

345345
class FeedParsingError(val url: URL, e: Throwable) : Exception(e.message, e)
346346

347-
suspend fun OkHttpClient.getResponse(url: URL, forceNetwork: Boolean = false): Response {
347+
suspend fun OkHttpClient.getResponse(
348+
url: URL,
349+
forceNetwork: Boolean = false,
350+
): Response {
348351
val request = Request.Builder()
349352
.url(url)
350-
.cacheControl(
351-
CacheControl.Builder()
352-
.run {
353-
if (forceNetwork) {
353+
.run {
354+
if (forceNetwork) {
355+
cacheControl(
356+
CacheControl.Builder()
354357
// Force cache-revalidation
355-
maxAge(0, TimeUnit.SECONDS)
356-
} else {
357-
// Will accept anything generated in the last X
358-
maxAge(10, TimeUnit.MINUTES)
359-
}
360-
}
361-
.build(),
362-
)
358+
.maxAge(0, TimeUnit.SECONDS)
359+
.build(),
360+
)
361+
} else {
362+
this
363+
}
364+
}
363365
.build()
364366

365367
@Suppress("BlockingMethodInNonBlockingContext")

app/src/main/java/com/nononsenseapps/feeder/model/Networking.kt app/src/main/java/com/nononsenseapps/feeder/model/UserAgentInterceptor.kt

+2-1
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,5 @@ object UserAgentInterceptor : Interceptor {
2121
// const val USER_AGENT_STRING = "Mozilla/5.0 (Linux; Android 10) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.5195.136 Mobile Safari/537.36"
2222
// After email discussion with BleepingComputer.com where Feeder got blocked because they thought it was scraper of some kind
2323
// const val USER_AGENT_STRING = "Mjukisbyxor / ${BuildConfig.VERSION_NAME}(${BuildConfig.VERSION_CODE})"
24-
const val USER_AGENT_STRING = "SpaceCowboys Android RSS Reader / ${BuildConfig.VERSION_NAME}(${BuildConfig.VERSION_CODE})"
24+
const val USER_AGENT_STRING =
25+
"SpaceCowboys Android RSS Reader / ${BuildConfig.VERSION_NAME}(${BuildConfig.VERSION_CODE})"

app/src/main/java/com/nononsenseapps/feeder/ui/compose/searchfeed/SearchFeedScreen.kt

+14-1
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,16 @@ fun ColumnScope.rightContent(
410410
title = title,
411411
description = error.description,
412412
url = error.url,
413-
)
413+
) {
414+
onClick(
415+
SearchResult(
416+
title = error.url,
417+
url = error.url,
418+
description = "",
419+
feedImage = "",
420+
),
421+
)
422+
}
414423
}
415424
}
416425
for (result in results.item) {
@@ -489,6 +498,7 @@ fun ErrorResultView(
489498
description: String,
490499
url: String,
491500
modifier: Modifier = Modifier,
501+
onAddAnyway: () -> Unit,
492502
) {
493503
val dimens = LocalDimens.current
494504

@@ -518,6 +528,9 @@ fun ErrorResultView(
518528
description,
519529
style = MaterialTheme.typography.bodyMedium,
520530
)
531+
OutlinedButton(onClick = onAddAnyway) {
532+
Text(stringResource(id = R.string.add_anyway))
533+
}
521534
}
522535
}
523536
}

app/src/main/java/com/nononsenseapps/jsonfeed/JsonFeedParser.kt

+18-11
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ fun cachingHttpClient(
1616
cacheSize: Long = 10L * 1024L * 1024L,
1717
trustAllCerts: Boolean = true,
1818
connectTimeoutSecs: Long = 30L,
19-
readTimeoutSecs: Long = 30L
19+
readTimeoutSecs: Long = 30L,
20+
block: (OkHttpClient.Builder.() -> Unit)? = null,
2021
): OkHttpClient {
2122
val builder: OkHttpClient.Builder = OkHttpClient.Builder()
2223

@@ -33,6 +34,10 @@ fun cachingHttpClient(
3334
builder.trustAllCerts()
3435
}
3536

37+
block?.let {
38+
builder.block()
39+
}
40+
3641
return builder.build()
3742
}
3843

@@ -45,24 +50,24 @@ fun feedAdapter(): JsonAdapter<Feed> =
4550
*/
4651
class JsonFeedParser(
4752
private val httpClient: OkHttpClient,
48-
private val jsonFeedAdapter: JsonAdapter<Feed>
53+
private val jsonFeedAdapter: JsonAdapter<Feed>,
4954
) {
5055

5156
constructor(
5257
cacheDirectory: File? = null,
5358
cacheSize: Long = 10L * 1024L * 1024L,
5459
trustAllCerts: Boolean = true,
5560
connectTimeoutSecs: Long = 5L,
56-
readTimeoutSecs: Long = 5L
61+
readTimeoutSecs: Long = 5L,
5762
) : this(
5863
cachingHttpClient(
5964
cacheDirectory = cacheDirectory,
6065
cacheSize = cacheSize,
6166
trustAllCerts = trustAllCerts,
6267
connectTimeoutSecs = connectTimeoutSecs,
63-
readTimeoutSecs = readTimeoutSecs
68+
readTimeoutSecs = readTimeoutSecs,
6469
),
65-
feedAdapter()
70+
feedAdapter(),
6671
)
6772

6873
/**
@@ -77,7 +82,7 @@ class JsonFeedParser(
7782
} catch (error: Throwable) {
7883
throw IllegalArgumentException(
7984
"Bad URL. Perhaps it is missing an http:// prefix?",
80-
error
85+
error,
8186
)
8287
}
8388

@@ -95,11 +100,13 @@ class JsonFeedParser(
95100
contentType.subtype.contains("json") -> {
96101
parseJson(body)
97102
}
103+
98104
else -> {
99105
throw IOException("Incorrect subtype: ${contentType.type}/${contentType.subtype}")
100106
}
101107
}
102108
}
109+
103110
else -> {
104111
throw IOException("Incorrect type: ${contentType?.type}/${contentType?.subtype}")
105112
}
@@ -133,13 +140,13 @@ data class Feed(
133140
val author: Author? = null,
134141
val expired: Boolean? = null,
135142
val hubs: List<Hub>? = null,
136-
val items: List<Item>?
143+
val items: List<Item>?,
137144
)
138145

139146
data class Author(
140147
val name: String? = null,
141148
val url: String? = null,
142-
val avatar: String? = null
149+
val avatar: String? = null,
143150
)
144151

145152
data class Item(
@@ -156,18 +163,18 @@ data class Item(
156163
val date_modified: String? = null,
157164
val author: Author? = null,
158165
val tags: List<String>? = null,
159-
val attachments: List<Attachment>? = null
166+
val attachments: List<Attachment>? = null,
160167
)
161168

162169
data class Attachment(
163170
val url: String?,
164171
val mime_type: String? = null,
165172
val title: String? = null,
166173
val size_in_bytes: Long? = null,
167-
val duration_in_seconds: Long? = null
174+
val duration_in_seconds: Long? = null,
168175
)
169176

170177
data class Hub(
171178
val type: String?,
172-
val url: String?
179+
val url: String?,
173180
)

app/src/main/res/values-sv/strings.xml

+2-1
Original file line numberDiff line numberDiff line change
@@ -227,4 +227,5 @@
227227
<string name="failed_to_parse_full_article">Kund inte läsa hela artikeln</string>
228228
<string name="no_url">Ingen URL</string>
229229
<string name="theme_e_ink">Läsplatta</string>
230-
</resources>
230+
<string name="add_anyway">Lägg till ändå</string>
231+
</resources>

app/src/main/res/values/strings.xml

+1
Original file line numberDiff line numberDiff line change
@@ -240,4 +240,5 @@
240240
<string name="unsupported_content_type">Unsupported content type</string>
241241
<string name="failed_to_parse_full_article">Failed to parse full article</string>
242242
<string name="no_url">No URL</string>
243+
<string name="add_anyway">Add anyway</string>
243244
</resources>

0 commit comments

Comments
 (0)