From 5d35e5f74e8d3cb130d20a50a60085ecd88ecedd Mon Sep 17 00:00:00 2001 From: grakovne Date: Tue, 12 Nov 2024 21:32:40 +0100 Subject: [PATCH 1/5] wip --- app/build.gradle.kts | 1 + .../common/api/AudiobookshelfAuthService.kt | 7 +-- .../converter/PodcastPageResponseConverter.kt | 2 +- .../lissen/channel/common/ApiClient.kt | 24 +++++++++- .../lissen/channel/common/BinaryApiClient.kt | 24 +++++++++- .../playback/service/PlaybackService.kt | 44 +++++++++++++++++-- gradle/libs.versions.toml | 2 + 7 files changed, 95 insertions(+), 9 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 90269d98..a5abe386 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -96,6 +96,7 @@ dependencies { implementation(libs.androidx.hilt.navigation.compose) implementation(libs.hilt.android) implementation(libs.androidx.media3.session) + implementation(libs.androidx.media3.datasource.okhttp) kapt(libs.hilt.android.compiler) implementation(libs.androidx.core.ktx) diff --git a/app/src/main/java/org/grakovne/lissen/channel/audiobookshelf/common/api/AudiobookshelfAuthService.kt b/app/src/main/java/org/grakovne/lissen/channel/audiobookshelf/common/api/AudiobookshelfAuthService.kt index b2b04926..17b50e8a 100644 --- a/app/src/main/java/org/grakovne/lissen/channel/audiobookshelf/common/api/AudiobookshelfAuthService.kt +++ b/app/src/main/java/org/grakovne/lissen/channel/audiobookshelf/common/api/AudiobookshelfAuthService.kt @@ -37,9 +37,7 @@ class AudiobookshelfAuthService @Inject constructor( ) apiService = apiClient.retrofit.create(AudiobookshelfApiClient::class.java) - } catch (e: Exception) { - return ApiResult.Error(ApiError.InternalError) - } + val response: ApiResult = safeApiCall { apiService.login(CredentialsLoginRequest(username, password)) } @@ -53,6 +51,9 @@ class AudiobookshelfAuthService @Inject constructor( }, onFailure = { ApiResult.Error(it.code) } ) + } catch (e: Exception) { + return ApiResult.Error(ApiError.InternalError) + } } override fun getAuthType(): AuthType = AuthType.CREDENTIALS diff --git a/app/src/main/java/org/grakovne/lissen/channel/audiobookshelf/podcast/converter/PodcastPageResponseConverter.kt b/app/src/main/java/org/grakovne/lissen/channel/audiobookshelf/podcast/converter/PodcastPageResponseConverter.kt index 69373016..9c73a94e 100644 --- a/app/src/main/java/org/grakovne/lissen/channel/audiobookshelf/podcast/converter/PodcastPageResponseConverter.kt +++ b/app/src/main/java/org/grakovne/lissen/channel/audiobookshelf/podcast/converter/PodcastPageResponseConverter.kt @@ -19,7 +19,7 @@ class PodcastPageResponseConverter @Inject constructor() { id = it.id, title = title, author = it.media.metadata.author, - cachedState = BookCachedState.UNABLE_TO_CACHE, + cachedState = BookCachedState.ABLE_TO_CACHE, duration = it.media.duration.toInt() ) } diff --git a/app/src/main/java/org/grakovne/lissen/channel/common/ApiClient.kt b/app/src/main/java/org/grakovne/lissen/channel/common/ApiClient.kt index 935e9d1a..b6a61af2 100644 --- a/app/src/main/java/org/grakovne/lissen/channel/common/ApiClient.kt +++ b/app/src/main/java/org/grakovne/lissen/channel/common/ApiClient.kt @@ -7,7 +7,11 @@ import okhttp3.logging.HttpLoggingInterceptor import org.grakovne.lissen.domain.connection.ServerRequestHeader import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory +import java.security.KeyStore import java.util.concurrent.TimeUnit +import javax.net.ssl.SSLContext +import javax.net.ssl.TrustManagerFactory +import javax.net.ssl.X509TrustManager class ApiClient( host: String, @@ -15,7 +19,25 @@ class ApiClient( token: String? = null ) { - private val httpClient = OkHttpClient.Builder() + fun getSystemTrustManager(): X509TrustManager { + val keyStore = KeyStore.getInstance("AndroidCAStore") + keyStore.load(null) + + val trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()) + trustManagerFactory.init(keyStore) + + return trustManagerFactory.trustManagers.first { it is X509TrustManager } as X509TrustManager + } + + fun getSystemSSLContext(trustManager: X509TrustManager): SSLContext { + val sslContext = SSLContext.getInstance("TLS") + sslContext.init(null, arrayOf(trustManager), null) + return sslContext + } + + private val httpClient = OkHttpClient + .Builder() + .sslSocketFactory(getSystemSSLContext(getSystemTrustManager()).socketFactory, getSystemTrustManager()) .addInterceptor( HttpLoggingInterceptor().apply { level = HttpLoggingInterceptor.Level.NONE diff --git a/app/src/main/java/org/grakovne/lissen/channel/common/BinaryApiClient.kt b/app/src/main/java/org/grakovne/lissen/channel/common/BinaryApiClient.kt index 27cc8ffb..7483cbbf 100644 --- a/app/src/main/java/org/grakovne/lissen/channel/common/BinaryApiClient.kt +++ b/app/src/main/java/org/grakovne/lissen/channel/common/BinaryApiClient.kt @@ -5,7 +5,11 @@ import okhttp3.OkHttpClient import okhttp3.logging.HttpLoggingInterceptor import org.grakovne.lissen.domain.connection.ServerRequestHeader import retrofit2.Retrofit +import java.security.KeyStore import java.util.concurrent.TimeUnit +import javax.net.ssl.SSLContext +import javax.net.ssl.TrustManagerFactory +import javax.net.ssl.X509TrustManager class BinaryApiClient( host: String, @@ -13,7 +17,25 @@ class BinaryApiClient( token: String ) { - private val httpClient = OkHttpClient.Builder() + fun getSystemTrustManager(): X509TrustManager { + val keyStore = KeyStore.getInstance("AndroidCAStore") + keyStore.load(null) + + val trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()) + trustManagerFactory.init(keyStore) + + return trustManagerFactory.trustManagers.first { it is X509TrustManager } as X509TrustManager + } + + fun getSystemSSLContext(trustManager: X509TrustManager): SSLContext { + val sslContext = SSLContext.getInstance("TLS") + sslContext.init(null, arrayOf(trustManager), null) + return sslContext + } + + private val httpClient = OkHttpClient + .Builder() + .sslSocketFactory(getSystemSSLContext(getSystemTrustManager()).socketFactory, getSystemTrustManager()) .addInterceptor( HttpLoggingInterceptor().apply { level = HttpLoggingInterceptor.Level.NONE diff --git a/app/src/main/java/org/grakovne/lissen/playback/service/PlaybackService.kt b/app/src/main/java/org/grakovne/lissen/playback/service/PlaybackService.kt index d11d0429..42b6e4a2 100644 --- a/app/src/main/java/org/grakovne/lissen/playback/service/PlaybackService.kt +++ b/app/src/main/java/org/grakovne/lissen/playback/service/PlaybackService.kt @@ -10,6 +10,7 @@ import androidx.media3.common.MediaMetadata.PICTURE_TYPE_FRONT_COVER import androidx.media3.common.util.UnstableApi import androidx.media3.datasource.DefaultDataSource import androidx.media3.datasource.DefaultHttpDataSource +import androidx.media3.datasource.okhttp.OkHttpDataSource import androidx.media3.exoplayer.ExoPlayer import androidx.media3.exoplayer.source.ProgressiveMediaSource import androidx.media3.session.MediaSession @@ -22,13 +23,19 @@ import kotlinx.coroutines.awaitAll import kotlinx.coroutines.cancel import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor import org.grakovne.lissen.channel.audiobookshelf.common.api.RequestHeadersProvider import org.grakovne.lissen.content.LissenMediaProvider import org.grakovne.lissen.domain.BookFile import org.grakovne.lissen.domain.DetailedItem import org.grakovne.lissen.domain.MediaProgress import org.grakovne.lissen.persistence.preferences.LissenSharedPreferences +import java.security.KeyStore import javax.inject.Inject +import javax.net.ssl.SSLContext +import javax.net.ssl.TrustManagerFactory +import javax.net.ssl.X509TrustManager @AndroidEntryPoint class PlaybackService : MediaSessionService() { @@ -228,19 +235,50 @@ class PlaybackService : MediaSessionService() { progress: MediaProgress? ) = seek(chapters, progress?.currentTime) + fun getSystemTrustManager(): X509TrustManager { + val keyStore = KeyStore.getInstance("AndroidCAStore") + keyStore.load(null) + + val trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()) + trustManagerFactory.init(keyStore) + + return trustManagerFactory.trustManagers.first { it is X509TrustManager } as X509TrustManager + } + + fun getSystemSSLContext(trustManager: X509TrustManager): SSLContext { + val sslContext = SSLContext.getInstance("TLS") + sslContext.init(null, arrayOf(trustManager), null) + return sslContext + } + + private fun createOkHttpClient(): OkHttpClient { + val trustManager = getSystemTrustManager() + val sslContext = getSystemSSLContext(trustManager) + return OkHttpClient.Builder() + .sslSocketFactory(sslContext.socketFactory, trustManager) + .addInterceptor( + HttpLoggingInterceptor().apply { + level = HttpLoggingInterceptor.Level.NONE + } + ) + .build() + } + @OptIn(UnstableApi::class) private fun buildDataSourceFactory(): DefaultDataSource.Factory { val requestHeaders = requestHeadersProvider .fetchRequestHeaders() .associate { it.name to it.value } - val networkDatasourceFactory = DefaultHttpDataSource - .Factory() + val okHttpClient = createOkHttpClient() + + val okHttpDataSourceFactory = OkHttpDataSource + .Factory(okHttpClient) .setDefaultRequestProperties(requestHeaders) return DefaultDataSource.Factory( baseContext, - networkDatasourceFactory + okHttpDataSourceFactory ) } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 1aa31095..6b42de69 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -31,6 +31,7 @@ roomRuntime = "2.6.1" rules = "1.6.1" runtimeLivedata = "1.7.5" media3Session = "1.4.1" +media3DatasourceOkhttp = "1.4.1" [libraries] accompanist-systemuicontroller = { module = "com.google.accompanist:accompanist-systemuicontroller", version.ref = "accompanistSystemuicontroller" } @@ -80,6 +81,7 @@ material3 = { module = "androidx.compose.material3:material3", version.ref = "ma okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" } retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofit" } androidx-media3-session = { group = "androidx.media3", name = "media3-session", version.ref = "media3Session" } +androidx-media3-datasource-okhttp = { group = "androidx.media3", name = "media3-datasource-okhttp", version.ref = "media3DatasourceOkhttp" } [plugins] android-application = { id = "com.android.application", version.ref = "agp" } From 2119298d2d73349f1cf70c849473889d1473b6ac Mon Sep 17 00:00:00 2001 From: grakovne Date: Tue, 12 Nov 2024 21:48:30 +0100 Subject: [PATCH 2/5] wip --- .../common/api/AudiobookshelfAuthService.kt | 23 +++++++------- .../converter/PodcastPageResponseConverter.kt | 2 +- .../lissen/channel/common/ApiClient.kt | 23 ++------------ .../lissen/channel/common/BinaryApiClient.kt | 23 ++------------ .../lissen/common/CertificateExtension.kt | 31 +++++++++++++++++++ .../playback/service/PlaybackService.kt | 29 +++-------------- 6 files changed, 51 insertions(+), 80 deletions(-) create mode 100644 app/src/main/java/org/grakovne/lissen/common/CertificateExtension.kt diff --git a/app/src/main/java/org/grakovne/lissen/channel/audiobookshelf/common/api/AudiobookshelfAuthService.kt b/app/src/main/java/org/grakovne/lissen/channel/audiobookshelf/common/api/AudiobookshelfAuthService.kt index 17b50e8a..54614b69 100644 --- a/app/src/main/java/org/grakovne/lissen/channel/audiobookshelf/common/api/AudiobookshelfAuthService.kt +++ b/app/src/main/java/org/grakovne/lissen/channel/audiobookshelf/common/api/AudiobookshelfAuthService.kt @@ -38,19 +38,18 @@ class AudiobookshelfAuthService @Inject constructor( apiService = apiClient.retrofit.create(AudiobookshelfApiClient::class.java) + val response: ApiResult = + safeApiCall { apiService.login(CredentialsLoginRequest(username, password)) } - val response: ApiResult = - safeApiCall { apiService.login(CredentialsLoginRequest(username, password)) } - - return response - .fold( - onSuccess = { - loginResponseConverter - .apply(it) - .let { ApiResult.Success(it) } - }, - onFailure = { ApiResult.Error(it.code) } - ) + return response + .fold( + onSuccess = { + loginResponseConverter + .apply(it) + .let { ApiResult.Success(it) } + }, + onFailure = { ApiResult.Error(it.code) } + ) } catch (e: Exception) { return ApiResult.Error(ApiError.InternalError) } diff --git a/app/src/main/java/org/grakovne/lissen/channel/audiobookshelf/podcast/converter/PodcastPageResponseConverter.kt b/app/src/main/java/org/grakovne/lissen/channel/audiobookshelf/podcast/converter/PodcastPageResponseConverter.kt index 9c73a94e..69373016 100644 --- a/app/src/main/java/org/grakovne/lissen/channel/audiobookshelf/podcast/converter/PodcastPageResponseConverter.kt +++ b/app/src/main/java/org/grakovne/lissen/channel/audiobookshelf/podcast/converter/PodcastPageResponseConverter.kt @@ -19,7 +19,7 @@ class PodcastPageResponseConverter @Inject constructor() { id = it.id, title = title, author = it.media.metadata.author, - cachedState = BookCachedState.ABLE_TO_CACHE, + cachedState = BookCachedState.UNABLE_TO_CACHE, duration = it.media.duration.toInt() ) } diff --git a/app/src/main/java/org/grakovne/lissen/channel/common/ApiClient.kt b/app/src/main/java/org/grakovne/lissen/channel/common/ApiClient.kt index b6a61af2..c8949654 100644 --- a/app/src/main/java/org/grakovne/lissen/channel/common/ApiClient.kt +++ b/app/src/main/java/org/grakovne/lissen/channel/common/ApiClient.kt @@ -4,14 +4,11 @@ import okhttp3.Interceptor import okhttp3.OkHttpClient import okhttp3.Request import okhttp3.logging.HttpLoggingInterceptor +import org.grakovne.lissen.common.withTrustedCertificates import org.grakovne.lissen.domain.connection.ServerRequestHeader import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory -import java.security.KeyStore import java.util.concurrent.TimeUnit -import javax.net.ssl.SSLContext -import javax.net.ssl.TrustManagerFactory -import javax.net.ssl.X509TrustManager class ApiClient( host: String, @@ -19,25 +16,9 @@ class ApiClient( token: String? = null ) { - fun getSystemTrustManager(): X509TrustManager { - val keyStore = KeyStore.getInstance("AndroidCAStore") - keyStore.load(null) - - val trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()) - trustManagerFactory.init(keyStore) - - return trustManagerFactory.trustManagers.first { it is X509TrustManager } as X509TrustManager - } - - fun getSystemSSLContext(trustManager: X509TrustManager): SSLContext { - val sslContext = SSLContext.getInstance("TLS") - sslContext.init(null, arrayOf(trustManager), null) - return sslContext - } - private val httpClient = OkHttpClient .Builder() - .sslSocketFactory(getSystemSSLContext(getSystemTrustManager()).socketFactory, getSystemTrustManager()) + .withTrustedCertificates() .addInterceptor( HttpLoggingInterceptor().apply { level = HttpLoggingInterceptor.Level.NONE diff --git a/app/src/main/java/org/grakovne/lissen/channel/common/BinaryApiClient.kt b/app/src/main/java/org/grakovne/lissen/channel/common/BinaryApiClient.kt index 7483cbbf..ac5dd8b8 100644 --- a/app/src/main/java/org/grakovne/lissen/channel/common/BinaryApiClient.kt +++ b/app/src/main/java/org/grakovne/lissen/channel/common/BinaryApiClient.kt @@ -3,13 +3,10 @@ package org.grakovne.lissen.channel.common import okhttp3.Interceptor import okhttp3.OkHttpClient import okhttp3.logging.HttpLoggingInterceptor +import org.grakovne.lissen.common.withTrustedCertificates import org.grakovne.lissen.domain.connection.ServerRequestHeader import retrofit2.Retrofit -import java.security.KeyStore import java.util.concurrent.TimeUnit -import javax.net.ssl.SSLContext -import javax.net.ssl.TrustManagerFactory -import javax.net.ssl.X509TrustManager class BinaryApiClient( host: String, @@ -17,25 +14,9 @@ class BinaryApiClient( token: String ) { - fun getSystemTrustManager(): X509TrustManager { - val keyStore = KeyStore.getInstance("AndroidCAStore") - keyStore.load(null) - - val trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()) - trustManagerFactory.init(keyStore) - - return trustManagerFactory.trustManagers.first { it is X509TrustManager } as X509TrustManager - } - - fun getSystemSSLContext(trustManager: X509TrustManager): SSLContext { - val sslContext = SSLContext.getInstance("TLS") - sslContext.init(null, arrayOf(trustManager), null) - return sslContext - } - private val httpClient = OkHttpClient .Builder() - .sslSocketFactory(getSystemSSLContext(getSystemTrustManager()).socketFactory, getSystemTrustManager()) + .withTrustedCertificates() .addInterceptor( HttpLoggingInterceptor().apply { level = HttpLoggingInterceptor.Level.NONE diff --git a/app/src/main/java/org/grakovne/lissen/common/CertificateExtension.kt b/app/src/main/java/org/grakovne/lissen/common/CertificateExtension.kt new file mode 100644 index 00000000..8df5c4a8 --- /dev/null +++ b/app/src/main/java/org/grakovne/lissen/common/CertificateExtension.kt @@ -0,0 +1,31 @@ +package org.grakovne.lissen.common + +import okhttp3.OkHttpClient +import java.security.KeyStore +import javax.net.ssl.SSLContext +import javax.net.ssl.TrustManagerFactory +import javax.net.ssl.TrustManagerFactory.getInstance +import javax.net.ssl.X509TrustManager + +fun OkHttpClient.Builder.withTrustedCertificates(): OkHttpClient.Builder { + val trustManager = getSystemTrustManager() + val sslContext = getSystemSSLContext(trustManager) + this.sslSocketFactory(sslContext.socketFactory, trustManager) + return this +} + +private fun getSystemTrustManager(): X509TrustManager { + val keyStore = KeyStore.getInstance("AndroidCAStore") + keyStore.load(null) + + val trustManagerFactory = getInstance(TrustManagerFactory.getDefaultAlgorithm()) + trustManagerFactory.init(keyStore) + + return trustManagerFactory.trustManagers.first { it is X509TrustManager } as X509TrustManager +} + +private fun getSystemSSLContext(trustManager: X509TrustManager): SSLContext { + val sslContext = SSLContext.getInstance("TLS") + sslContext.init(null, arrayOf(trustManager), null) + return sslContext +} diff --git a/app/src/main/java/org/grakovne/lissen/playback/service/PlaybackService.kt b/app/src/main/java/org/grakovne/lissen/playback/service/PlaybackService.kt index 42b6e4a2..1a643337 100644 --- a/app/src/main/java/org/grakovne/lissen/playback/service/PlaybackService.kt +++ b/app/src/main/java/org/grakovne/lissen/playback/service/PlaybackService.kt @@ -9,7 +9,6 @@ import androidx.media3.common.MediaMetadata import androidx.media3.common.MediaMetadata.PICTURE_TYPE_FRONT_COVER import androidx.media3.common.util.UnstableApi import androidx.media3.datasource.DefaultDataSource -import androidx.media3.datasource.DefaultHttpDataSource import androidx.media3.datasource.okhttp.OkHttpDataSource import androidx.media3.exoplayer.ExoPlayer import androidx.media3.exoplayer.source.ProgressiveMediaSource @@ -26,16 +25,13 @@ import kotlinx.coroutines.withContext import okhttp3.OkHttpClient import okhttp3.logging.HttpLoggingInterceptor import org.grakovne.lissen.channel.audiobookshelf.common.api.RequestHeadersProvider +import org.grakovne.lissen.common.withTrustedCertificates import org.grakovne.lissen.content.LissenMediaProvider import org.grakovne.lissen.domain.BookFile import org.grakovne.lissen.domain.DetailedItem import org.grakovne.lissen.domain.MediaProgress import org.grakovne.lissen.persistence.preferences.LissenSharedPreferences -import java.security.KeyStore import javax.inject.Inject -import javax.net.ssl.SSLContext -import javax.net.ssl.TrustManagerFactory -import javax.net.ssl.X509TrustManager @AndroidEntryPoint class PlaybackService : MediaSessionService() { @@ -235,27 +231,10 @@ class PlaybackService : MediaSessionService() { progress: MediaProgress? ) = seek(chapters, progress?.currentTime) - fun getSystemTrustManager(): X509TrustManager { - val keyStore = KeyStore.getInstance("AndroidCAStore") - keyStore.load(null) - - val trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()) - trustManagerFactory.init(keyStore) - - return trustManagerFactory.trustManagers.first { it is X509TrustManager } as X509TrustManager - } - - fun getSystemSSLContext(trustManager: X509TrustManager): SSLContext { - val sslContext = SSLContext.getInstance("TLS") - sslContext.init(null, arrayOf(trustManager), null) - return sslContext - } - private fun createOkHttpClient(): OkHttpClient { - val trustManager = getSystemTrustManager() - val sslContext = getSystemSSLContext(trustManager) - return OkHttpClient.Builder() - .sslSocketFactory(sslContext.socketFactory, trustManager) + return OkHttpClient + .Builder() + .withTrustedCertificates() .addInterceptor( HttpLoggingInterceptor().apply { level = HttpLoggingInterceptor.Level.NONE From 24e83012fc24d28fd294c5b546d0566df88d4426 Mon Sep 17 00:00:00 2001 From: grakovne Date: Tue, 12 Nov 2024 21:52:24 +0100 Subject: [PATCH 3/5] wip --- .../common/api/AudiobookshelfAuthService.kt | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/org/grakovne/lissen/channel/audiobookshelf/common/api/AudiobookshelfAuthService.kt b/app/src/main/java/org/grakovne/lissen/channel/audiobookshelf/common/api/AudiobookshelfAuthService.kt index 54614b69..b2b04926 100644 --- a/app/src/main/java/org/grakovne/lissen/channel/audiobookshelf/common/api/AudiobookshelfAuthService.kt +++ b/app/src/main/java/org/grakovne/lissen/channel/audiobookshelf/common/api/AudiobookshelfAuthService.kt @@ -37,22 +37,22 @@ class AudiobookshelfAuthService @Inject constructor( ) apiService = apiClient.retrofit.create(AudiobookshelfApiClient::class.java) - - val response: ApiResult = - safeApiCall { apiService.login(CredentialsLoginRequest(username, password)) } - - return response - .fold( - onSuccess = { - loginResponseConverter - .apply(it) - .let { ApiResult.Success(it) } - }, - onFailure = { ApiResult.Error(it.code) } - ) } catch (e: Exception) { return ApiResult.Error(ApiError.InternalError) } + + val response: ApiResult = + safeApiCall { apiService.login(CredentialsLoginRequest(username, password)) } + + return response + .fold( + onSuccess = { + loginResponseConverter + .apply(it) + .let { ApiResult.Success(it) } + }, + onFailure = { ApiResult.Error(it.code) } + ) } override fun getAuthType(): AuthType = AuthType.CREDENTIALS From c8c9a5615fa97b875d7b541489c5dfe284ab09ac Mon Sep 17 00:00:00 2001 From: grakovne Date: Tue, 12 Nov 2024 22:04:55 +0100 Subject: [PATCH 4/5] wip --- .../grakovne/lissen/common/CertificateExtension.kt | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/org/grakovne/lissen/common/CertificateExtension.kt b/app/src/main/java/org/grakovne/lissen/common/CertificateExtension.kt index 8df5c4a8..c9801f3b 100644 --- a/app/src/main/java/org/grakovne/lissen/common/CertificateExtension.kt +++ b/app/src/main/java/org/grakovne/lissen/common/CertificateExtension.kt @@ -8,10 +8,15 @@ import javax.net.ssl.TrustManagerFactory.getInstance import javax.net.ssl.X509TrustManager fun OkHttpClient.Builder.withTrustedCertificates(): OkHttpClient.Builder { - val trustManager = getSystemTrustManager() - val sslContext = getSystemSSLContext(trustManager) - this.sslSocketFactory(sslContext.socketFactory, trustManager) - return this + return try { + val trustManager = getSystemTrustManager() + val sslContext = getSystemSSLContext(trustManager) + this.sslSocketFactory(sslContext.socketFactory, trustManager) + + this + } catch (ex: Exception) { + this + } } private fun getSystemTrustManager(): X509TrustManager { From 28c79846ef2705943a853bea8707c13a5041a7d5 Mon Sep 17 00:00:00 2001 From: grakovne Date: Tue, 12 Nov 2024 22:10:05 +0100 Subject: [PATCH 5/5] wip --- .../lissen/viewmodel/PlayerViewModel.kt | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/org/grakovne/lissen/viewmodel/PlayerViewModel.kt b/app/src/main/java/org/grakovne/lissen/viewmodel/PlayerViewModel.kt index d861bf77..17de0f94 100644 --- a/app/src/main/java/org/grakovne/lissen/viewmodel/PlayerViewModel.kt +++ b/app/src/main/java/org/grakovne/lissen/viewmodel/PlayerViewModel.kt @@ -1,5 +1,6 @@ package org.grakovne.lissen.viewmodel +import android.util.Log import androidx.lifecycle.LiveData import androidx.lifecycle.MediatorLiveData import androidx.lifecycle.MutableLiveData @@ -111,9 +112,17 @@ class PlayerViewModel @Inject constructor( } fun seekTo(chapterPosition: Double) { - val absolutePosition = currentChapterIndex.value - ?.let { chapterIndex -> book.value?.chapters?.get(chapterIndex)?.start } - ?.let { it + chapterPosition } ?: return + val currentIndex = currentChapterIndex.value ?: return + + if (currentIndex < 0) { + Log.w(TAG, "Unable seek to $chapterPosition because there is no chapter") + return + } + + val absolutePosition = currentIndex + .let { chapterIndex -> book.value?.chapters?.get(chapterIndex)?.start } + ?.let { it + chapterPosition } + ?: return mediaRepository.seekTo(absolutePosition) } @@ -164,7 +173,7 @@ class PlayerViewModel @Inject constructor( } companion object { - + private const val TAG = "PlayerViewModel" private const val CURRENT_TRACK_REPLAY_THRESHOLD = 5 } }