diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/LoginActivity.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/LoginActivity.kt index ac9ed95..fc6e981 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/LoginActivity.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/LoginActivity.kt @@ -11,6 +11,7 @@ import android.view.MenuItem import android.view.View import android.view.inputmethod.EditorInfo import android.widget.TextView +import android.widget.Toast import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatDelegate @@ -40,15 +41,16 @@ class LoginActivity : AppCompatActivity(), DIAware { private lateinit var binding: ActivityLoginBinding override val di by closestDI() - private val repository : Repository by instance() - private val appSettingsService : AppSettingsService by instance() - private val tracker : Tracker by instance() + private val repository: Repository by instance() + private val appSettingsService: AppSettingsService by instance() + private val tracker: Tracker by instance() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - TrackHelper.track().download().identifier(DownloadTracker.Extra.ApkChecksum(applicationContext)) + TrackHelper.track().download() + .identifier(DownloadTracker.Extra.ApkChecksum(applicationContext)) .with(tracker) TrackHelper.track().screen("/login").with(tracker) @@ -64,7 +66,30 @@ class LoginActivity : AppCompatActivity(), DIAware { handleBaseUrlFail() if (appSettingsService.getBaseUrl().isNotEmpty()) { - goToMain() + showProgress(true) + // This should be reverted when "old" users connected with a non-selfoss rss + // are handled. Revert to "simple" way. + CoroutineScope(Dispatchers.Main).launch { + try { + val (errorFetching, displaySelfossOnly) = repository.shouldBeSelfossInstance() + if (!errorFetching && !displaySelfossOnly) { + goToMain() + } else { + showProgress(false) + if (displaySelfossOnly) { + Toast.makeText( + applicationContext, + R.string.application_selfoss_only, + Toast.LENGTH_LONG + ).show() + } + repository.logout() + } + } catch (e: Throwable) { + repository.logout() + showProgress(false) + } + } } handleActions() @@ -191,17 +216,27 @@ class LoginActivity : AppCompatActivity(), DIAware { repository.refreshLoginInformation(url, login, password) - CoroutineScope(Dispatchers.IO).launch { + CoroutineScope(Dispatchers.Main).launch { val result = repository.login() if (result) { - goToMain() - } else { - CoroutineScope(Dispatchers.Main).launch { + val (errorFetching, displaySelfossOnly) = repository.shouldBeSelfossInstance() + if (!errorFetching && !displaySelfossOnly) { + goToMain() + } else { + if (displaySelfossOnly) { + Toast.makeText( + applicationContext, + R.string.application_selfoss_only, + Toast.LENGTH_LONG + ).show() + } preferenceError() } + } else { + preferenceError() } + showProgress(false) } - showProgress(false) } } @@ -215,11 +250,11 @@ class LoginActivity : AppCompatActivity(), DIAware { .alpha( if (show) 0F else 1F ).setListener(object : AnimatorListenerAdapter() { - override fun onAnimationEnd(animation: Animator) { - binding.loginForm.visibility = if (show) View.GONE else View.VISIBLE + override fun onAnimationEnd(animation: Animator) { + binding.loginForm.visibility = if (show) View.GONE else View.VISIBLE + } } - } - ) + ) binding.loginProgress.visibility = if (show) View.VISIBLE else View.GONE binding.loginProgress @@ -228,11 +263,11 @@ class LoginActivity : AppCompatActivity(), DIAware { .alpha( if (show) 1F else 0F ).setListener(object : AnimatorListenerAdapter() { - override fun onAnimationEnd(animation: Animator) { - binding.loginProgress.visibility = if (show) View.VISIBLE else View.GONE + override fun onAnimationEnd(animation: Animator) { + binding.loginProgress.visibility = if (show) View.VISIBLE else View.GONE + } } - } - ) + ) } override fun onCreateOptionsMenu(menu: Menu): Boolean { diff --git a/androidApp/src/main/res/values-ca-rES/strings.xml b/androidApp/src/main/res/values-ca-rES/strings.xml index 856b886..2724d0e 100644 --- a/androidApp/src/main/res/values-ca-rES/strings.xml +++ b/androidApp/src/main/res/values-ca-rES/strings.xml @@ -126,4 +126,5 @@ A crash occured. Sending the details to the developper. "Disable automatic bug reporting. " Filters + This app only works with a Selfoss instance, and no other RSS feed. diff --git a/androidApp/src/main/res/values-de-rDE/strings.xml b/androidApp/src/main/res/values-de-rDE/strings.xml index 4b2662a..b385cbf 100644 --- a/androidApp/src/main/res/values-de-rDE/strings.xml +++ b/androidApp/src/main/res/values-de-rDE/strings.xml @@ -126,4 +126,5 @@ A crash occured. Sending the details to the developper. "Disable automatic bug reporting. " Filters + This app only works with a Selfoss instance, and no other RSS feed. diff --git a/androidApp/src/main/res/values-es-rES/strings.xml b/androidApp/src/main/res/values-es-rES/strings.xml index 7e2ec50..06c9790 100644 --- a/androidApp/src/main/res/values-es-rES/strings.xml +++ b/androidApp/src/main/res/values-es-rES/strings.xml @@ -126,4 +126,5 @@ A crash occured. Sending the details to the developper. "Disable automatic bug reporting. " Filters + This app only works with a Selfoss instance, and no other RSS feed. diff --git a/androidApp/src/main/res/values-fa-rIR/strings.xml b/androidApp/src/main/res/values-fa-rIR/strings.xml index 7ef5c9a..c592459 100644 --- a/androidApp/src/main/res/values-fa-rIR/strings.xml +++ b/androidApp/src/main/res/values-fa-rIR/strings.xml @@ -126,4 +126,5 @@ A crash occured. Sending the details to the developper. "Disable automatic bug reporting. " Filters + This app only works with a Selfoss instance, and no other RSS feed. diff --git a/androidApp/src/main/res/values-fr-rFR/strings.xml b/androidApp/src/main/res/values-fr-rFR/strings.xml index cb97594..d343ecb 100644 --- a/androidApp/src/main/res/values-fr-rFR/strings.xml +++ b/androidApp/src/main/res/values-fr-rFR/strings.xml @@ -126,4 +126,5 @@ A crash occured. Sending the details to the developper. "Disable automatic bug reporting. " Filters + This app only works with a Selfoss instance, and no other RSS feed. diff --git a/androidApp/src/main/res/values-gl-rES/strings.xml b/androidApp/src/main/res/values-gl-rES/strings.xml index e762ae5..78ded15 100644 --- a/androidApp/src/main/res/values-gl-rES/strings.xml +++ b/androidApp/src/main/res/values-gl-rES/strings.xml @@ -126,4 +126,5 @@ A crash occured. Sending the details to the developper. "Disable automatic bug reporting. " Filters + This app only works with a Selfoss instance, and no other RSS feed. diff --git a/androidApp/src/main/res/values-in-rID/strings.xml b/androidApp/src/main/res/values-in-rID/strings.xml index 903ed34..a02a294 100644 --- a/androidApp/src/main/res/values-in-rID/strings.xml +++ b/androidApp/src/main/res/values-in-rID/strings.xml @@ -126,4 +126,5 @@ A crash occured. Sending the details to the developper. "Disable automatic bug reporting. " Filters + This app only works with a Selfoss instance, and no other RSS feed. diff --git a/androidApp/src/main/res/values-it-rIT/strings.xml b/androidApp/src/main/res/values-it-rIT/strings.xml index 2ba3b43..217080a 100644 --- a/androidApp/src/main/res/values-it-rIT/strings.xml +++ b/androidApp/src/main/res/values-it-rIT/strings.xml @@ -126,4 +126,5 @@ A crash occured. Sending the details to the developper. "Disable automatic bug reporting. " Filters + This app only works with a Selfoss instance, and no other RSS feed. diff --git a/androidApp/src/main/res/values-ko-rKR/strings.xml b/androidApp/src/main/res/values-ko-rKR/strings.xml index bc748b9..854d980 100644 --- a/androidApp/src/main/res/values-ko-rKR/strings.xml +++ b/androidApp/src/main/res/values-ko-rKR/strings.xml @@ -126,4 +126,5 @@ A crash occured. Sending the details to the developper. "Disable automatic bug reporting. " Filters + This app only works with a Selfoss instance, and no other RSS feed. diff --git a/androidApp/src/main/res/values-night/strings.xml b/androidApp/src/main/res/values-night/strings.xml index 3208ea8..bf5530d 100644 --- a/androidApp/src/main/res/values-night/strings.xml +++ b/androidApp/src/main/res/values-night/strings.xml @@ -6,4 +6,5 @@ A crash occured. Sending the details to the developper. "Disable automatic bug reporting. " Filters + This app only works with a Selfoss instance, and no other RSS feed. \ No newline at end of file diff --git a/androidApp/src/main/res/values-nl-rNL/strings.xml b/androidApp/src/main/res/values-nl-rNL/strings.xml index 261c68f..ca23e14 100644 --- a/androidApp/src/main/res/values-nl-rNL/strings.xml +++ b/androidApp/src/main/res/values-nl-rNL/strings.xml @@ -126,4 +126,5 @@ A crash occured. Sending the details to the developper. "Disable automatic bug reporting. " Filters + This app only works with a Selfoss instance, and no other RSS feed. diff --git a/androidApp/src/main/res/values-pt-rBR/strings.xml b/androidApp/src/main/res/values-pt-rBR/strings.xml index b83d58a..9d94cda 100644 --- a/androidApp/src/main/res/values-pt-rBR/strings.xml +++ b/androidApp/src/main/res/values-pt-rBR/strings.xml @@ -126,4 +126,5 @@ A crash occured. Sending the details to the developper. "Disable automatic bug reporting. " Filters + This app only works with a Selfoss instance, and no other RSS feed. diff --git a/androidApp/src/main/res/values-pt-rPT/strings.xml b/androidApp/src/main/res/values-pt-rPT/strings.xml index 7a0b892..f57a215 100644 --- a/androidApp/src/main/res/values-pt-rPT/strings.xml +++ b/androidApp/src/main/res/values-pt-rPT/strings.xml @@ -126,4 +126,5 @@ A crash occured. Sending the details to the developper. "Disable automatic bug reporting. " Filters + This app only works with a Selfoss instance, and no other RSS feed. diff --git a/androidApp/src/main/res/values-si-rLK/strings.xml b/androidApp/src/main/res/values-si-rLK/strings.xml index beb7aa3..74ed3dd 100644 --- a/androidApp/src/main/res/values-si-rLK/strings.xml +++ b/androidApp/src/main/res/values-si-rLK/strings.xml @@ -126,4 +126,5 @@ A crash occured. Sending the details to the developper. "Disable automatic bug reporting. " Filters + This app only works with a Selfoss instance, and no other RSS feed. diff --git a/androidApp/src/main/res/values-tr-rTR/strings.xml b/androidApp/src/main/res/values-tr-rTR/strings.xml index 3dd3f12..588e206 100644 --- a/androidApp/src/main/res/values-tr-rTR/strings.xml +++ b/androidApp/src/main/res/values-tr-rTR/strings.xml @@ -126,4 +126,5 @@ A crash occured. Sending the details to the developper. "Disable automatic bug reporting. " Filters + This app only works with a Selfoss instance, and no other RSS feed. diff --git a/androidApp/src/main/res/values-zh-rCN/strings.xml b/androidApp/src/main/res/values-zh-rCN/strings.xml index 810a201..b2bbe80 100644 --- a/androidApp/src/main/res/values-zh-rCN/strings.xml +++ b/androidApp/src/main/res/values-zh-rCN/strings.xml @@ -126,4 +126,5 @@ 发生崩溃。请将细节发送给开发人员。 "禁用自动错误报告 " 筛选器 + This app only works with a Selfoss instance, and no other RSS feed. diff --git a/androidApp/src/main/res/values-zh-rTW/strings.xml b/androidApp/src/main/res/values-zh-rTW/strings.xml index 9e9e751..0457e1b 100644 --- a/androidApp/src/main/res/values-zh-rTW/strings.xml +++ b/androidApp/src/main/res/values-zh-rTW/strings.xml @@ -126,4 +126,5 @@ A crash occured. Sending the details to the developper. "Disable automatic bug reporting. " Filters + This app only works with a Selfoss instance, and no other RSS feed. diff --git a/androidApp/src/main/res/values/strings.xml b/androidApp/src/main/res/values/strings.xml index e53facf..dfc256d 100644 --- a/androidApp/src/main/res/values/strings.xml +++ b/androidApp/src/main/res/values/strings.xml @@ -129,4 +129,5 @@ A crash occured. Sending the details to the developper. "Disable automatic bug reporting. " Filters + This app only works with a Selfoss instance, and no other RSS feed. diff --git a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/repository/RepositoryImpl.kt b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/repository/RepositoryImpl.kt index 48ab99f..c93d68b 100644 --- a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/repository/RepositoryImpl.kt +++ b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/repository/RepositoryImpl.kt @@ -8,13 +8,19 @@ import bou.amine.apps.readerforselfossv2.rest.SelfossApi import bou.amine.apps.readerforselfossv2.service.AppSettingsService import bou.amine.apps.readerforselfossv2.utils.* import io.github.aakira.napier.Napier +import io.ktor.client.call.* import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.launch -class Repository(private val api: SelfossApi, private val appSettingsService: AppSettingsService, val isConnectionAvailable: MutableStateFlow, private val db: ReaderForSelfossDB) { +class Repository( + private val api: SelfossApi, + private val appSettingsService: AppSettingsService, + val isConnectionAvailable: MutableStateFlow, + private val db: ReaderForSelfossDB +) { var items = ArrayList() var connectionMonitored = false @@ -146,7 +152,8 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap } suspend fun getTags(): List { - val isDatabaseEnabled = appSettingsService.isItemCachingEnabled() || !appSettingsService.isUpdateSourcesEnabled() + val isDatabaseEnabled = + appSettingsService.isItemCachingEnabled() || !appSettingsService.isUpdateSourcesEnabled() return if (isNetworkAvailable() && !fetchedTags) { val apiTags = api.tags() if (apiTags.success && apiTags.data != null && isDatabaseEnabled) { @@ -178,7 +185,8 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap } suspend fun getSources(): ArrayList { - val isDatabaseEnabled = appSettingsService.isItemCachingEnabled() || !appSettingsService.isUpdateSourcesEnabled() + val isDatabaseEnabled = + appSettingsService.isItemCachingEnabled() || !appSettingsService.isUpdateSourcesEnabled() return if (isNetworkAvailable() && !fetchedSources) { val apiSources = api.sources() if (apiSources.success && apiSources.data != null && isDatabaseEnabled) { @@ -380,18 +388,35 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap return result } + suspend fun shouldBeSelfossInstance(): Pair { + var fetchFailed = true + var showSelfossOnlyModal = false + if (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 + fetchFailed = !api.getItemsWithoutCatch().success + } catch (e: NoTransformationFoundException) { + showSelfossOnlyModal = true + } catch (e: Throwable) { + Napier.e(e.stackTraceToString(), tag = "RepositoryImpl.shouldBeSelfossInstance") + } + } + + return Pair(fetchFailed, showSelfossOnlyModal) + } + suspend fun logout() { if (isNetworkAvailable()) { try { val response = api.logout() - if (response.isSuccess) { + if (!response.isSuccess) { Napier.e("Couldn't logout.", tag = "RepositoryImpl.logout") } } catch (cause: Throwable) { Napier.e(cause.stackTraceToString(), tag = "RepositoryImpl.logout") - } finally { - appSettingsService.clearAll() } + appSettingsService.clearAll() } else { appSettingsService.clearAll() } @@ -456,11 +481,29 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap private fun getDBItems(): List = db.itemsQueries.items().executeAsList() - private fun insertDBAction(articleid: String, read: Boolean = false, unread: Boolean = false, starred: Boolean = false, unstarred: Boolean = false) = + private fun insertDBAction( + articleid: String, + read: Boolean = false, + unread: Boolean = false, + starred: Boolean = false, + unstarred: Boolean = false + ) = db.actionsQueries.insertAction(articleid, read, unread, starred, unstarred) private fun updateDBItem(item: SelfossModel.Item) = - db.itemsQueries.updateItem(item.datetime, item.title.getHtmlDecoded(), item.content, item.unread, item.starred, item.thumbnail, item.icon, item.link, item.sourcetitle, item.tags.joinToString(","), item.id.toString()) + db.itemsQueries.updateItem( + item.datetime, + item.title.getHtmlDecoded(), + item.content, + item.unread, + item.starred, + item.thumbnail, + item.icon, + item.link, + item.sourcetitle, + item.tags.joinToString(","), + item.id.toString() + ) suspend fun tryToCacheItemsAndGetNewOnes(): List { try { diff --git a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/rest/SelfossApi.kt b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/rest/SelfossApi.kt index bba630c..c94d01e 100644 --- a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/rest/SelfossApi.kt +++ b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/rest/SelfossApi.kt @@ -47,7 +47,7 @@ class SelfossApi(private val appSettingsService: AppSettingsService) { } install(HttpCookies) install(HttpRequestRetry) { - maxRetries = 2 + maxRetries = 1 retryIf { _, response -> response.status == HttpStatusCode.Forbidden && shouldHavePostLogin() && hasLoginInfo() } @@ -134,6 +134,16 @@ class SelfossApi(private val appSettingsService: AppSettingsService) { parameter("offset", offset) }) + suspend fun getItemsWithoutCatch(): StatusAndData> = + bodyOrFailure(client.get(url("/items")) { + if (!shouldHavePostLogin()) { + parameter("username", appSettingsService.getUserName()) + parameter("password", appSettingsService.getPassword()) + } + parameter("type", "all") + parameter("items", 1) + }) + suspend fun stats(): StatusAndData = bodyOrFailure(client.tryToGet(url("/stats")) { if (!shouldHavePostLogin()) {