Merge branch 'master' into repository_tests
# Conflicts: # .drone.yml
This commit is contained in:
commit
d2436bb976
106
.drone.yml
106
.drone.yml
@ -1,26 +1,118 @@
|
|||||||
kind: pipeline
|
kind: pipeline
|
||||||
type: docker
|
type: docker
|
||||||
name: android
|
name: test
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: code-analysis
|
- name: AnylyseBuildTest
|
||||||
image: mingc/android-build-box:latest
|
image: mingc/android-build-box:latest
|
||||||
failure: ignore
|
failure: ignore
|
||||||
commands:
|
commands:
|
||||||
- ls -la
|
- echo "---------------------------------------------------------"
|
||||||
|
- 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
|
---
|
||||||
image: mingc/android-build-box:latest
|
kind: pipeline
|
||||||
|
type: docker
|
||||||
|
name: Publish
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: createTag
|
||||||
|
image: ubuntu:latest
|
||||||
commands:
|
commands:
|
||||||
- ./gradlew test -PignoreGitVersion=true -P appLoginUrl="\"URL\"" -P appLoginUsername="\"LOGIN\"" -P appLoginPassword="\"PASS\"" -P pushCache=false
|
- apt-get update && apt-get install -y git
|
||||||
|
- ./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:
|
||||||
- ./gradlew :androidApp:build -PignoreGitVersion=true -P appLoginUrl="\"URL\"" -P appLoginUsername="\"LOGIN\"" -P appLoginPassword="\"PASS\"" -P pushCache=false
|
- echo "Generate APK"
|
||||||
|
- ./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
|
11
CHANGELOG.md
11
CHANGELOG.md
@ -1,3 +1,14 @@
|
|||||||
|
# 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
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# ReaderForSelfoss-multiplatform
|
# ReaderForSelfoss-multiplatform [![Build Status](https://build.amine-louveau.fr/api/badges/Louvorg/ReaderForSelfoss-multiplatform/status.svg)](https://build.amine-louveau.fr/Louvorg/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)
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ android {
|
|||||||
}
|
}
|
||||||
flavorDimensions.add("build")
|
flavorDimensions.add("build")
|
||||||
productFlavors {
|
productFlavors {
|
||||||
create("github") {
|
create("githubConfig") {
|
||||||
versionNameSuffix = "-github"
|
versionNameSuffix = "-github"
|
||||||
dimension = "build"
|
dimension = "build"
|
||||||
}
|
}
|
||||||
@ -101,6 +101,7 @@ android {
|
|||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
jvmTarget = "1.8"
|
jvmTarget = "1.8"
|
||||||
}
|
}
|
||||||
|
namespace = "bou.amine.apps.readerforselfossv2.android"
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
31
androidApp/proguard-rules.pro
vendored
31
androidApp/proguard-rules.pro
vendored
@ -55,11 +55,38 @@
|
|||||||
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
|
||||||
|
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
#!/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
|
|
@ -1,7 +1,6 @@
|
|||||||
<?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" />
|
||||||
|
@ -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.isBaseUrlValid
|
import bou.amine.apps.readerforselfossv2.android.utils.isBaseUrlInvalid
|
||||||
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.isBaseUrlValid(this@AddSourceActivity)) {
|
if (baseUrl.isEmpty() || baseUrl.isBaseUrlInvalid(this@AddSourceActivity)) {
|
||||||
mustLoginToAddSource()
|
mustLoginToAddSource()
|
||||||
} else {
|
} else {
|
||||||
handleSpoutsSpinner(binding.spoutsSpinner, binding.progress, binding.formContainer)
|
handleSpoutsSpinner(binding.spoutsSpinner, binding.progress, binding.formContainer)
|
||||||
|
@ -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.isBaseUrlValid
|
import bou.amine.apps.readerforselfossv2.android.utils.isBaseUrlInvalid
|
||||||
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()
|
val url = binding.urlView.text.toString().trim()
|
||||||
val login = binding.loginView.text.toString()
|
val login = binding.loginView.text.toString().trim()
|
||||||
val password = binding.passwordView.text.toString()
|
val password = binding.passwordView.text.toString().trim()
|
||||||
|
|
||||||
var cancel = false
|
var cancel = false
|
||||||
var focusView: View? = null
|
var focusView: View? = null
|
||||||
|
|
||||||
if (!url.isBaseUrlValid(this@LoginActivity)) {
|
if (url.isBaseUrlInvalid(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
|
||||||
|
@ -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> {
|
||||||
|
@ -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.isBaseUrlValid(ctx: Context): Boolean {
|
fun String.isBaseUrlInvalid(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.isBaseUrlValid(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) {
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
#!/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}
|
|
@ -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.2.2")
|
classpath("com.android.tools.build:gradle:7.3.0")
|
||||||
|
|
||||||
// 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")
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
git fetch --tags -p
|
git fetch --tags -p
|
||||||
|
|
||||||
BASE_VERSION="1.7"
|
BASE_VERSION="1"
|
||||||
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
|
@ -1,3 +1 @@
|
|||||||
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.
|
|
||||||
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -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.3.3-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
15
publish-version.sh
Executable file
15
publish-version.sh
Executable file
@ -0,0 +1,15 @@
|
|||||||
|
#!/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
|
@ -114,6 +114,7 @@ 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 {
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest package="bou.amine.apps.readerforselfossv2" />
|
<manifest />
|
@ -105,4 +105,16 @@ 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -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: List<SelfossModel.Item>? = null
|
var fetchedItems: SelfossModel.StatusAndData<List<SelfossModel.Item>> = SelfossModel.StatusAndData.error()
|
||||||
if (isNetworkAvailable()) {
|
if (isNetworkAvailable()) {
|
||||||
fetchedItems = api.getItems(
|
fetchedItems = api.getItems(
|
||||||
displayedItems.type,
|
displayedItems.type,
|
||||||
@ -60,23 +60,25 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
|
|||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
if (appSettingsService.isItemCachingEnabled()) {
|
if (appSettingsService.isItemCachingEnabled()) {
|
||||||
fetchedItems = getDBItems().filter {
|
fetchedItems = SelfossModel.StatusAndData.succes(
|
||||||
displayedItems == ItemType.ALL ||
|
getDBItems().filter {
|
||||||
(it.unread && displayedItems == ItemType.UNREAD) ||
|
displayedItems == ItemType.ALL ||
|
||||||
(it.starred && displayedItems == ItemType.STARRED)
|
(it.unread && displayedItems == ItemType.UNREAD) ||
|
||||||
}.map { it.toView() }
|
(it.starred && displayedItems == ItemType.STARRED)
|
||||||
|
}.map { it.toView() }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fetchedItems != null) {
|
if (fetchedItems.success && fetchedItems.data != null) {
|
||||||
items = ArrayList(fetchedItems)
|
items = ArrayList(fetchedItems.data!!)
|
||||||
sortItems()
|
sortItems()
|
||||||
}
|
}
|
||||||
return items
|
return items
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getOlderItems(): ArrayList<SelfossModel.Item> {
|
suspend fun getOlderItems(): ArrayList<SelfossModel.Item> {
|
||||||
var fetchedItems: List<SelfossModel.Item>? = null
|
var fetchedItems: SelfossModel.StatusAndData<List<SelfossModel.Item>> = SelfossModel.StatusAndData.error()
|
||||||
if (isNetworkAvailable()) {
|
if (isNetworkAvailable()) {
|
||||||
val offset = items.size
|
val offset = items.size
|
||||||
fetchedItems = api.getItems(
|
fetchedItems = api.getItems(
|
||||||
@ -89,16 +91,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 != null) {
|
if (fetchedItems.success && fetchedItems.data != null) {
|
||||||
items.addAll(fetchedItems)
|
items.addAll(fetchedItems.data!!)
|
||||||
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()) {
|
||||||
api.getItems(
|
val items = api.getItems(
|
||||||
itemType.type,
|
itemType.type,
|
||||||
0,
|
0,
|
||||||
tagFilter?.tag,
|
tagFilter?.tag,
|
||||||
@ -107,6 +109,11 @@ 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()
|
||||||
}
|
}
|
||||||
@ -120,10 +127,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 != null) {
|
if (response.success && response.data != null) {
|
||||||
badgeUnread = response.unread
|
badgeUnread = response.data.unread
|
||||||
badgeAll = response.total
|
badgeAll = response.data.total
|
||||||
badgeStarred = response.starred
|
badgeStarred = response.data.starred
|
||||||
success = true
|
success = true
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -139,10 +146,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 != null && (appSettingsService.isItemCachingEnabled() || !appSettingsService.isUpdateSourcesEnabled())) {
|
if (apiTags.success && apiTags.data != null && (appSettingsService.isItemCachingEnabled() || !appSettingsService.isUpdateSourcesEnabled())) {
|
||||||
resetDBTagsWithData(apiTags)
|
resetDBTagsWithData(apiTags.data)
|
||||||
}
|
}
|
||||||
apiTags
|
apiTags.data
|
||||||
} else {
|
} else {
|
||||||
getDBTags().map { it.toView() }
|
getDBTags().map { it.toView() }
|
||||||
}
|
}
|
||||||
@ -151,7 +158,12 @@ 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()) {
|
||||||
api.spouts()
|
val spouts = api.spouts()
|
||||||
|
return if (spouts.success && spouts.data != null) {
|
||||||
|
spouts.data
|
||||||
|
} else {
|
||||||
|
emptyMap() // TODO: do something here
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
throw NetworkUnavailableException()
|
throw NetworkUnavailableException()
|
||||||
}
|
}
|
||||||
@ -160,10 +172,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 != null && (appSettingsService.isItemCachingEnabled() || !appSettingsService.isUpdateSourcesEnabled())) {
|
if (apiSources.success && apiSources.data != null && (appSettingsService.isItemCachingEnabled() || !appSettingsService.isUpdateSourcesEnabled())) {
|
||||||
resetDBSourcesWithData(apiSources)
|
resetDBSourcesWithData(apiSources.data)
|
||||||
}
|
}
|
||||||
apiSources
|
apiSources.data
|
||||||
} else {
|
} else {
|
||||||
ArrayList(getDBSources().map { it.toView() })
|
ArrayList(getDBSources().map { it.toView() })
|
||||||
}
|
}
|
||||||
@ -180,7 +192,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 == true
|
api.markAsRead(id.toString())?.isSuccess
|
||||||
} else {
|
} else {
|
||||||
insertDBAction(id.toString(), read = true)
|
insertDBAction(id.toString(), read = true)
|
||||||
true
|
true
|
||||||
@ -199,7 +211,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 == true
|
api.unmarkAsRead(id.toString())?.isSuccess
|
||||||
} else {
|
} else {
|
||||||
insertDBAction(id.toString(), unread = true)
|
insertDBAction(id.toString(), unread = true)
|
||||||
true
|
true
|
||||||
@ -217,7 +229,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 == true
|
api.starr(id.toString())?.isSuccess
|
||||||
} else {
|
} else {
|
||||||
insertDBAction(id.toString(), starred = true)
|
insertDBAction(id.toString(), starred = true)
|
||||||
true
|
true
|
||||||
@ -235,7 +247,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 == true
|
api.unstarr(id.toString())?.isSuccess
|
||||||
} else {
|
} else {
|
||||||
insertDBAction(id.toString(), starred = true)
|
insertDBAction(id.toString(), starred = true)
|
||||||
true
|
true
|
||||||
@ -245,7 +257,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 == true) {
|
if (isNetworkAvailable() && api.markAllAsRead(items.map { it.id.toString() })?.isSuccess) {
|
||||||
success = true
|
success = true
|
||||||
for (item in items) {
|
for (item in items) {
|
||||||
markAsReadLocally(item)
|
markAsReadLocally(item)
|
||||||
@ -334,7 +346,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") ?: false
|
api.update()?.equals("finished")
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
@ -367,8 +379,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 != null && fetchedVersion.getApiMajorVersion() != apiMajorVersion) {
|
if (fetchedVersion.success && fetchedVersion.data != null && fetchedVersion.data.getApiMajorVersion() != apiMajorVersion) {
|
||||||
appSettingsService.updateApiVersion(fetchedVersion.getApiMajorVersion())
|
appSettingsService.updateApiVersion(fetchedVersion.data.getApiMajorVersion())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -429,7 +441,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.orEmpty() + allItems.orEmpty() + starredItems.orEmpty())
|
insertDBItems(newItems + allItems + starredItems)
|
||||||
return newItems
|
return newItems
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
// We do nothing
|
// We do nothing
|
||||||
|
@ -10,6 +10,7 @@ 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
|
||||||
@ -34,7 +35,7 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
|
|||||||
appSettingsService.logApiCalls(message)
|
appSettingsService.logApiCalls(message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
level = LogLevel.ALL
|
level = LogLevel.INFO
|
||||||
}
|
}
|
||||||
install(HttpTimeout) {
|
install(HttpTimeout) {
|
||||||
requestTimeoutMillis = appSettingsService.getApiTimeout()
|
requestTimeoutMillis = appSettingsService.getApiTimeout()
|
||||||
@ -65,11 +66,11 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
|
|||||||
client = createHttpClient()
|
client = createHttpClient()
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun login(): SelfossModel.SuccessResponse? =
|
suspend fun login(): SelfossModel.SuccessResponse =
|
||||||
client.get(url("/login")) {
|
maybeResponse(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,
|
||||||
@ -79,8 +80,8 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
|
|||||||
search: String?,
|
search: String?,
|
||||||
updatedSince: String?,
|
updatedSince: String?,
|
||||||
items: Int? = null
|
items: Int? = null
|
||||||
): List<SelfossModel.Item>? =
|
): SelfossModel.StatusAndData<List<SelfossModel.Item>> =
|
||||||
client.get(url("/items")) {
|
bodyOrFailure(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)
|
||||||
@ -90,74 +91,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.Stats? =
|
suspend fun stats(): SelfossModel.StatusAndData<SelfossModel.Stats> =
|
||||||
client.get(url("/stats")) {
|
bodyOrFailure(client.get(url("/stats")) {
|
||||||
parameter("username", appSettingsService.getUserName())
|
parameter("username", appSettingsService.getUserName())
|
||||||
parameter("password", appSettingsService.getPassword())
|
parameter("password", appSettingsService.getPassword())
|
||||||
}.body()
|
})
|
||||||
|
|
||||||
suspend fun tags(): List<SelfossModel.Tag>? =
|
suspend fun tags(): SelfossModel.StatusAndData<List<SelfossModel.Tag>> =
|
||||||
client.get(url("/tags")) {
|
bodyOrFailure(client.get(url("/tags")) {
|
||||||
parameter("username", appSettingsService.getUserName())
|
parameter("username", appSettingsService.getUserName())
|
||||||
parameter("password", appSettingsService.getPassword())
|
parameter("password", appSettingsService.getPassword())
|
||||||
}.body()
|
})
|
||||||
|
|
||||||
suspend fun update(): String? =
|
suspend fun update(): SelfossModel.StatusAndData<String> =
|
||||||
client.get(url("/update")) {
|
bodyOrFailure(client.get(url("/update")) {
|
||||||
parameter("username", appSettingsService.getUserName())
|
parameter("username", appSettingsService.getUserName())
|
||||||
parameter("password", appSettingsService.getPassword())
|
parameter("password", appSettingsService.getPassword())
|
||||||
}.body()
|
})
|
||||||
|
|
||||||
suspend fun spouts(): Map<String, SelfossModel.Spout>? =
|
suspend fun spouts(): SelfossModel.StatusAndData<Map<String, SelfossModel.Spout>> =
|
||||||
client.get(url("/sources/spouts")) {
|
bodyOrFailure(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(): ArrayList<SelfossModel.Source>? =
|
suspend fun sources(): SelfossModel.StatusAndData<ArrayList<SelfossModel.Source>> =
|
||||||
client.get(url("/sources/list")) {
|
bodyOrFailure(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.ApiVersion? =
|
suspend fun version(): SelfossModel.StatusAndData<SelfossModel.ApiVersion> =
|
||||||
client.get(url("/api/about")).body()
|
bodyOrFailure(client.get(url("/api/about")))
|
||||||
|
|
||||||
suspend fun markAsRead(id: String): SelfossModel.SuccessResponse? =
|
suspend fun markAsRead(id: String): SelfossModel.SuccessResponse =
|
||||||
client.post(url("/mark/$id")) {
|
maybeResponse(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 =
|
||||||
client.post(url("/unmark/$id")) {
|
maybeResponse(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 =
|
||||||
client.post(url("/starr/$id")) {
|
maybeResponse(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 =
|
||||||
client.post(url("/unstarr/$id")) {
|
maybeResponse(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 =
|
||||||
client.submitForm(
|
maybeResponse(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,
|
||||||
@ -166,12 +167,14 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
|
|||||||
tags: String,
|
tags: String,
|
||||||
filter: String,
|
filter: String,
|
||||||
version: Int
|
version: Int
|
||||||
): SelfossModel.SuccessResponse? =
|
): SelfossModel.SuccessResponse =
|
||||||
if (version > 1) {
|
maybeResponse(
|
||||||
createSource2(title, url, spout, tags, filter)
|
if (version > 1) {
|
||||||
} else {
|
createSource2(title, url, spout, tags, filter)
|
||||||
createSource(title, url, spout, tags, filter)
|
} else {
|
||||||
}
|
createSource(title, url, spout, tags, filter)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
suspend fun createSource(
|
suspend fun createSource(
|
||||||
title: String,
|
title: String,
|
||||||
@ -179,7 +182,7 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
|
|||||||
spout: String,
|
spout: String,
|
||||||
tags: String,
|
tags: String,
|
||||||
filter: String
|
filter: String
|
||||||
): SelfossModel.SuccessResponse? =
|
): HttpResponse =
|
||||||
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 {
|
||||||
@ -189,7 +192,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,
|
||||||
@ -197,7 +200,7 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
|
|||||||
spout: String,
|
spout: String,
|
||||||
tags: String,
|
tags: String,
|
||||||
filter: String
|
filter: String
|
||||||
): SelfossModel.SuccessResponse? =
|
): HttpResponse =
|
||||||
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 {
|
||||||
@ -207,11 +210,27 @@ 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 =
|
||||||
client.delete(url("/source/$id")) {
|
maybeResponse(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()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
14
version.sh
Executable file
14
version.sh
Executable file
@ -0,0 +1,14 @@
|
|||||||
|
#!/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
|
Loading…
Reference in New Issue
Block a user