Compare commits

...

10 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
ceba58e98f Merge pull request 'Fix alignment changes resetting reader article position' (#190) from davidoskky/ReaderForSelfoss-multiplatform:alignment into master
Reviewed-on: Louvorg/ReaderForSelfoss-multiplatform#190
2025-03-16 13:14:44 +00:00
c3ee07dd85 Refactor star icon handling
Extracted all favorite handling to two functions. Makes it a little bit more readable.
2025-03-12 16:07:49 +01:00
93d99192b3 Don't restart activity changing alignment
When changing alignment in the reader we were restarting the reader activity to reload. Doing this led to reloading the article which was initially opened every time you changed alignment. Now, when changing the alignment we retain all existing fragments but command all of them to update their alignment setting.
2025-03-12 16:07:49 +01:00
359dec2ca0 Changelog for v125030711 2025-03-12 11:39:57 +00:00
62354ec70a Merge pull request 'fix: initial status loading issues.' (#192) from connectivity into master
Reviewed-on: Louvorg/ReaderForSelfoss-multiplatform#192
2025-03-12 11:20:14 +00:00
18a17251ac chore: check changes for translations and android. 2025-03-11 22:20:07 +01:00
5e91724ee2 fix: initial status loading issues. 2025-03-11 22:04:42 +01:00
14 changed files with 270 additions and 148 deletions

View File

@@ -10,30 +10,44 @@ jobs:
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: "Check android app changes"
id: check-android-changes
uses: tj-actions/changed-files@v45
with:
files: |
androidApp/src/**
- name: Fetch tags
if: steps.check-android-changes.outputs.any_modified == 'true'
run: git fetch --tags -p
- uses: actions/setup-java@v4
if: steps.check-android-changes.outputs.any_modified == 'true'
with:
distribution: 'temurin'
java-version: '17'
cache: gradle
- uses: gradle/actions/setup-gradle@v3
if: steps.check-android-changes.outputs.any_modified == 'true'
- uses: android-actions/setup-android@v3
if: steps.check-android-changes.outputs.any_modified == 'true'
- name: Configure gradle...
if: steps.check-android-changes.outputs.any_modified == 'true'
run: mkdir -p ~/.gradle && echo "org.gradle.daemon=false\nignoreGitVersion=true" >> ~/.gradle/gradle.properties
- name: Build and test
if: steps.check-android-changes.outputs.any_modified == 'true'
run: ./gradlew build -x testReleaseUnitTest -x testDebugUnitTest -x testGithubConfigReleaseUnitTest -x testGithubConfigDebugUnitTest # These tests will be done
- uses: KengoTODA/actions-setup-docker-compose@v1
with:
version: "2.23.3"
# TESTS ARE RUN LOCALLY
# TESTS ARE RUN LOCALLY
# - uses: KengoTODA/actions-setup-docker-compose@v1
# with:
# version: "2.23.3"
# - name: run selfoss
# run: |
# docker compose -f .gitea/workflows/assets/docker-compose.yml up -d
- name: coverage
if: steps.check-android-changes.outputs.any_modified == 'true'
run: |
./gradlew :koverHtmlReport
- uses: actions/upload-artifact@v3
if: steps.check-android-changes.outputs.any_modified == 'true'
with:
name: coverage
path: build/reports/kover/html

View File

@@ -29,7 +29,16 @@ jobs:
steps:
- name: Check out repository code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: "Check translations changes"
id: check-translations-changes
uses: tj-actions/changed-files@v45
with:
files: |
androidApp/src/main/res/values/strings.xml
- name: upload translation sources
if: steps.check-api-changes.outputs.any_modified == 'true'
uses: crowdin/github-action@v2
with:
config: './.gitea/workflows/assets/crowdin.yml'
@@ -42,8 +51,10 @@ jobs:
CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}
- name: wait
if: steps.check-api-changes.outputs.any_modified == 'true'
run: sleep 10s
- name: download translations
if: steps.check-api-changes.outputs.any_modified == 'true'
uses: crowdin/github-action@v2
with:
config: './.gitea/workflows/assets/crowdin.yml'
@@ -56,17 +67,18 @@ jobs:
CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}
- name: Check for uncommitted changes
if: steps.check-api-changes.outputs.any_modified == 'true'
id: check-changes
uses: mskri/check-uncommitted-changes-action@v1.0.1
- name: Commit Changes
if: steps.check-changes.outputs.changes != ''
if: steps.check-api-changes.outputs.any_modified == 'true' && steps.check-changes.outputs.changes != ''
run: |
git config --global user.email aminecmi+giteadrone@pm.me
git config --global user.name giteadrone
git add ./androidApp/src/main/res/*
git commit -m "translation: translation files"
- name: Push changes
if: steps.check-changes.outputs.changes != ''
if: steps.check-api-changes.outputs.any_modified == 'true' && steps.check-changes.outputs.changes != ''
uses: appleboy/git-push-action@v1.0.0
with:
author_name: giteadrone

View File

@@ -1,3 +1,14 @@
**v125030711
- Merge pull request 'fix: initial status loading issues.' (#192) from connectivity into master
- chore: check changes for translations and android.
- fix: initial status loading issues.
- Merge pull request 'chore: new connectivity dep. Closes #84.' (#189) from connectivity into master
- chore: new connectivity dep. Closes #84.
- Changelog for v125030681
--------------------------------------------------------------------
**v125030681
- chore: do not send reports on simulators.

View File

@@ -37,22 +37,6 @@ class ReaderActivity :
private val repository: Repository by instance()
private val appSettingsService: AppSettingsService by instance()
private fun showMenuItem(willAddToFavorite: Boolean) {
if (willAddToFavorite) {
toolbarMenu.findItem(R.id.star).icon?.setTint(Color.WHITE)
} else {
toolbarMenu.findItem(R.id.star).icon?.setTint(Color.RED)
}
}
private fun canFavorite() {
showMenuItem(true)
}
private fun canRemoveFromFavorite() {
showMenuItem(false)
}
@Suppress("detekt:SwallowedException")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -73,14 +57,21 @@ class ReaderActivity :
finish()
}
try {
readItem(allItems[currentItem])
} catch (e: IndexOutOfBoundsException) {
finish()
}
readItem()
binding.pager.adapter = ScreenSlidePagerAdapter(this)
binding.pager.setCurrentItem(currentItem, false)
binding.pager.registerOnPageChangeCallback(
object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
super.onPageSelected(position)
currentItem = position
updateStarIcon()
readItem()
}
},
)
}
override fun onResume() {
@@ -89,14 +80,20 @@ class ReaderActivity :
binding.indicator.setViewPager(binding.pager)
}
private fun readItem(item: SelfossModel.Item) {
if (appSettingsService.isMarkOnScrollEnabled() && !appSettingsService.getPublicAccess()) {
private fun readItem() {
val item = allItems.getOrNull(currentItem)
if (appSettingsService.isMarkOnScrollEnabled() && !appSettingsService.getPublicAccess() && item != null) {
CoroutineScope(Dispatchers.IO).launch {
repository.markAsRead(item)
}
}
}
private fun updateStarIcon() {
val isStarred = allItems.getOrNull(currentItem)?.starred ?: false
toolbarMenu.findItem(R.id.star)?.icon?.setTint(if (isStarred) Color.RED else Color.WHITE)
}
override fun onSaveInstanceState(oldInstanceState: Bundle) {
super.onSaveInstanceState(oldInstanceState)
oldInstanceState.clear()
@@ -141,8 +138,7 @@ class ReaderActivity :
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
val inflater = menuInflater
inflater.inflate(R.menu.reader_menu, menu)
menuInflater.inflate(R.menu.reader_menu, menu)
toolbarMenu = menu
alignmentMenu()
@@ -150,87 +146,50 @@ class ReaderActivity :
if (appSettingsService.getPublicAccess()) {
menu.removeItem(R.id.star)
} else {
if (allItems.isNotEmpty() && allItems[currentItem].starred) {
canRemoveFromFavorite()
} else {
canFavorite()
}
binding.pager.registerOnPageChangeCallback(
object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
super.onPageSelected(position)
if (!allItems.isNullOrEmpty() && allItems.size >= position) {
if (allItems[position].starred) {
canRemoveFromFavorite()
} else {
canFavorite()
}
readItem(allItems[position])
}
}
},
)
updateStarIcon()
}
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
fun afterSave() {
allItems[binding.pager.currentItem] =
allItems[binding.pager.currentItem].toggleStar()
canRemoveFromFavorite()
}
fun afterUnsave() {
allItems[binding.pager.currentItem] = allItems[binding.pager.currentItem].toggleStar()
canFavorite()
}
when (item.itemId) {
android.R.id.home -> {
onBackPressedDispatcher.onBackPressed()
return true
}
R.id.star -> {
if (allItems[binding.pager.currentItem].starred) {
CoroutineScope(Dispatchers.IO).launch {
repository.unstarr(allItems[binding.pager.currentItem])
}
afterUnsave()
} else {
CoroutineScope(Dispatchers.IO).launch {
repository.starr(allItems[binding.pager.currentItem])
}
afterSave()
}
}
R.id.align_left -> {
switchAlignmentSetting(AppSettingsService.ALIGN_LEFT)
refreshFragment()
}
R.id.align_justify -> {
switchAlignmentSetting(AppSettingsService.JUSTIFY)
refreshFragment()
}
android.R.id.home -> onBackPressedDispatcher.onBackPressed()
R.id.star -> toggleFavorite()
R.id.align_left -> switchAlignmentSetting(AppSettingsService.ALIGN_LEFT)
R.id.align_justify -> switchAlignmentSetting(AppSettingsService.JUSTIFY)
}
return super.onOptionsItemSelected(item)
}
private fun switchAlignmentSetting(allignment: Int) {
appSettingsService.changeAllignment(allignment)
alignmentMenu()
private fun toggleFavorite() {
val item = allItems.getOrNull(currentItem) ?: return
val starred = item.starred
CoroutineScope(Dispatchers.IO).launch {
if (starred) {
repository.unstarr(item)
} else {
repository.starr(item)
}
}
item.toggleStar()
updateStarIcon()
}
private fun refreshFragment() {
finish()
overridePendingTransition(0, 0)
startActivity(intent)
overridePendingTransition(0, 0)
private fun switchAlignmentSetting(alignment: Int) {
appSettingsService.changeAllignment(alignment)
alignmentMenu()
val fragmentManager = supportFragmentManager
val fragments = fragmentManager.fragments
for (fragment in fragments) {
if (fragment is ArticleFragment) {
fragment.refreshAlignment()
}
}
}
}

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

@@ -170,7 +170,7 @@ class ArticleFragment :
private fun handleContent() {
if (contentText.isEmptyOrNullOrNullString()) {
if (connectivityService.isNetworkAvailable() == true && url.isUrlValid()) {
if (connectivityService.isNetworkAvailable() && url.isUrlValid()) {
getContentFromMercury(url!!)
}
} else {
@@ -263,13 +263,15 @@ class ArticleFragment :
)
}
private fun refreshAlignment() {
fun refreshAlignment() {
textAlignment =
when (appSettingsService.getActiveAllignment()) {
1 -> "justify"
2 -> "left"
else -> "justify"
}
htmlToWebview()
}
@Suppress("detekt:SwallowedException")

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
@@ -55,7 +57,7 @@ class RepositoryTest {
private val connectivityService = mockk<ConnectivityService>()
private lateinit var repository: Repository
private fun initializeRepository(isNetworkAvailable: Boolean? = true) {
private fun initializeRepository(isNetworkAvailable: Boolean = true) {
every { connectivityService.isNetworkAvailable() } returns isNetworkAvailable
repository = Repository(api, appSettingsService, connectivityService, db)
@@ -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

@@ -0,0 +1,8 @@
**v125030711**
- Merge pull request 'fix: initial status loading issues.' (#192) from connectivity into master
- chore: check changes for translations and android.
- fix: initial status loading issues.
- Merge pull request 'chore: new connectivity dep. Closes #84.' (#189) from connectivity into master
- chore: new connectivity dep. Closes #84.
- Changelog for v125030681

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

@@ -63,7 +63,7 @@ class Repository(
suspend fun getNewerItems(): ArrayList<SelfossModel.Item> {
var fetchedItems: StatusAndData<List<SelfossModel.Item>> = StatusAndData.error()
if (connectivityService.isNetworkAvailable() == true) {
if (connectivityService.isNetworkAvailable()) {
fetchedItems =
api.getItems(
displayedItems.type,
@@ -102,7 +102,7 @@ class Repository(
suspend fun getOlderItems(): ArrayList<SelfossModel.Item> {
var fetchedItems: StatusAndData<List<SelfossModel.Item>> = StatusAndData.error()
if (connectivityService.isNetworkAvailable() == true) {
if (connectivityService.isNetworkAvailable()) {
val offset = items.size
fetchedItems =
api.getItems(
@@ -122,7 +122,7 @@ class Repository(
}
private suspend fun getMaxItemsForBackground(itemType: ItemType): List<SelfossModel.Item> {
return if (connectivityService.isNetworkAvailable() == true) {
return if (connectivityService.isNetworkAvailable()) {
val items =
api.getItems(
itemType.type,
@@ -146,7 +146,7 @@ class Repository(
@Suppress("detekt:ForbiddenComment")
suspend fun reloadBadges(): Boolean {
var success = false
if (connectivityService.isNetworkAvailable() == true) {
if (connectivityService.isNetworkAvailable()) {
val response = api.stats()
if (response.success && response.data != null) {
_badgeUnread.value = response.data.unread ?: 0
@@ -168,7 +168,7 @@ class Repository(
suspend fun getTags(): List<SelfossModel.Tag> {
val isDatabaseEnabled =
appSettingsService.isItemCachingEnabled() || !appSettingsService.isUpdateSourcesEnabled()
return if (connectivityService.isNetworkAvailable() == true && !fetchedTags) {
return if (connectivityService.isNetworkAvailable() && !fetchedTags) {
val apiTags = api.tags()
if (apiTags.success && apiTags.data != null && isDatabaseEnabled) {
resetDBTagsWithData(apiTags.data)
@@ -185,7 +185,7 @@ class Repository(
}
suspend fun getSpouts(): Map<String, SelfossModel.Spout> =
if (connectivityService.isNetworkAvailable() == true) {
if (connectivityService.isNetworkAvailable()) {
val spouts = api.spouts()
if (spouts.success && spouts.data != null) {
spouts.data
@@ -201,7 +201,7 @@ class Repository(
val isDatabaseEnabled =
appSettingsService.isItemCachingEnabled() || !appSettingsService.isUpdateSourcesEnabled()
val shouldFetch = if (!appSettingsService.isUpdateSourcesEnabled()) !fetchedSources else true
if (shouldFetch && connectivityService.isNetworkAvailable() == true) {
if (shouldFetch && connectivityService.isNetworkAvailable()) {
if (appSettingsService.getPublicAccess()) {
val apiSources = api.sourcesStats()
if (apiSources.success && apiSources.data != null) {
@@ -223,7 +223,7 @@ class Repository(
val isDatabaseEnabled =
appSettingsService.isItemCachingEnabled() || !appSettingsService.isUpdateSourcesEnabled()
val shouldFetch = if (!appSettingsService.isUpdateSourcesEnabled()) !fetchedSources else true
if (shouldFetch && connectivityService.isNetworkAvailable() == true) {
if (shouldFetch && connectivityService.isNetworkAvailable()) {
val apiSources = api.sourcesDetailed()
if (apiSources.success && apiSources.data != null) {
fetchedSources = true
@@ -248,7 +248,7 @@ class Repository(
}
private suspend fun markAsReadById(id: Int): Boolean =
if (connectivityService.isNetworkAvailable() == true) {
if (connectivityService.isNetworkAvailable()) {
api.markAsRead(id.toString()).isSuccess
} else {
insertDBAction(id.toString(), read = true)
@@ -265,7 +265,7 @@ class Repository(
}
private suspend fun unmarkAsReadById(id: Int): Boolean =
if (connectivityService.isNetworkAvailable() == true) {
if (connectivityService.isNetworkAvailable()) {
api.unmarkAsRead(id.toString()).isSuccess
} else {
insertDBAction(id.toString(), unread = true)
@@ -282,7 +282,7 @@ class Repository(
}
private suspend fun starrById(id: Int): Boolean =
if (connectivityService.isNetworkAvailable() == true) {
if (connectivityService.isNetworkAvailable()) {
api.starr(id.toString()).isSuccess
} else {
insertDBAction(id.toString(), starred = true)
@@ -299,7 +299,7 @@ class Repository(
}
private suspend fun unstarrById(id: Int): Boolean =
if (connectivityService.isNetworkAvailable() == true) {
if (connectivityService.isNetworkAvailable()) {
api.unstarr(id.toString()).isSuccess
} else {
insertDBAction(id.toString(), starred = true)
@@ -309,9 +309,7 @@ class Repository(
suspend fun markAllAsRead(items: ArrayList<SelfossModel.Item>): Boolean {
var success = false
if (connectivityService.isNetworkAvailable() != null &&
connectivityService.isNetworkAvailable()!! &&
api.markAllAsRead(items.map { it.id.toString() }).isSuccess
if (connectivityService.isNetworkAvailable() && api.markAllAsRead(items.map { it.id.toString() }).isSuccess
) {
success = true
for (item in items) {
@@ -370,15 +368,17 @@ class Repository(
url: String,
spout: String,
tags: String,
filter: String,
): Boolean {
var response = false
if (connectivityService.isNetworkAvailable() == true) {
if (connectivityService.isNetworkAvailable()) {
response = api
.createSourceForVersion(
title,
url,
spout,
tags,
filter,
).isSuccess == true
}
@@ -391,10 +391,11 @@ class Repository(
url: String,
spout: String,
tags: String,
filter: String,
): Boolean {
var response = false
if (connectivityService.isNetworkAvailable() == true) {
response = api.updateSourceForVersion(id, title, url, spout, tags).isSuccess == true
if (connectivityService.isNetworkAvailable()) {
response = api.updateSourceForVersion(id, title, url, spout, tags, filter).isSuccess == true
}
return response
@@ -405,13 +406,13 @@ class Repository(
title: String,
): Boolean {
var success = false
if (connectivityService.isNetworkAvailable() == true) {
if (connectivityService.isNetworkAvailable()) {
val response = api.deleteSource(id)
success = response.isSuccess
}
// We filter on success or if the network isn't available
if (success || !(connectivityService.isNetworkAvailable() == true)) {
if (success || !connectivityService.isNetworkAvailable()) {
items = ArrayList(items.filter { it.sourcetitle != title })
setReaderItems(items)
db.itemsQueries.deleteItemsWhereSource(title)
@@ -421,7 +422,7 @@ class Repository(
}
suspend fun updateRemote(): Boolean =
if (connectivityService.isNetworkAvailable() == true) {
if (connectivityService.isNetworkAvailable()) {
api.update().data.equals("finished")
} else {
false
@@ -429,7 +430,7 @@ class Repository(
suspend fun login(): Boolean {
var result = false
if (connectivityService.isNetworkAvailable() == true) {
if (connectivityService.isNetworkAvailable()) {
try {
val response = api.login()
result = response.isSuccess == true
@@ -442,7 +443,7 @@ class Repository(
suspend fun checkIfFetchFails(): Boolean {
var fetchFailed = true
if (connectivityService.isNetworkAvailable() == true) {
if (connectivityService.isNetworkAvailable()) {
try {
// Trying to fetch one item, and check someone is trying to use the app with
// a random rss feed, that would throw a NoTransformationFoundException
@@ -456,7 +457,7 @@ class Repository(
}
suspend fun logout() {
if (connectivityService.isNetworkAvailable() == true) {
if (connectivityService.isNetworkAvailable()) {
try {
val response = api.logout()
if (!response.isSuccess) {
@@ -484,7 +485,7 @@ class Repository(
suspend fun updateApiInformation() {
val apiMajorVersion = appSettingsService.getApiVersion()
if (connectivityService.isNetworkAvailable() == true) {
if (connectivityService.isNetworkAvailable()) {
val fetchedInformation = api.apiInformation()
if (fetchedInformation.success && fetchedInformation.data != null) {
if (fetchedInformation.data.getApiMajorVersion() != apiMajorVersion) {

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

View File

@@ -10,7 +10,7 @@ import kotlinx.coroutines.launch
class ConnectivityService {
private val _networkAvailableProvider = MutableSharedFlow<Boolean>()
val networkAvailableProvider = _networkAvailableProvider.asSharedFlow()
private var currentStatus: Boolean? = null
private var currentStatus = true
private lateinit var connectivity: Connectivity
fun start() {
@@ -20,23 +20,27 @@ class ConnectivityService {
connectivity.statusUpdates.collect { status ->
when (status) {
is Connectivity.Status.Connected -> {
currentStatus = true
_networkAvailableProvider.emit(true)
if (!currentStatus) {
currentStatus = true
_networkAvailableProvider.emit(true)
}
}
is Connectivity.Status.Disconnected -> {
currentStatus = false
_networkAvailableProvider.emit(false)
if (currentStatus) {
currentStatus = false
_networkAvailableProvider.emit(false)
}
}
}
}
}
}
fun isNetworkAvailable(): Boolean? = currentStatus
fun isNetworkAvailable(): Boolean = currentStatus
fun stop() {
currentStatus = null
currentStatus = true
connectivity.stop()
}
}