Compare commits

..

2 Commits

Author SHA1 Message Date
4a55bc0f1d Refactor star icon handling
Some checks failed
Check PR code / Lint (pull_request) Successful in 2m50s
Check PR code / translations (pull_request) Failing after 29s
Check PR code / build (pull_request) Successful in 9m27s
Extracted all favorite handling to two functions. Makes it a little bit more readable.
2025-03-11 17:01:45 +01:00
4859b77ac0 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-11 15:56:10 +01:00
8 changed files with 39 additions and 86 deletions

View File

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

View File

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

View File

@ -1,14 +1,3 @@
**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 **v125030681
- chore: do not send reports on simulators. - chore: do not send reports on simulators.

View File

@ -170,7 +170,7 @@ class ArticleFragment :
private fun handleContent() { private fun handleContent() {
if (contentText.isEmptyOrNullOrNullString()) { if (contentText.isEmptyOrNullOrNullString()) {
if (connectivityService.isNetworkAvailable() && url.isUrlValid()) { if (connectivityService.isNetworkAvailable() == true && url.isUrlValid()) {
getContentFromMercury(url!!) getContentFromMercury(url!!)
} }
} else { } else {

View File

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

View File

@ -1,8 +0,0 @@
**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

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

View File

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