Compare commits

..

No commits in common. "366b2e10f15554da7320a4630bf7552637fe86bb" and "ef994460c1cb5d22ff37d2cba300351c2444c69a" have entirely different histories.

24 changed files with 164 additions and 349 deletions

View File

@ -1,118 +1,26 @@
kind: pipeline kind: pipeline
type: docker type: docker
name: test name: android
steps: steps:
- name: AnylyseBuildTest - name: code-analysis
image: mingc/android-build-box:latest image: mingc/android-build-box:latest
failure: ignore failure: ignore
commands: commands:
- echo "---------------------------------------------------------" - ls -la
- echo "Analysing..."
- ./gradlew sonarqube -Dsonar.projectKey=RFS2 -Dsonar.host.url=$SONAR_HOST_URL -Dsonar.login=$SONAR_LOGIN -PignoreGitVersion=true -P appLoginUrl="\"URL\"" -P appLoginUsername="\"LOGIN\"" -P appLoginPassword="\"PASS\"" - ./gradlew sonarqube -Dsonar.projectKey=RFS2 -Dsonar.host.url=$SONAR_HOST_URL -Dsonar.login=$SONAR_LOGIN -PignoreGitVersion=true -P appLoginUrl="\"URL\"" -P appLoginUsername="\"LOGIN\"" -P appLoginPassword="\"PASS\""
- echo "---------------------------------------------------------"
- echo "Building..."
- ./gradlew :androidApp:build -PignoreGitVersion=true -P appLoginUrl="\"URL\"" -P appLoginUsername="\"LOGIN\"" -P appLoginPassword="\"PASS\"" -P pushCache=false
- echo "---------------------------------------------------------"
- echo "Testing..."
- echo "---------------------------------------------------------"
- ./gradlew test -PignoreGitVersion=true -P appLoginUrl="\"URL\"" -P appLoginUsername="\"LOGIN\"" -P appLoginPassword="\"PASS\"" -P pushCache=false
environment: environment:
SONAR_HOST_URL: SONAR_HOST_URL:
from_secret: sonarScannerHostUrl from_secret: sonarScannerHostUrl
SONAR_LOGIN: SONAR_LOGIN:
from_secret: sonarScannerLogin from_secret: sonarScannerLogin
trigger:
event:
- push
- pull_request
--- - name: test
kind: pipeline image: mingc/android-build-box:latest
type: docker
name: Publish
steps:
- name: createTag
image: ubuntu:latest
commands: commands:
- apt-get update && apt-get install -y git - ./gradlew test -PignoreGitVersion=true -P appLoginUrl="\"URL\"" -P appLoginUsername="\"LOGIN\"" -P appLoginPassword="\"PASS\"" -P pushCache=false
- ./build.sh --publish --from-ci
- git remote add pushing https://$GITEA_USR:$GITEA_PASS@gitea.amine-louveau.fr/Louvorg/ReaderForSelfoss-multiplatform.git
- git push pushing --tags
environment:
GITEA_USR:
from_secret: giteaUsr
GITEA_PASS:
from_secret: giteaPass
- name: scpFiles
image: appleboy/drone-scp
settings:
host: amine-louveau.fr
username: ubuntu
key:
from_secret: privateKey
port: 22
target: /home/ubuntu/
source: version.txt
- name: deploy
image: appleboy/drone-ssh
settings:
host: amine-louveau.fr
user: ubuntu
key:
from_secret: privateKey
command_timeout: 2m
script:
- cd /home/ubuntu
- sudo rm -rf /var/www/amine/version.txt
- sudo chown www-data:www-data ./version.txt
- sudo mv version.txt /var/www/amine/
trigger:
event:
- promote
target:
- production
---
kind: pipeline
type: docker
name: Release
steps:
- name: build - name: build
image: mingc/android-build-box:latest image: mingc/android-build-box:latest
commands: commands:
- echo "Generate APK" - ./gradlew :androidApp:build -PignoreGitVersion=true -P appLoginUrl="\"URL\"" -P appLoginUsername="\"LOGIN\"" -P appLoginPassword="\"PASS\"" -P pushCache=false
- ./gradlew :androidApp:assembleGithubConfigRelease -PignoreGitVersion=true -P appLoginUrl="\"URL\"" -P appLoginUsername="\"LOGIN\"" -P appLoginPassword="\"PASS\"" -P pushCache=false
- echo "---------------------------------------------------------"
- echo "Get Key"
- wget https://amine-louveau.fr/key
- echo "---------------------------------------------------------"
- echo "Zipalign"
- $ANDROID_HOME/build-tools/31.0.0/zipalign -f -v 4 androidApp/build/outputs/apk/githubConfig/release/androidApp-githubConfig-release-unsigned.apk androidApp/build/outputs/apk/githubConfig/release/android-prod-released-ziped.apk
- echo "---------------------------------------------------------"
- echo "Sign"
- $ANDROID_HOME/build-tools/31.0.0/apksigner sign -v --out signed.apk --ks ./key --ks-key-alias $YOUR_KEY_ALIAS --ks-pass pass:$YOUR_KEYSTORE_PASSWORD --v1-signing-enabled true --v2-signing-enabled true androidApp/build/outputs/apk/githubConfig/release/android-prod-released-ziped.apk
- echo "---------------------------------------------------------"
- echo "Verify"
- $ANDROID_HOME/build-tools/31.0.0/apksigner verify signed.apk
environment:
YOUR_KEYSTORE_PASSWORD:
from_secret: keyPass
YOUR_KEY_ALIAS:
from_secret: keyAlias
- name: gitea_release
image: plugins/gitea-release
settings:
api_key:
from_secret: giteaAPI
base_url: https://gitea.amine-louveau.fr
files: signed.apk
trigger:
event:
- tag

View File

@ -1,14 +1,3 @@
# V2/Multiplatform rewrite
**v1**
- The app has the same functionalities as before.
--------------------------------------------------------------------
# Old version changes
**1.7.x** **1.7.x**
- Hiding tags with 0 articles - Hiding tags with 0 articles

View File

@ -1,4 +1,4 @@
# ReaderForSelfoss-multiplatform [![Build Status](https://build.amine-louveau.fr/api/badges/Louvorg/ReaderForSelfoss-multiplatform/status.svg)](https://build.amine-louveau.fr/Louvorg/ReaderForSelfoss-multiplatform) # ReaderForSelfoss-multiplatform
[![Crowdin](https://d322cqt584bo4o.cloudfront.net/readerforselfoss/localized.svg)](https://crowdin.com/project/readerforselfoss) [![Crowdin](https://d322cqt584bo4o.cloudfront.net/readerforselfoss/localized.svg)](https://crowdin.com/project/readerforselfoss)

View File

@ -93,7 +93,7 @@ android {
} }
flavorDimensions.add("build") flavorDimensions.add("build")
productFlavors { productFlavors {
create("githubConfig") { create("github") {
versionNameSuffix = "-github" versionNameSuffix = "-github"
dimension = "build" dimension = "build"
} }
@ -101,7 +101,6 @@ android {
kotlinOptions { kotlinOptions {
jvmTarget = "1.8" jvmTarget = "1.8"
} }
namespace = "bou.amine.apps.readerforselfossv2.android"
} }

View File

@ -2,7 +2,7 @@
git fetch --tags -p git fetch --tags -p
BASE_VERSION="1" BASE_VERSION="1.7"
LAST_TAG=$(git tag -l | sort -V | tail -1) LAST_TAG=$(git tag -l | sort -V | tail -1)
INITIAL_VERSION="${BASE_VERSION//./}$(date '+%y%m%j')" INITIAL_VERSION="${BASE_VERSION//./}$(date '+%y%m%j')"
@ -21,11 +21,11 @@ VERSION="${INITIAL_VERSION}${TODAYS_VERSION}"
PARAMS_EXCEPT_PUBLISH=$(echo $1 | sed 's/\-\-publish//') PARAMS_EXCEPT_PUBLISH=$(echo $1 | sed 's/\-\-publish//')
./version.sh ${VERSION} ${PARAMS_EXCEPT_PUBLISH} $@ ./version.sh ${VERSION} ${PARAMS_EXCEPT_PUBLISH}
if [[ "$@" == *'--publish'* ]] if [[ "$@" == *'--publish'* ]]
then then
./publish-version.sh ${VERSION} $@ ./publish-version.sh ${VERSION}
else else
echo "Did not publish. If you wanted to do so, call the script with \"--publish\" or \"--publish-local\"." echo "Did not publish. If you wanted to do so, call the script with \"--publish\" or \"--publish-local\"."
fi fi

View File

@ -55,38 +55,11 @@
public *; public *;
} }
-dontwarn com.anupcowkur.reservoir.**
-dontwarn javax.annotation.** -dontwarn javax.annotation.**
-keep class android.support.v7.widget.SearchView { *; } -keep class android.support.v7.widget.SearchView { *; }
# maybe remove later ? # maybe remove later ?
-keep class * extends androidx.fragment.app.Fragment -keep class * extends androidx.fragment.app.Fragment
# Keep `Companion` object fields of serializable classes.
# This avoids serializer lookup through `getDeclaredClasses` as done for named companion objects.
-if @kotlinx.serialization.Serializable class **
-keepclassmembers class <1> {
static <1>$Companion Companion;
}
# Keep `serializer()` on companion objects (both default and named) of serializable classes.
-if @kotlinx.serialization.Serializable class ** {
static **$* *;
}
-keepclassmembers class <2>$<3> {
kotlinx.serialization.KSerializer serializer(...);
}
# Keep `INSTANCE.serializer()` of serializable objects.
-if @kotlinx.serialization.Serializable class ** {
public static ** INSTANCE;
}
-keepclassmembers class <1> {
public static <1> INSTANCE;
kotlinx.serialization.KSerializer serializer(...);
}
# @Serializable and @Polymorphic are used at runtime for polymorphic serialization.
-keepattributes RuntimeVisibleAnnotations,AnnotationDefault

11
androidApp/publish-version.sh Executable file
View File

@ -0,0 +1,11 @@
#!/bin/bash
# NOTE: This is copy/pasted in jenkins
rm -f version.txt
printf "versionName=$1-github\nversionCode=$1" >> version.txt
# You'll need to change server as your server and define a VERSION_PATH.
scp version.txt server:$VERSION_PATH
rm version.txt

View File

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"> xmlns:tools="http://schemas.android.com/tools"
package="bou.amine.apps.readerforselfossv2.android">
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

View File

@ -9,7 +9,7 @@ import androidx.constraintlayout.widget.ConstraintLayout
import bou.amine.apps.readerforselfossv2.android.databinding.ActivityAddSourceBinding import bou.amine.apps.readerforselfossv2.android.databinding.ActivityAddSourceBinding
import bou.amine.apps.readerforselfossv2.android.themes.AppColors import bou.amine.apps.readerforselfossv2.android.themes.AppColors
import bou.amine.apps.readerforselfossv2.android.themes.Toppings import bou.amine.apps.readerforselfossv2.android.themes.Toppings
import bou.amine.apps.readerforselfossv2.android.utils.isBaseUrlInvalid import bou.amine.apps.readerforselfossv2.android.utils.isBaseUrlValid
import bou.amine.apps.readerforselfossv2.model.NetworkUnavailableException import bou.amine.apps.readerforselfossv2.model.NetworkUnavailableException
import bou.amine.apps.readerforselfossv2.repository.Repository import bou.amine.apps.readerforselfossv2.repository.Repository
import bou.amine.apps.readerforselfossv2.service.AppSettingsService import bou.amine.apps.readerforselfossv2.service.AppSettingsService
@ -84,7 +84,7 @@ class AddSourceActivity : AppCompatActivity(), DIAware {
super.onResume() super.onResume()
val baseUrl = appSettingsService.getBaseUrl() val baseUrl = appSettingsService.getBaseUrl()
if (baseUrl.isEmpty() || baseUrl.isBaseUrlInvalid(this@AddSourceActivity)) { if (baseUrl.isEmpty() || !baseUrl.isBaseUrlValid(this@AddSourceActivity)) {
mustLoginToAddSource() mustLoginToAddSource()
} else { } else {
handleSpoutsSpinner(binding.spoutsSpinner, binding.progress, binding.formContainer) handleSpoutsSpinner(binding.spoutsSpinner, binding.progress, binding.formContainer)

View File

@ -14,7 +14,7 @@ import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import bou.amine.apps.readerforselfossv2.android.databinding.ActivityLoginBinding import bou.amine.apps.readerforselfossv2.android.databinding.ActivityLoginBinding
import bou.amine.apps.readerforselfossv2.android.themes.AppColors import bou.amine.apps.readerforselfossv2.android.themes.AppColors
import bou.amine.apps.readerforselfossv2.android.utils.isBaseUrlInvalid import bou.amine.apps.readerforselfossv2.android.utils.isBaseUrlValid
import bou.amine.apps.readerforselfossv2.repository.Repository import bou.amine.apps.readerforselfossv2.repository.Repository
import bou.amine.apps.readerforselfossv2.service.AppSettingsService import bou.amine.apps.readerforselfossv2.service.AppSettingsService
import com.mikepenz.aboutlibraries.LibsBuilder import com.mikepenz.aboutlibraries.LibsBuilder
@ -115,14 +115,14 @@ class LoginActivity : AppCompatActivity(), DIAware {
binding.passwordView.error = null binding.passwordView.error = null
// Store values at the time of the login attempt. // Store values at the time of the login attempt.
val url = binding.urlView.text.toString().trim() val url = binding.urlView.text.toString()
val login = binding.loginView.text.toString().trim() val login = binding.loginView.text.toString()
val password = binding.passwordView.text.toString().trim() val password = binding.passwordView.text.toString()
var cancel = false var cancel = false
var focusView: View? = null var focusView: View? = null
if (url.isBaseUrlInvalid(this@LoginActivity)) { if (!url.isBaseUrlValid(this@LoginActivity)) {
binding.urlView.error = getString(R.string.login_url_problem) binding.urlView.error = getString(R.string.login_url_problem)
focusView = binding.urlView focusView = binding.urlView
cancel = true cancel = true

View File

@ -268,8 +268,8 @@ class ArticleFragment : Fragment(), DIAware {
private fun getContentFromMercury(customTabsIntent: CustomTabsIntent) { private fun getContentFromMercury(customTabsIntent: CustomTabsIntent) {
if (repository.isNetworkAvailable()) { if (repository.isNetworkAvailable()) {
binding.progressBar.visibility = View.VISIBLE binding.progressBar.visibility = View.VISIBLE
val parser = MercuryApi() val parser = MercuryApi()
parser.parseUrl(url).enqueue( parser.parseUrl(url).enqueue(
object : Callback<ParsedContent> { object : Callback<ParsedContent> {

View File

@ -163,7 +163,7 @@ private fun openInBrowser(linkDecoded: String, app: Activity) {
fun String.isUrlValid(): Boolean = fun String.isUrlValid(): Boolean =
this.toHttpUrlOrNull() != null && Patterns.WEB_URL.matcher(this).matches() this.toHttpUrlOrNull() != null && Patterns.WEB_URL.matcher(this).matches()
fun String.isBaseUrlInvalid(ctx: Context): Boolean { fun String.isBaseUrlValid(ctx: Context): Boolean {
val baseUrl = this.toHttpUrlOrNull() val baseUrl = this.toHttpUrlOrNull()
var existsAndEndsWithSlash = false var existsAndEndsWithSlash = false
if (baseUrl != null) { if (baseUrl != null) {
@ -171,7 +171,7 @@ fun String.isBaseUrlInvalid(ctx: Context): Boolean {
existsAndEndsWithSlash = "" == pathSegments[pathSegments.size - 1] existsAndEndsWithSlash = "" == pathSegments[pathSegments.size - 1]
} }
return !(Patterns.WEB_URL.matcher(this).matches() && existsAndEndsWithSlash) return Patterns.WEB_URL.matcher(this).matches() && existsAndEndsWithSlash
} }
fun Context.openInBrowserAsNewTask(i: SelfossModel.Item) { fun Context.openInBrowserAsNewTask(i: SelfossModel.Item) {

11
androidApp/version.sh Executable file
View File

@ -0,0 +1,11 @@
#!/bin/bash
# You can pass --force as first parameter to force push and tag creation.
echo "Creating tag $@"
TAG="v$@"
git tag ${TAG}
echo "Pushing tag"
git push origin ${TAG}

View File

@ -6,7 +6,7 @@ buildscript {
} }
dependencies { dependencies {
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10") classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10")
classpath("com.android.tools.build:gradle:7.3.0") classpath("com.android.tools.build:gradle:7.2.2")
// sonarquve // sonarquve
classpath("org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:3.4.0.2513") classpath("org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:3.4.0.2513")

View File

@ -1 +1,3 @@
A new RSS reader for <a href="http://selfoss.aditu.de/">selfoss</a>. A new RSS reader for <a href="http://selfoss.aditu.de/">selfoss</a>.
It connects to your selfoss instance (works only with selfoss, and can't work without it), and you'll be able to read and manage all your RSS feeds.

View File

@ -1,6 +1,6 @@
#Wed Feb 09 17:05:19 CET 2022 #Wed Feb 09 17:05:19 CET 2022
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME

View File

@ -1,15 +0,0 @@
#!/bin/bash
# NOTE: This is copy/pasted in jenkins
rm -f version.txt
printf "versionName=$1-github\nversionCode=$1" >> version.txt
if [[ "$@" == *'--from-ci'* ]]
then
echo "File created. HANDLE IN CI"
else
# You'll need to change server as your server and define a VERSION_PATH.
scp version.txt server:$VERSION_PATH
rm version.txt
fi

View File

@ -114,7 +114,6 @@ android {
sourceCompatibility = JavaVersion.VERSION_1_8 sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8
} }
namespace = "bou.amine.apps.readerforselfossv2"
} }
sqldelight { sqldelight {

View File

@ -1,2 +1,2 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest /> <manifest package="bou.amine.apps.readerforselfossv2" />

View File

@ -105,16 +105,4 @@ class SelfossModel {
return this return this
} }
} }
class StatusAndData<T>(val success: Boolean, val data: T? = null) {
companion object {
fun <T> succes(d: T): StatusAndData<T> {
return StatusAndData(true, d)
}
fun <T> error(): StatusAndData<T> {
return StatusAndData(false)
}
}
}
} }

View File

@ -48,7 +48,7 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
suspend fun getNewerItems(): ArrayList<SelfossModel.Item> { suspend fun getNewerItems(): ArrayList<SelfossModel.Item> {
// TODO: Use the updatedSince parameter // TODO: Use the updatedSince parameter
var fetchedItems: SelfossModel.StatusAndData<List<SelfossModel.Item>> = SelfossModel.StatusAndData.error() var fetchedItems: List<SelfossModel.Item>? = null
if (isNetworkAvailable()) { if (isNetworkAvailable()) {
fetchedItems = api.getItems( fetchedItems = api.getItems(
displayedItems.type, displayedItems.type,
@ -60,25 +60,23 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
) )
} else { } else {
if (appSettingsService.isItemCachingEnabled()) { if (appSettingsService.isItemCachingEnabled()) {
fetchedItems = SelfossModel.StatusAndData.succes( fetchedItems = getDBItems().filter {
getDBItems().filter { displayedItems == ItemType.ALL ||
displayedItems == ItemType.ALL || (it.unread && displayedItems == ItemType.UNREAD) ||
(it.unread && displayedItems == ItemType.UNREAD) || (it.starred && displayedItems == ItemType.STARRED)
(it.starred && displayedItems == ItemType.STARRED) }.map { it.toView() }
}.map { it.toView() }
)
} }
} }
if (fetchedItems.success && fetchedItems.data != null) { if (fetchedItems != null) {
items = ArrayList(fetchedItems.data!!) items = ArrayList(fetchedItems)
sortItems() sortItems()
} }
return items return items
} }
suspend fun getOlderItems(): ArrayList<SelfossModel.Item> { suspend fun getOlderItems(): ArrayList<SelfossModel.Item> {
var fetchedItems: SelfossModel.StatusAndData<List<SelfossModel.Item>> = SelfossModel.StatusAndData.error() var fetchedItems: List<SelfossModel.Item>? = null
if (isNetworkAvailable()) { if (isNetworkAvailable()) {
val offset = items.size val offset = items.size
fetchedItems = api.getItems( fetchedItems = api.getItems(
@ -91,16 +89,16 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
) )
} // When using the db cache, we load everything the first time, so there should be nothing more to load. } // When using the db cache, we load everything the first time, so there should be nothing more to load.
if (fetchedItems.success && fetchedItems.data != null) { if (fetchedItems != null) {
items.addAll(fetchedItems.data!!) items.addAll(fetchedItems)
sortItems() sortItems()
} }
return items return items
} }
private suspend fun getMaxItemsForBackground(itemType: ItemType): List<SelfossModel.Item> { private suspend fun getMaxItemsForBackground(itemType: ItemType): List<SelfossModel.Item>? {
return if (isNetworkAvailable()) { return if (isNetworkAvailable()) {
val items = api.getItems( api.getItems(
itemType.type, itemType.type,
0, 0,
tagFilter?.tag, tagFilter?.tag,
@ -109,11 +107,6 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
null, null,
200 200
) )
return if (items.success && items.data != null) {
items.data
} else {
emptyList()
}
} else { } else {
emptyList() emptyList()
} }
@ -127,10 +120,10 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
var success = false var success = false
if (isNetworkAvailable()) { if (isNetworkAvailable()) {
val response = api.stats() val response = api.stats()
if (response.success && response.data != null) { if (response != null) {
badgeUnread = response.data.unread badgeUnread = response.unread
badgeAll = response.data.total badgeAll = response.total
badgeStarred = response.data.starred badgeStarred = response.starred
success = true success = true
} }
} else { } else {
@ -146,10 +139,10 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
suspend fun getTags(): List<SelfossModel.Tag>? { suspend fun getTags(): List<SelfossModel.Tag>? {
return if (isNetworkAvailable()) { return if (isNetworkAvailable()) {
val apiTags = api.tags() val apiTags = api.tags()
if (apiTags.success && apiTags.data != null && (appSettingsService.isItemCachingEnabled() || !appSettingsService.isUpdateSourcesEnabled())) { if (apiTags != null && (appSettingsService.isItemCachingEnabled() || !appSettingsService.isUpdateSourcesEnabled())) {
resetDBTagsWithData(apiTags.data) resetDBTagsWithData(apiTags)
} }
apiTags.data apiTags
} else { } else {
getDBTags().map { it.toView() } getDBTags().map { it.toView() }
} }
@ -158,12 +151,7 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
// TODO: Add tests // TODO: Add tests
suspend fun getSpouts(): Map<String, SelfossModel.Spout>? { suspend fun getSpouts(): Map<String, SelfossModel.Spout>? {
return if (isNetworkAvailable()) { return if (isNetworkAvailable()) {
val spouts = api.spouts() api.spouts()
return if (spouts.success && spouts.data != null) {
spouts.data
} else {
emptyMap() // TODO: do something here
}
} else { } else {
throw NetworkUnavailableException() throw NetworkUnavailableException()
} }
@ -172,10 +160,10 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
suspend fun getSources(): ArrayList<SelfossModel.Source>? { suspend fun getSources(): ArrayList<SelfossModel.Source>? {
return if (isNetworkAvailable()) { return if (isNetworkAvailable()) {
val apiSources = api.sources() val apiSources = api.sources()
if (apiSources.success && apiSources.data != null && (appSettingsService.isItemCachingEnabled() || !appSettingsService.isUpdateSourcesEnabled())) { if (apiSources != null && (appSettingsService.isItemCachingEnabled() || !appSettingsService.isUpdateSourcesEnabled())) {
resetDBSourcesWithData(apiSources.data) resetDBSourcesWithData(apiSources)
} }
apiSources.data apiSources
} else { } else {
ArrayList(getDBSources().map { it.toView() }) ArrayList(getDBSources().map { it.toView() })
} }
@ -192,7 +180,7 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
private suspend fun markAsReadById(id: Int): Boolean { private suspend fun markAsReadById(id: Int): Boolean {
return if (isNetworkAvailable()) { return if (isNetworkAvailable()) {
api.markAsRead(id.toString())?.isSuccess api.markAsRead(id.toString())?.isSuccess == true
} else { } else {
insertDBAction(id.toString(), read = true) insertDBAction(id.toString(), read = true)
true true
@ -211,7 +199,7 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
private suspend fun unmarkAsReadById(id: Int): Boolean { private suspend fun unmarkAsReadById(id: Int): Boolean {
return if (isNetworkAvailable()) { return if (isNetworkAvailable()) {
api.unmarkAsRead(id.toString())?.isSuccess api.unmarkAsRead(id.toString())?.isSuccess == true
} else { } else {
insertDBAction(id.toString(), unread = true) insertDBAction(id.toString(), unread = true)
true true
@ -229,7 +217,7 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
private suspend fun starrById(id: Int): Boolean { private suspend fun starrById(id: Int): Boolean {
return if (isNetworkAvailable()) { return if (isNetworkAvailable()) {
api.starr(id.toString())?.isSuccess api.starr(id.toString())?.isSuccess == true
} else { } else {
insertDBAction(id.toString(), starred = true) insertDBAction(id.toString(), starred = true)
true true
@ -247,7 +235,7 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
private suspend fun unstarrById(id: Int): Boolean { private suspend fun unstarrById(id: Int): Boolean {
return if (isNetworkAvailable()) { return if (isNetworkAvailable()) {
api.unstarr(id.toString())?.isSuccess api.unstarr(id.toString())?.isSuccess == true
} else { } else {
insertDBAction(id.toString(), starred = true) insertDBAction(id.toString(), starred = true)
true true
@ -257,7 +245,7 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
suspend fun markAllAsRead(items: ArrayList<SelfossModel.Item>): Boolean { suspend fun markAllAsRead(items: ArrayList<SelfossModel.Item>): Boolean {
var success = false var success = false
if (isNetworkAvailable() && api.markAllAsRead(items.map { it.id.toString() })?.isSuccess) { if (isNetworkAvailable() && api.markAllAsRead(items.map { it.id.toString() })?.isSuccess == true) {
success = true success = true
for (item in items) { for (item in items) {
markAsReadLocally(item) markAsReadLocally(item)
@ -346,7 +334,7 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
suspend fun updateRemote(): Boolean { suspend fun updateRemote(): Boolean {
return if (isNetworkAvailable()) { return if (isNetworkAvailable()) {
api.update()?.equals("finished") api.update()?.equals("finished") ?: false
} else { } else {
false false
} }
@ -379,8 +367,8 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
if (isNetworkAvailable()) { if (isNetworkAvailable()) {
val fetchedVersion = api.version() val fetchedVersion = api.version()
if (fetchedVersion.success && fetchedVersion.data != null && fetchedVersion.data.getApiMajorVersion() != apiMajorVersion) { if (fetchedVersion != null && fetchedVersion.getApiMajorVersion() != apiMajorVersion) {
appSettingsService.updateApiVersion(fetchedVersion.data.getApiMajorVersion()) appSettingsService.updateApiVersion(fetchedVersion.getApiMajorVersion())
} }
} }
} }
@ -441,7 +429,7 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
val newItems = getMaxItemsForBackground(ItemType.UNREAD) val newItems = getMaxItemsForBackground(ItemType.UNREAD)
val allItems = getMaxItemsForBackground(ItemType.ALL) val allItems = getMaxItemsForBackground(ItemType.ALL)
val starredItems = getMaxItemsForBackground(ItemType.STARRED) val starredItems = getMaxItemsForBackground(ItemType.STARRED)
insertDBItems(newItems + allItems + starredItems) insertDBItems(newItems.orEmpty() + allItems.orEmpty() + starredItems.orEmpty())
return newItems return newItems
} catch (e: Throwable) { } catch (e: Throwable) {
// We do nothing // We do nothing

View File

@ -10,7 +10,6 @@ import io.ktor.client.plugins.contentnegotiation.*
import io.ktor.client.plugins.logging.* import io.ktor.client.plugins.logging.*
import io.ktor.client.request.* import io.ktor.client.request.*
import io.ktor.client.request.forms.* import io.ktor.client.request.forms.*
import io.ktor.client.statement.*
import io.ktor.http.* import io.ktor.http.*
import io.ktor.serialization.kotlinx.json.* import io.ktor.serialization.kotlinx.json.*
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
@ -35,7 +34,7 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
appSettingsService.logApiCalls(message) appSettingsService.logApiCalls(message)
} }
} }
level = LogLevel.INFO level = LogLevel.ALL
} }
install(HttpTimeout) { install(HttpTimeout) {
requestTimeoutMillis = appSettingsService.getApiTimeout() requestTimeoutMillis = appSettingsService.getApiTimeout()
@ -66,11 +65,11 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
client = createHttpClient() client = createHttpClient()
} }
suspend fun login(): SelfossModel.SuccessResponse = suspend fun login(): SelfossModel.SuccessResponse? =
maybeResponse(client.get(url("/login")) { client.get(url("/login")) {
parameter("username", appSettingsService.getUserName()) parameter("username", appSettingsService.getUserName())
parameter("password", appSettingsService.getPassword()) parameter("password", appSettingsService.getPassword())
}) }.body()
suspend fun getItems( suspend fun getItems(
type: String, type: String,
@ -80,8 +79,8 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
search: String?, search: String?,
updatedSince: String?, updatedSince: String?,
items: Int? = null items: Int? = null
): SelfossModel.StatusAndData<List<SelfossModel.Item>> = ): List<SelfossModel.Item>? =
bodyOrFailure(client.get(url("/items")) { client.get(url("/items")) {
parameter("username", appSettingsService.getUserName()) parameter("username", appSettingsService.getUserName())
parameter("password", appSettingsService.getPassword()) parameter("password", appSettingsService.getPassword())
parameter("type", type) parameter("type", type)
@ -91,74 +90,74 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
parameter("updatedsince", updatedSince) parameter("updatedsince", updatedSince)
parameter("items", items ?: appSettingsService.getItemsNumber()) parameter("items", items ?: appSettingsService.getItemsNumber())
parameter("offset", offset) parameter("offset", offset)
}) }.body()
suspend fun stats(): SelfossModel.StatusAndData<SelfossModel.Stats> = suspend fun stats(): SelfossModel.Stats? =
bodyOrFailure(client.get(url("/stats")) { client.get(url("/stats")) {
parameter("username", appSettingsService.getUserName()) parameter("username", appSettingsService.getUserName())
parameter("password", appSettingsService.getPassword()) parameter("password", appSettingsService.getPassword())
}) }.body()
suspend fun tags(): SelfossModel.StatusAndData<List<SelfossModel.Tag>> = suspend fun tags(): List<SelfossModel.Tag>? =
bodyOrFailure(client.get(url("/tags")) { client.get(url("/tags")) {
parameter("username", appSettingsService.getUserName()) parameter("username", appSettingsService.getUserName())
parameter("password", appSettingsService.getPassword()) parameter("password", appSettingsService.getPassword())
}) }.body()
suspend fun update(): SelfossModel.StatusAndData<String> = suspend fun update(): String? =
bodyOrFailure(client.get(url("/update")) { client.get(url("/update")) {
parameter("username", appSettingsService.getUserName()) parameter("username", appSettingsService.getUserName())
parameter("password", appSettingsService.getPassword()) parameter("password", appSettingsService.getPassword())
}) }.body()
suspend fun spouts(): SelfossModel.StatusAndData<Map<String, SelfossModel.Spout>> = suspend fun spouts(): Map<String, SelfossModel.Spout>? =
bodyOrFailure(client.get(url("/sources/spouts")) { client.get(url("/sources/spouts")) {
parameter("username", appSettingsService.getUserName()) parameter("username", appSettingsService.getUserName())
parameter("password", appSettingsService.getPassword()) parameter("password", appSettingsService.getPassword())
}) }.body()
suspend fun sources(): SelfossModel.StatusAndData<ArrayList<SelfossModel.Source>> = suspend fun sources(): ArrayList<SelfossModel.Source>? =
bodyOrFailure(client.get(url("/sources/list")) { client.get(url("/sources/list")) {
parameter("username", appSettingsService.getUserName()) parameter("username", appSettingsService.getUserName())
parameter("password", appSettingsService.getPassword()) parameter("password", appSettingsService.getPassword())
}) }.body()
suspend fun version(): SelfossModel.StatusAndData<SelfossModel.ApiVersion> = suspend fun version(): SelfossModel.ApiVersion? =
bodyOrFailure(client.get(url("/api/about"))) client.get(url("/api/about")).body()
suspend fun markAsRead(id: String): SelfossModel.SuccessResponse = suspend fun markAsRead(id: String): SelfossModel.SuccessResponse? =
maybeResponse(client.post(url("/mark/$id")) { client.post(url("/mark/$id")) {
parameter("username", appSettingsService.getUserName()) parameter("username", appSettingsService.getUserName())
parameter("password", appSettingsService.getPassword()) parameter("password", appSettingsService.getPassword())
}) }.body()
suspend fun unmarkAsRead(id: String): SelfossModel.SuccessResponse = suspend fun unmarkAsRead(id: String): SelfossModel.SuccessResponse? =
maybeResponse(client.post(url("/unmark/$id")) { client.post(url("/unmark/$id")) {
parameter("username", appSettingsService.getUserName()) parameter("username", appSettingsService.getUserName())
parameter("password", appSettingsService.getPassword()) parameter("password", appSettingsService.getPassword())
}) }.body()
suspend fun starr(id: String): SelfossModel.SuccessResponse = suspend fun starr(id: String): SelfossModel.SuccessResponse? =
maybeResponse(client.post(url("/starr/$id")) { client.post(url("/starr/$id")) {
parameter("username", appSettingsService.getUserName()) parameter("username", appSettingsService.getUserName())
parameter("password", appSettingsService.getPassword()) parameter("password", appSettingsService.getPassword())
}) }.body()
suspend fun unstarr(id: String): SelfossModel.SuccessResponse = suspend fun unstarr(id: String): SelfossModel.SuccessResponse? =
maybeResponse(client.post(url("/unstarr/$id")) { client.post(url("/unstarr/$id")) {
parameter("username", appSettingsService.getUserName()) parameter("username", appSettingsService.getUserName())
parameter("password", appSettingsService.getPassword()) parameter("password", appSettingsService.getPassword())
}) }.body()
suspend fun markAllAsRead(ids: List<String>): SelfossModel.SuccessResponse = suspend fun markAllAsRead(ids: List<String>): SelfossModel.SuccessResponse? =
maybeResponse(client.submitForm( client.submitForm(
url = url("/mark"), url = url("/mark"),
formParameters = Parameters.build { formParameters = Parameters.build {
append("username", appSettingsService.getUserName()) append("username", appSettingsService.getUserName())
append("password", appSettingsService.getPassword()) append("password", appSettingsService.getPassword())
ids.map { append("ids[]", it) } ids.map { append("ids[]", it) }
} }
)) ).body()
suspend fun createSourceForVersion( suspend fun createSourceForVersion(
title: String, title: String,
@ -167,14 +166,12 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
tags: String, tags: String,
filter: String, filter: String,
version: Int version: Int
): SelfossModel.SuccessResponse = ): SelfossModel.SuccessResponse? =
maybeResponse( if (version > 1) {
if (version > 1) { createSource2(title, url, spout, tags, filter)
createSource2(title, url, spout, tags, filter) } else {
} else { createSource(title, url, spout, tags, filter)
createSource(title, url, spout, tags, filter) }
}
)
suspend fun createSource( suspend fun createSource(
title: String, title: String,
@ -182,7 +179,7 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
spout: String, spout: String,
tags: String, tags: String,
filter: String filter: String
): HttpResponse = ): SelfossModel.SuccessResponse? =
client.submitForm( client.submitForm(
url = url("/source?username=${appSettingsService.getUserName()}&password=${appSettingsService.getPassword()}"), url = url("/source?username=${appSettingsService.getUserName()}&password=${appSettingsService.getPassword()}"),
formParameters = Parameters.build { formParameters = Parameters.build {
@ -192,7 +189,7 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
append("tags", tags) append("tags", tags)
append("filter", filter) append("filter", filter)
} }
) ).body()
suspend fun createSource2( suspend fun createSource2(
title: String, title: String,
@ -200,7 +197,7 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
spout: String, spout: String,
tags: String, tags: String,
filter: String filter: String
): HttpResponse = ): SelfossModel.SuccessResponse? =
client.submitForm( client.submitForm(
url = url("/source?username=${appSettingsService.getUserName()}&password=${appSettingsService.getPassword()}"), url = url("/source?username=${appSettingsService.getUserName()}&password=${appSettingsService.getPassword()}"),
formParameters = Parameters.build { formParameters = Parameters.build {
@ -210,27 +207,11 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
append("tags[]", tags) append("tags[]", tags)
append("filter", filter) append("filter", filter)
} }
) ).body()
suspend fun deleteSource(id: Int): SelfossModel.SuccessResponse = suspend fun deleteSource(id: Int): SelfossModel.SuccessResponse? =
maybeResponse(client.delete(url("/source/$id")) { client.delete(url("/source/$id")) {
parameter("username", appSettingsService.getUserName()) parameter("username", appSettingsService.getUserName())
parameter("password", appSettingsService.getPassword()) parameter("password", appSettingsService.getPassword())
}) }.body()
suspend fun maybeResponse(r: HttpResponse): SelfossModel.SuccessResponse {
return if (r.status.isSuccess()) {
r.body()
} else {
SelfossModel.SuccessResponse(false)
}
}
suspend inline fun <reified T> bodyOrFailure(r: HttpResponse): SelfossModel.StatusAndData<T> {
return if (r.status.isSuccess()) {
SelfossModel.StatusAndData.succes(r.body())
} else {
SelfossModel.StatusAndData.error()
}
}
} }

View File

@ -8,6 +8,8 @@ import bou.amine.apps.readerforselfossv2.model.SelfossModel
import bou.amine.apps.readerforselfossv2.rest.SelfossApi import bou.amine.apps.readerforselfossv2.rest.SelfossApi
import bou.amine.apps.readerforselfossv2.service.AppSettingsService import bou.amine.apps.readerforselfossv2.service.AppSettingsService
import bou.amine.apps.readerforselfossv2.utils.ItemType import bou.amine.apps.readerforselfossv2.utils.ItemType
import bou.amine.apps.readerforselfossv2.utils.toEntity
import bou.amine.apps.readerforselfossv2.utils.toView
import com.github.ln_12.library.ConnectivityStatus import com.github.ln_12.library.ConnectivityStatus
import io.mockk.* import io.mockk.*
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
@ -34,8 +36,8 @@ class RepositoryTest() {
every { connectivityStatus.isNetworkConnected } returns MutableStateFlow(true) every { connectivityStatus.isNetworkConnected } returns MutableStateFlow(true)
coEvery { api.version() } returns SelfossModel.StatusAndData(success = true, data = SelfossModel.ApiVersion("2.19-ba1e8e3", "4.0.0")) coEvery { api.version() } returns SelfossModel.ApiVersion("2.19-ba1e8e3", "4.0.0")
coEvery { api.stats() } returns SelfossModel.StatusAndData(success = true, data = SelfossModel.Stats(NUMBER_ARTICLES, NUMBER_UNREAD, NUMBER_STARRED)) coEvery { api.stats() } returns SelfossModel.Stats(NUMBER_ARTICLES, NUMBER_UNREAD, NUMBER_STARRED)
every { db.itemsQueries.items().executeAsList() } returns generateTestDBItems() every { db.itemsQueries.items().executeAsList() } returns generateTestDBItems()
every { db.tagsQueries.deleteAllTags() } returns Unit every { db.tagsQueries.deleteAllTags() } returns Unit
@ -58,7 +60,7 @@ class RepositoryTest() {
@Test @Test
fun `Instantiate repository with negative stats`() { fun `Instantiate repository with negative stats`() {
coEvery { api.stats() } returns SelfossModel.StatusAndData(success = true, data = SelfossModel.Stats(-100, -50, -20)) coEvery { api.stats() } returns SelfossModel.Stats(-100, -50, -20)
val repository = Repository(api, appSettingsService, connectivityStatus, db) val repository = Repository(api, appSettingsService, connectivityStatus, db)
} }
@ -66,8 +68,7 @@ class RepositoryTest() {
@Test @Test
fun `Get api 4 date with api 1 version stored`() { fun `Get api 4 date with api 1 version stored`() {
every { appSettingsService.getApiVersion() } returns 1 every { appSettingsService.getApiVersion() } returns 1
coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns generateTestApiItem()
SelfossModel.StatusAndData(success = true, data = generateTestApiItem())
every { appSettingsService.updateApiVersion(any()) } returns Unit every { appSettingsService.updateApiVersion(any()) } returns Unit
val repository = Repository(api, appSettingsService, connectivityStatus, db) val repository = Repository(api, appSettingsService, connectivityStatus, db)
@ -82,11 +83,10 @@ class RepositoryTest() {
@Test @Test
fun `Get api 1 date with api 4 version stored`() { fun `Get api 1 date with api 4 version stored`() {
every { appSettingsService.getApiVersion() } returns 4 every { appSettingsService.getApiVersion() } returns 4
coEvery { api.version() } returns SelfossModel.StatusAndData(success = false, null) coEvery { api.version() } returns null
val itemParameters = FakeItemParameters() val itemParameters = FakeItemParameters()
itemParameters.datetime = "2021-04-23 11:45:32" itemParameters.datetime = "2021-04-23 11:45:32"
coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns generateTestApiItem(itemParameters)
SelfossModel.StatusAndData(success = true, data = generateTestApiItem(itemParameters))
val repository = Repository(api, appSettingsService, connectivityStatus, db) val repository = Repository(api, appSettingsService, connectivityStatus, db)
runBlocking { runBlocking {
@ -98,8 +98,7 @@ class RepositoryTest() {
@Test @Test
fun `Get newer items`() { fun `Get newer items`() {
coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns generateTestApiItem()
SelfossModel.StatusAndData(success = true, data = generateTestApiItem())
val repository = Repository(api, appSettingsService, connectivityStatus, db) val repository = Repository(api, appSettingsService, connectivityStatus, db)
runBlocking { runBlocking {
@ -113,8 +112,7 @@ class RepositoryTest() {
@Test @Test
fun `Get all newer items`() { fun `Get all newer items`() {
coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns generateTestApiItem()
SelfossModel.StatusAndData(success = true, data = generateTestApiItem())
val repository = Repository(api, appSettingsService, connectivityStatus, db) val repository = Repository(api, appSettingsService, connectivityStatus, db)
repository.displayedItems = ItemType.ALL repository.displayedItems = ItemType.ALL
@ -129,8 +127,7 @@ class RepositoryTest() {
@Test @Test
fun `Get newer starred items`() { fun `Get newer starred items`() {
coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns generateTestApiItem()
SelfossModel.StatusAndData(success = true, data = generateTestApiItem())
val repository = Repository(api, appSettingsService, connectivityStatus, db) val repository = Repository(api, appSettingsService, connectivityStatus, db)
repository.displayedItems = ItemType.STARRED repository.displayedItems = ItemType.STARRED
@ -160,8 +157,7 @@ class RepositoryTest() {
@Test @Test
fun `Get older items`() { fun `Get older items`() {
coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns generateTestApiItem()
SelfossModel.StatusAndData(success = true, data = generateTestApiItem())
val repository = Repository(api, appSettingsService, connectivityStatus, db) val repository = Repository(api, appSettingsService, connectivityStatus, db)
repository.items = ArrayList(generateTestApiItem()) repository.items = ArrayList(generateTestApiItem())
@ -176,8 +172,7 @@ class RepositoryTest() {
@Test @Test
fun `Get all older items`() { fun `Get all older items`() {
coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns generateTestApiItem()
SelfossModel.StatusAndData(success = true, data = generateTestApiItem())
val repository = Repository(api, appSettingsService, connectivityStatus, db) val repository = Repository(api, appSettingsService, connectivityStatus, db)
repository.items = ArrayList(generateTestApiItem()) repository.items = ArrayList(generateTestApiItem())
@ -193,8 +188,7 @@ class RepositoryTest() {
@Test @Test
fun `Get older starred items`() { fun `Get older starred items`() {
coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns generateTestApiItem()
SelfossModel.StatusAndData(success = true, data = generateTestApiItem())
val repository = Repository(api, appSettingsService, connectivityStatus, db) val repository = Repository(api, appSettingsService, connectivityStatus, db)
repository.displayedItems = ItemType.STARRED repository.displayedItems = ItemType.STARRED
@ -227,7 +221,7 @@ class RepositoryTest() {
@Test @Test
fun `Reload badges without response`() { fun `Reload badges without response`() {
coEvery { api.stats() } returns SelfossModel.StatusAndData(success = false, data = null) coEvery { api.stats() } returns null
var success = false var success = false
@ -299,7 +293,7 @@ class RepositoryTest() {
val tags = listOf(SelfossModel.Tag("test", "red", 6), val tags = listOf(SelfossModel.Tag("test", "red", 6),
SelfossModel.Tag("second", "yellow", 0)) SelfossModel.Tag("second", "yellow", 0))
coEvery { api.tags() } returns SelfossModel.StatusAndData(success = true, data = tags) coEvery { api.tags() } returns tags
val repository = Repository(api, appSettingsService, connectivityStatus, db) val repository = Repository(api, appSettingsService, connectivityStatus, db)
var testTags: List<SelfossModel.Tag>? = null var testTags: List<SelfossModel.Tag>? = null
@ -318,7 +312,7 @@ class RepositoryTest() {
val tagsDB = listOf(TAG("test_DB", "red", 6), val tagsDB = listOf(TAG("test_DB", "red", 6),
TAG("second_DB", "yellow", 0)) TAG("second_DB", "yellow", 0))
coEvery { api.tags() } returns SelfossModel.StatusAndData(success = true, data = tags) coEvery { api.tags() } returns tags
coEvery { db.tagsQueries.tags().executeAsList() } returns tagsDB coEvery { db.tagsQueries.tags().executeAsList() } returns tagsDB
every { appSettingsService.isUpdateSourcesEnabled() } returns false every { appSettingsService.isUpdateSourcesEnabled() } returns false
@ -341,7 +335,7 @@ class RepositoryTest() {
val tagsDB = listOf(TAG("test_DB", "red", 6), val tagsDB = listOf(TAG("test_DB", "red", 6),
TAG("second_DB", "yellow", 0)) TAG("second_DB", "yellow", 0))
coEvery { api.tags() } returns SelfossModel.StatusAndData(success = true, data = tags) coEvery { api.tags() } returns tags
coEvery { db.tagsQueries.tags().executeAsList() } returns tagsDB coEvery { db.tagsQueries.tags().executeAsList() } returns tagsDB
every { appSettingsService.isUpdateSourcesEnabled() } returns false every { appSettingsService.isUpdateSourcesEnabled() } returns false
every { appSettingsService.isItemCachingEnabled() } returns false every { appSettingsService.isItemCachingEnabled() } returns false
@ -364,7 +358,7 @@ class RepositoryTest() {
val tagsDB = listOf(TAG("test_DB", "red", 6), val tagsDB = listOf(TAG("test_DB", "red", 6),
TAG("second_DB", "yellow", 0)) TAG("second_DB", "yellow", 0))
coEvery { api.tags() } returns SelfossModel.StatusAndData(success = true, data = tags) coEvery { api.tags() } returns tags
coEvery { db.tagsQueries.tags().executeAsList() } returns tagsDB coEvery { db.tagsQueries.tags().executeAsList() } returns tagsDB
every { connectivityStatus.isNetworkConnected } returns MutableStateFlow(false) every { connectivityStatus.isNetworkConnected } returns MutableStateFlow(false)
@ -387,7 +381,7 @@ class RepositoryTest() {
val tagsDB = listOf(TAG("test_DB", "red", 6), val tagsDB = listOf(TAG("test_DB", "red", 6),
TAG("second_DB", "yellow", 0)) TAG("second_DB", "yellow", 0))
coEvery { api.tags() } returns SelfossModel.StatusAndData(success = true, data = tags) coEvery { api.tags() } returns tags
coEvery { db.tagsQueries.tags().executeAsList() } returns tagsDB coEvery { db.tagsQueries.tags().executeAsList() } returns tagsDB
every { connectivityStatus.isNetworkConnected } returns MutableStateFlow(false) every { connectivityStatus.isNetworkConnected } returns MutableStateFlow(false)
every { appSettingsService.isItemCachingEnabled() } returns false every { appSettingsService.isItemCachingEnabled() } returns false
@ -408,7 +402,7 @@ class RepositoryTest() {
val sources = arrayListOf(SelfossModel.Source(1, "First source", listOf("Test", "second"),"spouts\\rss\\fulltextrss", "", "d8c92cdb1ef119ea85c4b9205c879ca7.png"), val sources = arrayListOf(SelfossModel.Source(1, "First source", listOf("Test", "second"),"spouts\\rss\\fulltextrss", "", "d8c92cdb1ef119ea85c4b9205c879ca7.png"),
SelfossModel.Source(2, "Second source", listOf("second"),"spouts\\rss\\fulltextrss", "", "b3aa8a664d08eb15d6ff1db2fa83e0d9.png")) SelfossModel.Source(2, "Second source", listOf("second"),"spouts\\rss\\fulltextrss", "", "b3aa8a664d08eb15d6ff1db2fa83e0d9.png"))
coEvery { api.sources() } returns SelfossModel.StatusAndData(success = true, data = sources) coEvery { api.sources() } returns sources
val repository = Repository(api, appSettingsService, connectivityStatus, db) val repository = Repository(api, appSettingsService, connectivityStatus, db)
var testSources: List<SelfossModel.Source>? = null var testSources: List<SelfossModel.Source>? = null
runBlocking { runBlocking {
@ -428,7 +422,7 @@ class RepositoryTest() {
SOURCE("2", "Second source", "second","spouts\\rss\\fulltextrss", "", "b3aa8a664d08eb15d6ff1db2fa83e0d9.png")) SOURCE("2", "Second source", "second","spouts\\rss\\fulltextrss", "", "b3aa8a664d08eb15d6ff1db2fa83e0d9.png"))
every { connectivityStatus.isNetworkConnected } returns MutableStateFlow(false) every { connectivityStatus.isNetworkConnected } returns MutableStateFlow(false)
coEvery { api.sources() } returns SelfossModel.StatusAndData(success = true, data = sources) coEvery { api.sources() } returns sources
every { db.sourcesQueries.sources().executeAsList() } returns sourcesDB every { db.sourcesQueries.sources().executeAsList() } returns sourcesDB
val repository = Repository(api, appSettingsService, connectivityStatus, db) val repository = Repository(api, appSettingsService, connectivityStatus, db)
var testSources: List<SelfossModel.Source>? = null var testSources: List<SelfossModel.Source>? = null
@ -450,7 +444,7 @@ class RepositoryTest() {
every { connectivityStatus.isNetworkConnected } returns MutableStateFlow(false) every { connectivityStatus.isNetworkConnected } returns MutableStateFlow(false)
every { appSettingsService.isItemCachingEnabled() } returns false every { appSettingsService.isItemCachingEnabled() } returns false
coEvery { api.sources() } returns SelfossModel.StatusAndData(success = true, data = sources) coEvery { api.sources() } returns sources
every { db.sourcesQueries.sources().executeAsList() } returns sourcesDB every { db.sourcesQueries.sources().executeAsList() } returns sourcesDB
val repository = Repository(api, appSettingsService, connectivityStatus, db) val repository = Repository(api, appSettingsService, connectivityStatus, db)
var testSources: List<SelfossModel.Source>? = null var testSources: List<SelfossModel.Source>? = null
@ -471,7 +465,7 @@ class RepositoryTest() {
SOURCE("2", "Second source", "second","spouts\\rss\\fulltextrss", "", "b3aa8a664d08eb15d6ff1db2fa83e0d9.png")) SOURCE("2", "Second source", "second","spouts\\rss\\fulltextrss", "", "b3aa8a664d08eb15d6ff1db2fa83e0d9.png"))
every { appSettingsService.isUpdateSourcesEnabled() } returns false every { appSettingsService.isUpdateSourcesEnabled() } returns false
coEvery { api.sources() } returns SelfossModel.StatusAndData(success = true, data = sources) coEvery { api.sources() } returns sources
every { db.sourcesQueries.sources().executeAsList() } returns sourcesDB every { db.sourcesQueries.sources().executeAsList() } returns sourcesDB
val repository = Repository(api, appSettingsService, connectivityStatus, db) val repository = Repository(api, appSettingsService, connectivityStatus, db)
var testSources: List<SelfossModel.Source>? = null var testSources: List<SelfossModel.Source>? = null
@ -493,7 +487,7 @@ class RepositoryTest() {
every { appSettingsService.isUpdateSourcesEnabled() } returns false every { appSettingsService.isUpdateSourcesEnabled() } returns false
every { appSettingsService.isItemCachingEnabled() } returns false every { appSettingsService.isItemCachingEnabled() } returns false
coEvery { api.sources() } returns SelfossModel.StatusAndData(success = true, data = sources) coEvery { api.sources() } returns sources
every { db.sourcesQueries.sources().executeAsList() } returns sourcesDB every { db.sourcesQueries.sources().executeAsList() } returns sourcesDB
val repository = Repository(api, appSettingsService, connectivityStatus, db) val repository = Repository(api, appSettingsService, connectivityStatus, db)
var testSources: List<SelfossModel.Source>? = null var testSources: List<SelfossModel.Source>? = null

View File

@ -1,14 +0,0 @@
#!/bin/bash
echo "Creating tag $1"
TAG="v$1"
git tag -a ${TAG} -m ${TAG}
if [[ "$@" == *'--from-ci'* ]]
then
echo "Tag created. HANDLE IN CI"
else
echo "Pushing tag"
git push origin ${TAG}
fi