Compare commits

...

3 Commits

Author SHA1 Message Date
9e140aefa6 Add filters only with selfoss >= 2.19
Source filters have been implemented in 2014 (commit 849957ca) but there is no reliable way to determine whether the selfoss instance does support source filters.
2025-04-13 20:01:56 +02:00
566930ba84 Fix sourceDetails unit tests 2025-04-13 00:01:46 +02:00
b1259fdc92 Support source filter editing
The API for filter is undocumented on the Selfoss API reference, but does exist. We can now allow users setting and modifying filters inside the application.
2025-04-12 23:58:12 +02:00
7 changed files with 128 additions and 14 deletions

View File

@ -65,6 +65,7 @@ class UpsertSourceActivity :
private fun initFields(items: Map<String, SelfossModel.Spout>) {
binding.nameInput.setText(existingSource!!.title)
binding.tags.setText(existingSource!!.tags?.joinToString(", "))
binding.filter.setText(existingSource!!.filter)
binding.sourceUri.setText(existingSource!!.params?.url)
binding.spoutsSpinner.setSelection(items.keys.indexOf(existingSource!!.spout))
binding.progress.visibility = View.GONE
@ -169,6 +170,7 @@ class UpsertSourceActivity :
url,
mSpoutsValue!!,
binding.tags.text.toString(),
binding.filter.text.toString(),
)
} else {
repository.createSource(
@ -176,6 +178,7 @@ class UpsertSourceActivity :
url,
mSpoutsValue!!,
binding.tags.text.toString(),
binding.filter.text.toString(),
)
}
if (successfullyAddedSource) {

View File

@ -64,15 +64,28 @@
android:id="@+id/tags"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="48dp"
android:layout_marginTop="16dp"
android:autofillHints="false"
android:hint="@string/add_source_hint_tags"
android:inputType="text"
android:minHeight="48dp"
android:textColorHint="?android:textColorPrimary"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/sourceUri" />
<EditText
android:id="@+id/filter"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:autofillHints="false"
android:hint="@string/add_source_hint_filter"
android:inputType="text"
android:minHeight="48dp"
android:textColorHint="?android:textColorPrimary"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tags" />
<Spinner
android:id="@+id/spoutsSpinner"
android:layout_width="match_parent"
@ -80,7 +93,7 @@
android:minHeight="48dp"
android:layout_marginTop="16dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tags" />
app:layout_constraintTop_toBottomOf="@+id/filter" />
<Button
android:id="@+id/saveBtn"

View File

@ -17,6 +17,7 @@
<string name="add_source_hint_tags">"Tag1, Tag2, Tag3"</string>
<string name="add_source_hint_url">"Link"</string>
<string name="add_source_hint_name">"Name"</string>
<string name="add_source_hint_filter">/Filter/</string>
<string name="add_source">"Add a source"</string>
<string name="add_source_save">"Save"</string>
<string name="wrong_infos">"Check your details again."</string>

View File

@ -44,6 +44,8 @@ private const val FEED_URL = "https://test.com/feed"
private const val TAGS = "Test, New"
private const val FILTER = "/filter/"
private const val NUMBER_ARTICLES = 100
private const val NUMBER_UNREAD = 50
private const val NUMBER_STARRED = 20
@ -836,7 +838,7 @@ class RepositoryTest {
@Test
fun create_source() {
coEvery { api.createSourceForVersion(any(), any(), any(), any()) } returns
coEvery { api.createSourceForVersion(any(), any(), any(), any(), any()) } returns
SuccessResponse(true)
initializeRepository()
@ -848,6 +850,7 @@ class RepositoryTest {
FEED_URL,
SPOUT,
TAGS,
FILTER,
)
}
@ -857,6 +860,7 @@ class RepositoryTest {
any(),
any(),
any(),
any(),
)
}
assertSame(true, response)
@ -864,7 +868,7 @@ class RepositoryTest {
@Test
fun create_source_but_response_fails() {
coEvery { api.createSourceForVersion(any(), any(), any(), any()) } returns
coEvery { api.createSourceForVersion(any(), any(), any(), any(), any()) } returns
SuccessResponse(false)
initializeRepository()
@ -876,6 +880,7 @@ class RepositoryTest {
FEED_URL,
SPOUT,
TAGS,
FILTER,
)
}
@ -885,6 +890,7 @@ class RepositoryTest {
any(),
any(),
any(),
any(),
)
}
assertSame(false, response)
@ -892,7 +898,7 @@ class RepositoryTest {
@Test
fun create_source_without_connection() {
coEvery { api.createSourceForVersion(any(), any(), any(), any()) } returns
coEvery { api.createSourceForVersion(any(), any(), any(), any(), any()) } returns
SuccessResponse(true)
initializeRepository(false)
@ -904,6 +910,7 @@ class RepositoryTest {
FEED_URL,
SPOUT,
TAGS,
FILTER,
)
}
@ -913,6 +920,7 @@ class RepositoryTest {
any(),
any(),
any(),
any(),
)
}
assertSame(false, response)

View File

@ -102,6 +102,7 @@ class SelfossModel {
override var error: String? = null,
override var icon: String? = null,
var params: SourceParams? = null,
var filter: String? = null,
) : Source
@Serializable

View File

@ -368,6 +368,7 @@ class Repository(
url: String,
spout: String,
tags: String,
filter: String,
): Boolean {
var response = false
if (connectivityService.isNetworkAvailable()) {
@ -377,6 +378,7 @@ class Repository(
url,
spout,
tags,
filter,
).isSuccess == true
}
@ -389,10 +391,11 @@ class Repository(
url: String,
spout: String,
tags: String,
filter: String,
): Boolean {
var response = false
if (connectivityService.isNetworkAvailable()) {
response = api.updateSourceForVersion(id, title, url, spout, tags).isSuccess == true
response = api.updateSourceForVersion(id, title, url, spout, tags, filter).isSuccess == true
}
return response

View File

@ -638,17 +638,59 @@ class SelfossApi(
url: String,
spout: String,
tags: String,
filter: String,
): SuccessResponse =
maybeResponse(
if (appSettingsService.getApiVersion() > 1) {
createSource("tags[]", title, url, spout, tags)
createSource(title, url, spout, tags, filter)
} else {
createSource("tags", title, url, spout, tags)
createSourceOld(title, url, spout, tags)
},
)
private suspend fun createSource(
tagsParamName: String,
title: String,
url: String,
spout: String,
tags: String,
filter: String,
): HttpResponse? =
client.tryToSubmitForm(
url = url("/source"),
formParameters =
Parameters.build {
if (!shouldHavePostLogin()) {
append("username", appSettingsService.getUserName())
append("password", appSettingsService.getPassword())
}
append("title", title)
append("url", url)
append("spout", spout)
append("filter", filter)
append("tags[]", tags)
},
block = {
if (appSettingsService
.getBasicUserName()
.isNotEmpty() &&
appSettingsService.getBasicPassword().isNotEmpty()
) {
headers {
append(
HttpHeaders.Authorization,
constructBasicAuthValue(
BasicAuthCredentials(
username = appSettingsService.getBasicUserName(),
password = appSettingsService.getBasicPassword(),
),
),
)
}
}
},
)
private suspend fun createSourceOld(
title: String,
url: String,
spout: String,
@ -665,7 +707,7 @@ class SelfossApi(
append("title", title)
append("url", url)
append("spout", spout)
append(tagsParamName, tags)
append("tags", tags)
},
block = {
if (appSettingsService
@ -694,18 +736,61 @@ class SelfossApi(
url: String,
spout: String,
tags: String,
filter: String,
): SuccessResponse =
maybeResponse(
if (appSettingsService.getApiVersion() > 1) {
updateSource(id, "tags[]", title, url, spout, tags)
updateSource(id, title, url, spout, tags, filter)
} else {
updateSource(id, "tags", title, url, spout, tags)
updateSourceOld(id, title, url, spout, tags)
},
)
private suspend fun updateSource(
id: Int,
tagsParamName: String,
title: String,
url: String,
spout: String,
tags: String,
filter: String,
): HttpResponse? =
client.tryToSubmitForm(
url = url("/source/$id"),
formParameters =
Parameters.build {
if (!shouldHavePostLogin()) {
append("username", appSettingsService.getUserName())
append("password", appSettingsService.getPassword())
}
append("title", title)
append("url", url)
append("spout", spout)
append("tags[]", tags)
append("filter", filter)
},
block = {
if (appSettingsService
.getBasicUserName()
.isNotEmpty() &&
appSettingsService.getBasicPassword().isNotEmpty()
) {
headers {
append(
HttpHeaders.Authorization,
constructBasicAuthValue(
BasicAuthCredentials(
username = appSettingsService.getBasicUserName(),
password = appSettingsService.getBasicPassword(),
),
),
)
}
}
},
)
private suspend fun updateSourceOld(
id: Int,
title: String,
url: String,
spout: String,
@ -722,7 +807,7 @@ class SelfossApi(
append("title", title)
append("url", url)
append("spout", spout)
append(tagsParamName, tags)
append("tags", tags)
},
block = {
if (appSettingsService