Compare commits
	
		
			11 Commits
		
	
	
		
			v125051211
			...
			0aac2cba0b
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 0aac2cba0b | |||
| 42e1c1ebbd | |||
| a67a2a0927 | |||
| 24beee070c | |||
| 1e6bc57751 | |||
| 85d966f54b | |||
| 3fff8eeeb6 | |||
| 5eb5a5658f | |||
| 3646658cb1 | |||
| b793301706 | |||
| 313042955c | 
| @@ -8,7 +8,7 @@ plugins { | ||||
|     kotlin("android") | ||||
|     kotlin("kapt") | ||||
|     id("com.mikepenz.aboutlibraries.plugin") | ||||
|     id("org.jetbrains.kotlinx.kover") version "0.6.1" | ||||
|     id("org.jetbrains.kotlinx.kover") | ||||
| } | ||||
|  | ||||
| fun Project.execWithOutput(cmd: String, ignore: Boolean = false): String { | ||||
| @@ -16,7 +16,7 @@ fun Project.execWithOutput(cmd: String, ignore: Boolean = false): String { | ||||
|         project.exec { | ||||
|             commandLine = cmd.split(" ") | ||||
|             standardOutput = outputStream | ||||
|             isIgnoreExitValue = ignore ?: false | ||||
|             isIgnoreExitValue = ignore | ||||
|         } | ||||
|         outputStream.toString() | ||||
|     } | ||||
| @@ -24,9 +24,8 @@ fun Project.execWithOutput(cmd: String, ignore: Boolean = false): String { | ||||
| } | ||||
|  | ||||
| fun gitVersion(): String { | ||||
|     var process = "" | ||||
|     val maybeTagOfCurrentCommit = execWithOutput("git -C ../ describe --contains HEAD", true) | ||||
|     process = if (maybeTagOfCurrentCommit.isEmpty()) { | ||||
|     var process = if (maybeTagOfCurrentCommit.isEmpty()) { | ||||
|         println("No tag on current commit. Will take the latest one.") | ||||
|         execWithOutput("git -C ../ for-each-ref refs/tags --sort=-refname --format='%(refname:short)' --count=1") | ||||
|     } else { | ||||
| @@ -171,7 +170,7 @@ dependencies { | ||||
|     //PhotoView | ||||
|     implementation("com.github.chrisbanes:PhotoView:2.3.0") | ||||
|  | ||||
|     implementation("androidx.core:core-ktx:1.8.0") | ||||
|     implementation("androidx.core:core-ktx:1.10.1") | ||||
|  | ||||
|     implementation("androidx.lifecycle:lifecycle-extensions:2.2.0") | ||||
|  | ||||
|   | ||||
							
								
								
									
										1
									
								
								androidApp/proguard-rules.pro
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								androidApp/proguard-rules.pro
									
									
									
									
										vendored
									
									
								
							| @@ -55,6 +55,7 @@ | ||||
| # maybe remove later ? | ||||
| -keep class * extends androidx.fragment.app.Fragment | ||||
|  | ||||
| -dontwarn org.slf4j.impl.StaticLoggerBinder | ||||
|  | ||||
| # Keep `Companion` object fields of serializable classes. | ||||
| # This avoids serializer lookup through `getDeclaredClasses` as done for named companion objects. | ||||
|   | ||||
| @@ -139,9 +139,12 @@ class LoginActivity : AppCompatActivity(), DIAware { | ||||
|  | ||||
|         showProgress(true) | ||||
|  | ||||
|         appSettingsService.updateSelfSigned(binding.selfSigned.isChecked) | ||||
|  | ||||
|         repository.refreshLoginInformation(url, login, password) | ||||
|  | ||||
|         CoroutineScope(Dispatchers.Main).launch { | ||||
|             repository.updateApiInformation() | ||||
|             val result = repository.login() | ||||
|             if (result) { | ||||
|                 val (errorFetching, displaySelfossOnly) = repository.shouldBeSelfossInstance() | ||||
|   | ||||
| @@ -82,7 +82,7 @@ class FilterSheetFragment : BottomSheetDialogFragment(), DIAware { | ||||
|     ) { | ||||
|         val sourceGroup = binding.sourcesGroup | ||||
|  | ||||
|         repository.getSourcesDetailsOrStats().forEach { source -> | ||||
|         repository.getSourcesDetailsOrStats().forEachIndexed { _, source -> | ||||
|             val c = Chip(context) | ||||
|             c.ellipsize = TextUtils.TruncateAt.END | ||||
|  | ||||
| @@ -144,7 +144,7 @@ class FilterSheetFragment : BottomSheetDialogFragment(), DIAware { | ||||
|  | ||||
|         val tags = repository.getTags() | ||||
|  | ||||
|         tags.forEach { tag -> | ||||
|         tags.forEachIndexed { _, tag -> | ||||
|             val c = Chip(context) | ||||
|             c.ellipsize = TextUtils.TruncateAt.END | ||||
|             c.text = tag.tag | ||||
|   | ||||
| @@ -55,7 +55,7 @@ | ||||
|                 android:id="@+id/selfSigned" | ||||
|                 android:layout_width="match_parent" | ||||
|                 android:layout_height="wrap_content" | ||||
|                 android:text="@string/disableSSL" | ||||
|                 android:text="@string/disable_ssl" | ||||
|                 android:textAlignment="viewStart" /> | ||||
|  | ||||
|             <com.google.android.material.switchmaterial.SwitchMaterial | ||||
|   | ||||
| @@ -130,4 +130,5 @@ | ||||
|     <string name="update_source">Update source</string> | ||||
|     <string name="confirm_disconnect_title">Disconnect ?</string> | ||||
|     <string name="confirm_disconnect_description">You will be disconnected from your selfoss instance.</string> | ||||
|     <string name="disable_ssl">Disable SSL</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -130,4 +130,5 @@ | ||||
|     <string name="update_source">Update source</string> | ||||
|     <string name="confirm_disconnect_title">Disconnect ?</string> | ||||
|     <string name="confirm_disconnect_description">You will be disconnected from your selfoss instance.</string> | ||||
|     <string name="disable_ssl">Disable SSL</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -130,4 +130,5 @@ | ||||
|     <string name="update_source">Update source</string> | ||||
|     <string name="confirm_disconnect_title">Disconnect ?</string> | ||||
|     <string name="confirm_disconnect_description">You will be disconnected from your selfoss instance.</string> | ||||
|     <string name="disable_ssl">Disable SSL</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -130,4 +130,5 @@ | ||||
|     <string name="update_source">Update source</string> | ||||
|     <string name="confirm_disconnect_title">Disconnect ?</string> | ||||
|     <string name="confirm_disconnect_description">You will be disconnected from your selfoss instance.</string> | ||||
|     <string name="disable_ssl">Disable SSL</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -130,4 +130,5 @@ | ||||
|     <string name="update_source">Update source</string> | ||||
|     <string name="confirm_disconnect_title">Disconnect ?</string> | ||||
|     <string name="confirm_disconnect_description">You will be disconnected from your selfoss instance.</string> | ||||
|     <string name="disable_ssl">Disable SSL</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -130,4 +130,5 @@ | ||||
|     <string name="update_source">Update source</string> | ||||
|     <string name="confirm_disconnect_title">Disconnect ?</string> | ||||
|     <string name="confirm_disconnect_description">You will be disconnected from your selfoss instance.</string> | ||||
|     <string name="disable_ssl">Disable SSL</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -130,4 +130,5 @@ | ||||
|     <string name="update_source">Update source</string> | ||||
|     <string name="confirm_disconnect_title">Disconnect ?</string> | ||||
|     <string name="confirm_disconnect_description">You will be disconnected from your selfoss instance.</string> | ||||
|     <string name="disable_ssl">Disable SSL</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <resources xmlns:tools="http://schemas.android.com/tools"> | ||||
| <resources> | ||||
|     <string name="app_name">"Lettore RSS per Selfoss"</string> | ||||
|     <string name="title_activity_login">"Accedi"</string> | ||||
|     <string name="prompt_password">"Password"</string> | ||||
| @@ -130,4 +130,5 @@ | ||||
|     <string name="update_source">Update source</string> | ||||
|     <string name="confirm_disconnect_title">Disconnect ?</string> | ||||
|     <string name="confirm_disconnect_description">You will be disconnected from your selfoss instance.</string> | ||||
|     <string name="disable_ssl">Disable SSL</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -130,4 +130,5 @@ | ||||
|     <string name="update_source">Update source</string> | ||||
|     <string name="confirm_disconnect_title">Disconnect ?</string> | ||||
|     <string name="confirm_disconnect_description">You will be disconnected from your selfoss instance.</string> | ||||
|     <string name="disable_ssl">Disable SSL</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <resources> | ||||
| <resources xmlns:tools="http://schemas.android.com/tools"> | ||||
|     <string name="gdpr_dialog_title">The app does not share any personal data about you.</string> | ||||
|     <string name="gdpr_dialog_message"><![CDATA[Crash reports sending is now enabled. It can be disabled from the settings page. Keep in mind that crash reports are essential for the app development.]]></string> | ||||
|     <string name="crash_toast_text">A crash occured. Sending the details to the developper.</string> | ||||
|   | ||||
| @@ -130,4 +130,5 @@ | ||||
|     <string name="update_source">Update source</string> | ||||
|     <string name="confirm_disconnect_title">Disconnect ?</string> | ||||
|     <string name="confirm_disconnect_description">You will be disconnected from your selfoss instance.</string> | ||||
|     <string name="disable_ssl">Disable SSL</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -130,4 +130,5 @@ | ||||
|     <string name="update_source">Update source</string> | ||||
|     <string name="confirm_disconnect_title">Disconnect ?</string> | ||||
|     <string name="confirm_disconnect_description">You will be disconnected from your selfoss instance.</string> | ||||
|     <string name="disable_ssl">Disable SSL</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -130,4 +130,5 @@ | ||||
|     <string name="update_source">Update source</string> | ||||
|     <string name="confirm_disconnect_title">Disconnect ?</string> | ||||
|     <string name="confirm_disconnect_description">You will be disconnected from your selfoss instance.</string> | ||||
|     <string name="disable_ssl">Disable SSL</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -130,4 +130,5 @@ | ||||
|     <string name="update_source">Update source</string> | ||||
|     <string name="confirm_disconnect_title">Disconnect ?</string> | ||||
|     <string name="confirm_disconnect_description">You will be disconnected from your selfoss instance.</string> | ||||
|     <string name="disable_ssl">Disable SSL</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -130,4 +130,5 @@ | ||||
|     <string name="update_source">Update source</string> | ||||
|     <string name="confirm_disconnect_title">Disconnect ?</string> | ||||
|     <string name="confirm_disconnect_description">You will be disconnected from your selfoss instance.</string> | ||||
|     <string name="disable_ssl">Disable SSL</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -130,4 +130,5 @@ | ||||
|     <string name="update_source">更新源</string> | ||||
|     <string name="confirm_disconnect_title">Disconnect ?</string> | ||||
|     <string name="confirm_disconnect_description">You will be disconnected from your selfoss instance.</string> | ||||
|     <string name="disable_ssl">Disable SSL</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -130,4 +130,5 @@ | ||||
|     <string name="update_source">Update source</string> | ||||
|     <string name="confirm_disconnect_title">Disconnect ?</string> | ||||
|     <string name="confirm_disconnect_description">You will be disconnected from your selfoss instance.</string> | ||||
|     <string name="disable_ssl">Disable SSL</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| <resources> | ||||
| <resources xmlns:tools="http://schemas.android.com/tools"> | ||||
|     <string name="app_name">"Reader for Selfoss"</string> | ||||
|     <string name="title_activity_login">"Log in"</string> | ||||
|     <string name="prompt_password">"Password"</string> | ||||
| @@ -6,7 +6,7 @@ | ||||
|     <string name="error_invalid_password">"Password not long enough"</string> | ||||
|     <string name="error_field_required">"Field required"</string> | ||||
|     <string name="prompt_url">"Url"</string> | ||||
|     <string name="disableSSL">"Disable SSL"</string> | ||||
|     <string name="disable_ssl">"Disable SSL"</string> | ||||
|     <string name="withLoginSwitch">"Login required ?"</string> | ||||
|     <string name="login_url_problem">"Oops. You may need to add a \"/\" at the end of the url."</string> | ||||
|     <string name="prompt_login">"Username"</string> | ||||
|   | ||||
| @@ -7,12 +7,12 @@ buildscript { | ||||
|  | ||||
| plugins { | ||||
|     //trick: for the same plugin versions in all sub-modules | ||||
|     id("com.android.application").version("7.4.0").apply(false) | ||||
|     id("com.android.library").version("7.4.0").apply(false) | ||||
|     kotlin("android").version("1.7.20").apply(false) | ||||
|     kotlin("multiplatform").version("1.7.20").apply(false) | ||||
|     id("com.android.application").version("8.1.0").apply(false) | ||||
|     id("com.android.library").version("8.1.0").apply(false) | ||||
|     id("org.jetbrains.kotlin.android").version("1.9.10").apply(false) | ||||
|     kotlin("multiplatform").version("1.9.10").apply(false) | ||||
|     id("com.mikepenz.aboutlibraries.plugin").version("10.5.1").apply(false) | ||||
|     id("org.jetbrains.kotlinx.kover") version "0.6.1" | ||||
|     id("org.jetbrains.kotlinx.kover").version("0.6.1").apply(true) | ||||
| } | ||||
|  | ||||
| allprojects { | ||||
|   | ||||
| @@ -13,22 +13,15 @@ | ||||
| #Tue Mar 22 16:50:00 CET 2022 | ||||
| #Gradle | ||||
| org.gradle.jvmargs=-Xmx2048M -Dfile.encoding=UTF-8 -Dkotlin.daemon.jvm.options\="-Xmx2048M" | ||||
|  | ||||
| #Kotlin | ||||
| kotlin.code.style=official | ||||
|  | ||||
| #Android | ||||
| android.useAndroidX=true | ||||
| kotlin.native.enableDependencyPropagation=false | ||||
| #android.nonTransitiveRClass=true | ||||
| android.enableJetifier=true | ||||
|  | ||||
|  | ||||
| android.nonTransitiveRClass=false | ||||
| #MPP | ||||
| kotlin.mpp.enableCInteropCommonization=true | ||||
| kotlin.mpp.enableGranularSourceSetsMetadata=true | ||||
|  | ||||
|  | ||||
| org.gradle.parallel=true | ||||
| org.gradle.caching=true | ||||
| ignoreGitVersion=false | ||||
|   | ||||
							
								
								
									
										6
									
								
								gradle/wrapper/gradle-wrapper.properties
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								gradle/wrapper/gradle-wrapper.properties
									
									
									
									
										vendored
									
									
								
							| @@ -1,6 +1,6 @@ | ||||
| #Mon Jan 23 20:47:46 CET 2023 | ||||
| #Thu Jul 13 11:41:19 CEST 2023 | ||||
| distributionBase=GRADLE_USER_HOME | ||||
| distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip | ||||
| distributionPath=wrapper/dists | ||||
| zipStorePath=wrapper/dists | ||||
| distributionUrl=https\://services.gradle.org/distributions/gradle-8.1-bin.zip | ||||
| zipStoreBase=GRADLE_USER_HOME | ||||
| zipStorePath=wrapper/dists | ||||
|   | ||||
| @@ -1,3 +1,5 @@ | ||||
| val ktorVersion = "2.3.2" | ||||
|  | ||||
| object SqlDelight { | ||||
|     const val runtime = "com.squareup.sqldelight:runtime:1.5.4" | ||||
|     const val android = "com.squareup.sqldelight:android-driver:1.5.4" | ||||
| @@ -9,12 +11,13 @@ plugins { | ||||
|     kotlin("multiplatform") | ||||
|     id("com.android.library") | ||||
|     id("com.squareup.sqldelight") | ||||
|     kotlin("plugin.serialization") version "1.4.10" | ||||
|     id("org.jetbrains.kotlinx.kover") version "0.6.1" | ||||
|     kotlin("plugin.serialization") version "1.9.0" | ||||
|     id("org.jetbrains.kotlinx.kover") | ||||
| } | ||||
|  | ||||
| kotlin { | ||||
|     android() | ||||
|     androidTarget() | ||||
|     jvmToolchain(11) | ||||
|  | ||||
|     listOf( | ||||
|         iosX64(), | ||||
| @@ -29,12 +32,14 @@ kotlin { | ||||
|     sourceSets { | ||||
|         val commonMain by getting { | ||||
|             dependencies { | ||||
|                 implementation("io.ktor:ktor-client-core:2.2.4") | ||||
|                 implementation("io.ktor:ktor-client-content-negotiation:2.2.4") | ||||
|                 implementation("io.ktor:ktor-serialization-kotlinx-json:2.2.4") | ||||
|                 implementation("io.ktor:ktor-client-logging:2.2.4") | ||||
|                 implementation("io.ktor:ktor-client-core:$ktorVersion") | ||||
|                 implementation("io.ktor:ktor-client-content-negotiation:$ktorVersion") | ||||
|                 implementation("io.ktor:ktor-serialization-kotlinx-json:$ktorVersion") | ||||
|                 implementation("io.ktor:ktor-client-logging:$ktorVersion") | ||||
|                 implementation("io.ktor:ktor-client-auth:$ktorVersion") | ||||
|                 implementation("io.ktor:ktor-client-cio:$ktorVersion") | ||||
|                 implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0") | ||||
|                 implementation("io.ktor:ktor-client-auth:2.2.4") | ||||
|  | ||||
|                 implementation("org.jsoup:jsoup:1.15.4") | ||||
|  | ||||
|                 //Dependency Injection | ||||
| @@ -58,15 +63,14 @@ kotlin { | ||||
|         } | ||||
|         val androidMain by getting { | ||||
|             dependencies { | ||||
|                 implementation("com.squareup.okhttp3:okhttp:4.10.0") | ||||
|                 implementation("io.ktor:ktor-client-okhttp:2.2.4") | ||||
|                 implementation("com.squareup.okhttp3:okhttp:4.11.0") | ||||
|                 implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.4.0") | ||||
|  | ||||
|                 // Sql | ||||
|                 implementation(SqlDelight.android) | ||||
|             } | ||||
|         } | ||||
|         val androidTest by getting { | ||||
|         val androidUnitTest by getting { | ||||
|             dependencies { | ||||
|                 implementation(kotlin("test-junit")) | ||||
|                 implementation("junit:junit:4.13.2") | ||||
| @@ -99,15 +103,14 @@ kotlin { | ||||
| } | ||||
|  | ||||
| android { | ||||
|     compileSdk = 32 | ||||
|     compileSdk = 33 | ||||
|     sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml") | ||||
|     defaultConfig { | ||||
|         minSdk = 21 | ||||
|         targetSdk = 32 | ||||
|     } | ||||
|     compileOptions { | ||||
|         sourceCompatibility = JavaVersion.VERSION_1_8 | ||||
|         targetCompatibility = JavaVersion.VERSION_1_8 | ||||
|         sourceCompatibility = JavaVersion.VERSION_11 | ||||
|         targetCompatibility = JavaVersion.VERSION_11 | ||||
|     } | ||||
|     namespace = "bou.amine.apps.readerforselfossv2" | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,17 @@ | ||||
| package bou.amine.apps.readerforselfossv2.rest | ||||
|  | ||||
| import io.ktor.client.engine.cio.CIOEngineConfig | ||||
| import java.security.cert.X509Certificate | ||||
| import javax.net.ssl.X509TrustManager | ||||
|  | ||||
| class NaiveTrustManager : X509TrustManager { | ||||
|     override fun checkClientTrusted(chain: Array<out X509Certificate>?, authType: String?) {} | ||||
|  | ||||
|     override fun checkServerTrusted(chain: Array<out X509Certificate>?, authType: String?) {} | ||||
|  | ||||
|     override fun getAcceptedIssuers(): Array<out X509Certificate> = arrayOf() | ||||
| } | ||||
|  | ||||
| actual fun setupInsecureHTTPEngine(config: CIOEngineConfig) { | ||||
|     config.https.trustManager = NaiveTrustManager() | ||||
| } | ||||
| @@ -1,82 +0,0 @@ | ||||
| package bou.amine.apps.readerforselfossv2.rest | ||||
|  | ||||
| import bou.amine.apps.readerforselfossv2.service.AppSettingsService | ||||
| import io.github.aakira.napier.Napier | ||||
| import io.ktor.client.* | ||||
| import io.ktor.client.engine.okhttp.* | ||||
| import io.ktor.client.plugins.* | ||||
| import io.ktor.client.plugins.cache.* | ||||
| import io.ktor.client.plugins.contentnegotiation.* | ||||
| import io.ktor.client.plugins.cookies.* | ||||
| import io.ktor.client.plugins.logging.* | ||||
| import io.ktor.http.* | ||||
| import io.ktor.serialization.kotlinx.json.* | ||||
| import kotlinx.coroutines.CoroutineScope | ||||
| import kotlinx.coroutines.Dispatchers | ||||
| import kotlinx.coroutines.launch | ||||
| import kotlinx.serialization.json.Json | ||||
| import okhttp3.OkHttpClient | ||||
| import org.apache.http.conn.ssl.AllowAllHostnameVerifier | ||||
| import java.security.cert.X509Certificate | ||||
| import javax.net.ssl.SSLContext | ||||
| import javax.net.ssl.X509TrustManager | ||||
|  | ||||
| class NaiveTrustManager : X509TrustManager { | ||||
|     override fun checkClientTrusted(chain: Array<out X509Certificate>?, authType: String?) {} | ||||
|  | ||||
|     override fun checkServerTrusted(chain: Array<out X509Certificate>?, authType: String?) {} | ||||
|  | ||||
|     override fun getAcceptedIssuers(): Array<out X509Certificate> = arrayOf() | ||||
| } | ||||
|  | ||||
| actual fun createHttpClient(appSettingsService: AppSettingsService, api: SelfossApi) = | ||||
|     HttpClient(OkHttp) { | ||||
|         engine { | ||||
|             val trustManager = NaiveTrustManager() | ||||
|             val sslContext = SSLContext.getInstance("TLS").apply { | ||||
|                 init(null, arrayOf(trustManager), null) | ||||
|             } | ||||
|             preconfigured = OkHttpClient().newBuilder() | ||||
|                 .sslSocketFactory( | ||||
|                     sslSocketFactory = sslContext.socketFactory, | ||||
|                     trustManager = trustManager | ||||
|                 ) | ||||
|                 .hostnameVerifier(AllowAllHostnameVerifier()) | ||||
|                 .build() | ||||
|         } | ||||
|         install(ContentNegotiation) { | ||||
|             install(HttpCache) | ||||
|             json(Json { | ||||
|                 prettyPrint = true | ||||
|                 isLenient = true | ||||
|                 ignoreUnknownKeys = true | ||||
|             }) | ||||
|         } | ||||
|         install(Logging) { | ||||
|             logger = object : Logger { | ||||
|                 override fun log(message: String) { | ||||
|                     Napier.d(message, tag = "LogApiCalls") | ||||
|                 } | ||||
|             } | ||||
|             level = LogLevel.INFO | ||||
|         } | ||||
|         install(HttpTimeout) { | ||||
|             requestTimeoutMillis = appSettingsService.getApiTimeout() | ||||
|         } | ||||
|         install(HttpCookies) | ||||
|         install(HttpRequestRetry) { | ||||
|             maxRetries = 2 | ||||
|             retryIf { _, response -> | ||||
|                 response.status == HttpStatusCode.Forbidden && api.shouldHavePostLogin() && api.hasLoginInfo() | ||||
|             } | ||||
|             modifyRequest { | ||||
|                 Napier.i("Will modify", tag = "HttpSend") | ||||
|                 CoroutineScope(Dispatchers.Main).launch { | ||||
|                     Napier.i("Will login", tag = "HttpSend") | ||||
|                     api.login() | ||||
|                     Napier.i("Did login", tag = "HttpSend") | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         expectSuccess = false | ||||
|     } | ||||
| @@ -4,12 +4,83 @@ import bou.amine.apps.readerforselfossv2.model.SelfossModel | ||||
| import bou.amine.apps.readerforselfossv2.model.StatusAndData | ||||
| import bou.amine.apps.readerforselfossv2.model.SuccessResponse | ||||
| import bou.amine.apps.readerforselfossv2.service.AppSettingsService | ||||
| import io.ktor.client.* | ||||
| import io.ktor.client.request.* | ||||
| import io.ktor.client.statement.* | ||||
| import io.ktor.http.* | ||||
| import io.github.aakira.napier.Napier | ||||
| import io.ktor.client.HttpClient | ||||
| import io.ktor.client.engine.cio.CIO | ||||
| import io.ktor.client.engine.cio.CIOEngineConfig | ||||
| import io.ktor.client.plugins.HttpRequestRetry | ||||
| import io.ktor.client.plugins.HttpTimeout | ||||
| import io.ktor.client.plugins.auth.providers.BasicAuthCredentials | ||||
| import io.ktor.client.plugins.cache.HttpCache | ||||
| import io.ktor.client.plugins.contentnegotiation.ContentNegotiation | ||||
| import io.ktor.client.plugins.cookies.HttpCookies | ||||
| import io.ktor.client.plugins.logging.LogLevel | ||||
| import io.ktor.client.plugins.logging.Logger | ||||
| import io.ktor.client.plugins.logging.Logging | ||||
| import io.ktor.client.request.get | ||||
| import io.ktor.client.request.headers | ||||
| import io.ktor.client.request.parameter | ||||
| import io.ktor.client.statement.HttpResponse | ||||
| import io.ktor.http.HttpHeaders | ||||
| import io.ktor.http.HttpStatusCode | ||||
| import io.ktor.http.Parameters | ||||
| import io.ktor.serialization.kotlinx.json.json | ||||
| import io.ktor.util.encodeBase64 | ||||
| import io.ktor.utils.io.charsets.Charsets | ||||
| import io.ktor.utils.io.core.toByteArray | ||||
| import kotlinx.coroutines.CoroutineScope | ||||
| import kotlinx.coroutines.Dispatchers | ||||
| import kotlinx.coroutines.launch | ||||
| import kotlinx.serialization.json.Json | ||||
|  | ||||
| expect fun createHttpClient(appSettingsService: AppSettingsService, api: SelfossApi): HttpClient | ||||
| expect fun setupInsecureHTTPEngine(config: CIOEngineConfig) | ||||
|  | ||||
| fun createHttpClient( | ||||
|     appSettingsService: AppSettingsService, | ||||
|     api: SelfossApi | ||||
| ) = | ||||
|     HttpClient(CIO) { | ||||
|         if (appSettingsService.getSelfSigned()) { | ||||
|             engine { | ||||
|                 setupInsecureHTTPEngine(this) | ||||
|             } | ||||
|         } | ||||
|         install(ContentNegotiation) { | ||||
|             install(HttpCache) | ||||
|             json(Json { | ||||
|                 prettyPrint = true | ||||
|                 isLenient = true | ||||
|                 ignoreUnknownKeys = true | ||||
|             }) | ||||
|         } | ||||
|         install(Logging) { | ||||
|             logger = object : Logger { | ||||
|                 override fun log(message: String) { | ||||
|                     Napier.d(message, tag = "LogApiCalls") | ||||
|                 } | ||||
|             } | ||||
|             level = LogLevel.INFO | ||||
|         } | ||||
|         install(HttpTimeout) { | ||||
|             requestTimeoutMillis = appSettingsService.getApiTimeout() | ||||
|         } | ||||
|         install(HttpCookies) | ||||
|         install(HttpRequestRetry) { | ||||
|             maxRetries = 2 | ||||
|             retryIf { _, response -> | ||||
|                 response.status == HttpStatusCode.Forbidden && api.shouldHavePostLogin() && api.hasLoginInfo() | ||||
|             } | ||||
|             modifyRequest { | ||||
|                 Napier.i("Will modify", tag = "HttpSend") | ||||
|                 CoroutineScope(Dispatchers.Main).launch { | ||||
|                     Napier.i("Will login", tag = "HttpSend") | ||||
|                     api.login() | ||||
|                     Napier.i("Did login", tag = "HttpSend") | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         expectSuccess = false | ||||
|     } | ||||
|  | ||||
| class SelfossApi(private val appSettingsService: AppSettingsService) { | ||||
|  | ||||
|   | ||||
| @@ -8,6 +8,7 @@ class AppSettingsService(acraSenderServiceProcess: Boolean = false) { | ||||
|     // Api related | ||||
|     private var _apiVersion: Int = -1 | ||||
|     private var _publicAccess: Boolean? = null | ||||
|     private var _selfSigned: Boolean? = null | ||||
|     private var _baseUrl: String = "" | ||||
|     private var _userName: String = "" | ||||
|     private var _basicUserName: String = "" | ||||
| @@ -77,6 +78,22 @@ class AppSettingsService(acraSenderServiceProcess: Boolean = false) { | ||||
|         _publicAccess = settings.getBoolean(API_PUBLIC_ACCESS, false) | ||||
|     } | ||||
|  | ||||
|     fun getSelfSigned(): Boolean { | ||||
|         if (_selfSigned == null) { | ||||
|             refreshSelfSigned() | ||||
|         } | ||||
|         return _selfSigned!! | ||||
|     } | ||||
|  | ||||
|     fun updateSelfSigned(selfSigned: Boolean) { | ||||
|         settings.putBoolean(API_SELF_SIGNED, selfSigned) | ||||
|         refreshSelfSigned() | ||||
|     } | ||||
|  | ||||
|     private fun refreshSelfSigned() { | ||||
|         _selfSigned = settings.getBoolean(API_SELF_SIGNED, false) | ||||
|     } | ||||
|  | ||||
|     fun getBaseUrl(): String { | ||||
|         if (_baseUrl.isEmpty()) { | ||||
|             refreshBaseUrl() | ||||
| @@ -383,6 +400,7 @@ class AppSettingsService(acraSenderServiceProcess: Boolean = false) { | ||||
|         refreshBaseUrl() | ||||
|         refreshApiVersion() | ||||
|         refreshPublicAccess() | ||||
|         refreshSelfSigned() | ||||
|     } | ||||
|  | ||||
|     fun refreshUserSettings() { | ||||
| @@ -468,6 +486,8 @@ class AppSettingsService(acraSenderServiceProcess: Boolean = false) { | ||||
|  | ||||
|         const val API_PUBLIC_ACCESS = "apiPublicAccess" | ||||
|  | ||||
|         const val API_SELF_SIGNED = "apiSelfSigned" | ||||
|  | ||||
|         const val API_ITEMS_NUMBER = "prefer_api_items_number" | ||||
|  | ||||
|         const val API_TIMEOUT = "api_timeout" | ||||
|   | ||||
		Reference in New Issue
	
	Block a user