Compare commits

..

9 Commits

Author SHA1 Message Date
ecd23213f9 fix: illegal input.
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone Build is passing
2023-05-13 22:14:25 +02:00
e6baed8cb4 Changelog for v123051321 [CI SKIP] 2023-05-12 19:19:35 +00:00
c87abec0b9 debug: Debug null context.
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone Build is passing
2023-05-12 20:31:40 +02:00
0aba41d8bf Changelog for v123051301 [CI SKIP] 2023-05-10 19:36:31 +00:00
2a2d1047b4 feat: Basic auth from url. Fixes #142 (#143)
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone Build is passing
Co-authored-by: aminecmi <aminecmi@gmail.com>
Reviewed-on: https://gitea.amine-louveau.fr/Louvorg/ReaderForSelfoss-multiplatform/pulls/143
2023-05-10 19:19:11 +00:00
66ef1ccf32 debug: Debug index out of bound exception.
Some checks failed
continuous-integration/drone/push Build is failing
2023-05-10 20:50:13 +02:00
677ede5bc7 Changelog for v123051211 [CI SKIP] 2023-05-01 18:26:12 +00:00
996a7ed22c fix: Sometimes url isn't even defined.
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone Build is passing
2023-04-30 18:41:15 +02:00
85208c4e5a Changelog for v123041021 [CI SKIP] 2023-04-12 19:01:21 +00:00
7 changed files with 292 additions and 46 deletions

View File

@ -1,3 +1,33 @@
**v123051321**
- debug: Debug null context.
- Changelog for v123051301 [CI SKIP]
--------------------------------------------------------------------
**v123051301**
- feat: Basic auth from url. Fixes #142 (#143)
- debug: Debug index out of bound exception.
- Changelog for v123051211 [CI SKIP]
--------------------------------------------------------------------
**v123051211**
- fix: Sometimes url isn't even defined.
- Changelog for v123041021 [CI SKIP]
--------------------------------------------------------------------
**v123041021**
- fix: 'Enable Core Library Desugaring to support older Android versions' (#138) from davidoskky/ReaderForSelfoss-multiplatform:desugaring into master
- Enable Core Library Desugaring to support older Android versions
- Changelog for v123030851 [CI SKIP]
--------------------------------------------------------------------
**v123030851**
- chore: replace textDrawable library (#136)

View File

@ -71,7 +71,12 @@ class ReaderActivity : AppCompatActivity(), DIAware {
finish()
}
readItem(allItems[currentItem])
try {
readItem(allItems[currentItem])
} catch (e: IndexOutOfBoundsException) {
e.sendSilentlyWithAcraWithName("out of bound > size = ${allItems.size} currentItem = $currentItem")
finish()
}
binding.pager.adapter = ScreenSlidePagerAdapter(this)
binding.pager.setCurrentItem(currentItem, false)

View File

@ -31,7 +31,6 @@ import bou.amine.apps.readerforselfossv2.android.utils.openInBrowserAsNewTask
import bou.amine.apps.readerforselfossv2.android.utils.shareLink
import bou.amine.apps.readerforselfossv2.model.MercuryModel
import bou.amine.apps.readerforselfossv2.model.SelfossModel
import bou.amine.apps.readerforselfossv2.model.StatusAndData
import bou.amine.apps.readerforselfossv2.repository.Repository
import bou.amine.apps.readerforselfossv2.rest.MercuryApi
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
@ -260,21 +259,8 @@ class ArticleFragment : Fragment(), DIAware {
CoroutineScope(Dispatchers.Main).launch {
try {
val response = mercuryApi.query(url)
if (response.success && response.data != null && !response.data?.content.isNullOrEmpty()) {
binding.titleView.text = response.data!!.title.orEmpty()
if (typeface != null) {
binding.titleView.typeface = typeface
}
URL(response.data!!.url)
url = response.data!!.url
contentText = response.data!!.content.orEmpty()
htmlToWebview()
handleLeadImage(response)
binding.nestedScrollView.scrollTo(0, 0)
binding.progressBar.visibility = View.GONE
if (response.success && response.data != null) {
handleMercuryData(response.data!!)
} else {
openInBrowserAfterFailing()
}
@ -287,14 +273,35 @@ class ArticleFragment : Fragment(), DIAware {
}
}
private fun handleLeadImage(response: StatusAndData<MercuryModel.ParsedContent>) {
if (!response.data?.lead_image_url.isNullOrEmpty() && context != null) {
private fun handleMercuryData(data: MercuryModel.ParsedContent) {
if (data.error == true || data.failed == true) {
openInBrowserAfterFailing()
} else {
binding.titleView.text = data.title.orEmpty()
if (typeface != null) {
binding.titleView.typeface = typeface
}
URL(data.url)
url = data.url!!
contentText = data.content.orEmpty()
htmlToWebview()
handleLeadImage(data?.lead_image_url)
binding.nestedScrollView.scrollTo(0, 0)
binding.progressBar.visibility = View.GONE
}
}
private fun handleLeadImage(lead_image_url: String?) {
if (!lead_image_url.isNullOrEmpty() && context != null) {
binding.imageView.visibility = View.VISIBLE
Glide
.with(requireContext())
.asBitmap()
.load(
response.data!!.lead_image_url.orEmpty()
lead_image_url
)
.apply(RequestOptions.fitCenterTransform())
.into(binding.imageView)
@ -523,7 +530,12 @@ class ArticleFragment : Fragment(), DIAware {
private fun openInBrowserAfterFailing() {
binding.progressBar.visibility = View.GONE
requireActivity().openInBrowserAsNewTask(this@ArticleFragment.item)
if (context != null) {
requireContext().openInBrowserAsNewTask(this@ArticleFragment.item)
} else {
Exception("openInBrowserAfterFailing context is null").sendSilentlyWithAcraWithName("openInBrowserAfterFailing > $context")
}
}
companion object {

View File

@ -6,9 +6,12 @@ class MercuryModel {
@Serializable
class ParsedContent(
val title: String?,
val content: String?,
val lead_image_url: String?, // NOSONAR
val url: String
val title: String? = null,
val content: String? = null,
val lead_image_url: String? = null, // NOSONAR
val url: String? = null,
val error: Boolean? = null,
val message: String? = null,
val failed: Boolean? = null
)
}

View File

@ -24,8 +24,8 @@ class SelfossModel {
@Serializable
class Stats(
val total: Int,
val unread: Int?,
val starred: Int?
val unread: Int? = null,
val starred: Int? = null
)
@Serializable
@ -36,9 +36,9 @@ class SelfossModel {
@Serializable
data class ApiInformation(
val version: String?,
val apiversion: String?,
val configuration: ApiConfiguration?
val version: String? = null,
val apiversion: String? = null,
val configuration: ApiConfiguration? = null
) {
fun getApiMajorVersion(): Int {
var versionNumber = 0
@ -54,9 +54,9 @@ class SelfossModel {
@Serializable
data class ApiConfiguration(
@Serializable(with = BooleanSerializer::class)
val publicMode: Boolean?,
val publicMode: Boolean? = null,
@Serializable(with = BooleanSerializer::class)
val authEnabled: Boolean?
val authEnabled: Boolean? = null
) {
fun isAuthEnabled() = authEnabled ?: true
@ -75,7 +75,7 @@ class SelfossModel {
data class SourceStats(
override val id: Int,
override var title: String,
override var unread: Int?,
override var unread: Int? = null,
override var error: String? = null,
override var icon: String? = null
) : Source
@ -86,11 +86,11 @@ class SelfossModel {
override var title: String,
override var unread: Int? = null,
@Serializable(with = TagsListSerializer::class)
var tags: List<String>?,
var spout: String?,
override var error: String?,
override var icon: String?,
var params: SourceParams?
var tags: List<String>? = null,
var spout: String? = null,
override var error: String? = null,
override var icon: String? = null,
var params: SourceParams? = null
) : Source
@Serializable
@ -107,13 +107,13 @@ class SelfossModel {
var unread: Boolean,
@Serializable(with = BooleanSerializer::class)
var starred: Boolean,
val thumbnail: String?,
val icon: String?,
val thumbnail: String? = null,
val icon: String? = null,
val link: String,
val sourcetitle: String,
@Serializable(with = TagsListSerializer::class)
val tags: List<String>,
val author: String?
val author: String? = null
) {
fun getLinkDecoded(): String {
var stringUrl: String

View File

@ -7,6 +7,7 @@ import bou.amine.apps.readerforselfossv2.service.AppSettingsService
import io.github.aakira.napier.Napier
import io.ktor.client.*
import io.ktor.client.plugins.*
import io.ktor.client.plugins.auth.providers.*
import io.ktor.client.plugins.cache.*
import io.ktor.client.plugins.contentnegotiation.*
import io.ktor.client.plugins.cookies.*
@ -15,6 +16,9 @@ import io.ktor.client.request.*
import io.ktor.client.statement.*
import io.ktor.http.*
import io.ktor.serialization.kotlinx.json.*
import io.ktor.util.*
import io.ktor.utils.io.charsets.*
import io.ktor.utils.io.core.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@ -32,6 +36,7 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
prettyPrint = true
isLenient = true
ignoreUnknownKeys = true
explicitNulls = false
})
}
install(Logging) {
@ -63,6 +68,7 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
expectSuccess = false
}
return client
}
@ -74,6 +80,13 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
client = createHttpClient()
}
fun constructBasicAuthValue(credentials: BasicAuthCredentials): String {
val authString = "${credentials.username}:${credentials.password}"
val authBuf = authString.toByteArray(Charsets.UTF_8).encodeBase64()
return "Basic $authBuf"
}
// Api version was introduces after the POST login, so when there is a version, it should be available
private fun shouldHavePostLogin() = appSettingsService.getApiVersion() != -1
private fun hasLoginInfo() =
@ -96,11 +109,23 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
private suspend fun getLogin() = maybeResponse(client.tryToGet(url("/login")) {
parameter("username", appSettingsService.getUserName())
parameter("password", appSettingsService.getPassword())
if (appSettingsService.getBasicUserName().isNotEmpty() && appSettingsService.getBasicPassword().isNotEmpty()) {
headers {
append(HttpHeaders.Authorization, constructBasicAuthValue(BasicAuthCredentials(username = appSettingsService.getBasicUserName(), password = appSettingsService.getBasicPassword()))
)
}
}
})
private suspend fun postLogin() = maybeResponse(client.tryToPost(url("/login")) {
parameter("username", appSettingsService.getUserName())
parameter("password", appSettingsService.getPassword())
if (appSettingsService.getBasicUserName().isNotEmpty() && appSettingsService.getBasicPassword().isNotEmpty()) {
headers {
append(HttpHeaders.Authorization, constructBasicAuthValue(BasicAuthCredentials(username = appSettingsService.getBasicUserName(), password = appSettingsService.getBasicPassword()))
)
}
}
})
private fun shouldHaveNewLogout() =
@ -114,9 +139,23 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
}
private suspend fun maybeLogoutIfAvailable() =
responseOrSuccessIf404(client.tryToGet(url("/logout")))
responseOrSuccessIf404(client.tryToGet(url("/logout")) {
if (appSettingsService.getBasicUserName().isNotEmpty() && appSettingsService.getBasicPassword().isNotEmpty()) {
headers {
append(HttpHeaders.Authorization, constructBasicAuthValue(BasicAuthCredentials(username = appSettingsService.getBasicUserName(), password = appSettingsService.getBasicPassword()))
)
}
}
})
private suspend fun doLogout() = maybeResponse(client.tryToDelete(url("/api/session/current")))
private suspend fun doLogout() = maybeResponse(client.tryToDelete(url("/api/session/current")) {
if (appSettingsService.getBasicUserName().isNotEmpty() && appSettingsService.getBasicPassword().isNotEmpty()) {
headers {
append(HttpHeaders.Authorization, constructBasicAuthValue(BasicAuthCredentials(username = appSettingsService.getBasicUserName(), password = appSettingsService.getBasicPassword()))
)
}
}
})
suspend fun getItems(
type: String,
@ -139,6 +178,12 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
parameter("updatedsince", updatedSince)
parameter("items", items ?: appSettingsService.getItemsNumber())
parameter("offset", offset)
if (appSettingsService.getBasicUserName().isNotEmpty() && appSettingsService.getBasicPassword().isNotEmpty()) {
headers {
append(HttpHeaders.Authorization, constructBasicAuthValue(BasicAuthCredentials(username = appSettingsService.getBasicUserName(), password = appSettingsService.getBasicPassword()))
)
}
}
})
suspend fun getItemsWithoutCatch(): StatusAndData<List<SelfossModel.Item>> =
@ -149,6 +194,12 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
}
parameter("type", "all")
parameter("items", 1)
if (appSettingsService.getBasicUserName().isNotEmpty() && appSettingsService.getBasicPassword().isNotEmpty()) {
headers {
append(HttpHeaders.Authorization, constructBasicAuthValue(BasicAuthCredentials(username = appSettingsService.getBasicUserName(), password = appSettingsService.getBasicPassword()))
)
}
}
})
suspend fun stats(): StatusAndData<SelfossModel.Stats> =
@ -157,6 +208,12 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
parameter("username", appSettingsService.getUserName())
parameter("password", appSettingsService.getPassword())
}
if (appSettingsService.getBasicUserName().isNotEmpty() && appSettingsService.getBasicPassword().isNotEmpty()) {
headers {
append(HttpHeaders.Authorization, constructBasicAuthValue(BasicAuthCredentials(username = appSettingsService.getBasicUserName(), password = appSettingsService.getBasicPassword()))
)
}
}
})
suspend fun tags(): StatusAndData<List<SelfossModel.Tag>> =
@ -165,6 +222,12 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
parameter("username", appSettingsService.getUserName())
parameter("password", appSettingsService.getPassword())
}
if (appSettingsService.getBasicUserName().isNotEmpty() && appSettingsService.getBasicPassword().isNotEmpty()) {
headers {
append(HttpHeaders.Authorization, constructBasicAuthValue(BasicAuthCredentials(username = appSettingsService.getBasicUserName(), password = appSettingsService.getBasicPassword()))
)
}
}
})
suspend fun update(): StatusAndData<String> =
@ -173,6 +236,12 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
parameter("username", appSettingsService.getUserName())
parameter("password", appSettingsService.getPassword())
}
if (appSettingsService.getBasicUserName().isNotEmpty() && appSettingsService.getBasicPassword().isNotEmpty()) {
headers {
append(HttpHeaders.Authorization, constructBasicAuthValue(BasicAuthCredentials(username = appSettingsService.getBasicUserName(), password = appSettingsService.getBasicPassword()))
)
}
}
})
suspend fun spouts(): StatusAndData<Map<String, SelfossModel.Spout>> =
@ -181,6 +250,12 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
parameter("username", appSettingsService.getUserName())
parameter("password", appSettingsService.getPassword())
}
if (appSettingsService.getBasicUserName().isNotEmpty() && appSettingsService.getBasicPassword().isNotEmpty()) {
headers {
append(HttpHeaders.Authorization, constructBasicAuthValue(BasicAuthCredentials(username = appSettingsService.getBasicUserName(), password = appSettingsService.getBasicPassword()))
)
}
}
})
suspend fun sourcesStats(): StatusAndData<ArrayList<SelfossModel.SourceStats>> =
@ -189,6 +264,12 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
parameter("username", appSettingsService.getUserName())
parameter("password", appSettingsService.getPassword())
}
if (appSettingsService.getBasicUserName().isNotEmpty() && appSettingsService.getBasicPassword().isNotEmpty()) {
headers {
append(HttpHeaders.Authorization, constructBasicAuthValue(BasicAuthCredentials(username = appSettingsService.getBasicUserName(), password = appSettingsService.getBasicPassword()))
)
}
}
})
suspend fun sourcesDetailed(): StatusAndData<ArrayList<SelfossModel.SourceDetail>> =
@ -197,10 +278,23 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
parameter("username", appSettingsService.getUserName())
parameter("password", appSettingsService.getPassword())
}
if (appSettingsService.getBasicUserName().isNotEmpty() && appSettingsService.getBasicPassword().isNotEmpty()) {
headers {
append(HttpHeaders.Authorization, constructBasicAuthValue(BasicAuthCredentials(username = appSettingsService.getBasicUserName(), password = appSettingsService.getBasicPassword()))
)
}
}
})
suspend fun apiInformation(): StatusAndData<SelfossModel.ApiInformation> =
bodyOrFailure(client.tryToGet(url("/api/about")))
bodyOrFailure(client.tryToGet(url("/api/about")) {
if (appSettingsService.getBasicUserName().isNotEmpty() && appSettingsService.getBasicPassword().isNotEmpty()) {
headers {
append(HttpHeaders.Authorization, constructBasicAuthValue(BasicAuthCredentials(username = appSettingsService.getBasicUserName(), password = appSettingsService.getBasicPassword()))
)
}
}
})
suspend fun markAsRead(id: String): SuccessResponse =
maybeResponse(client.tryToPost(url("/mark/$id")) {
@ -208,6 +302,12 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
parameter("username", appSettingsService.getUserName())
parameter("password", appSettingsService.getPassword())
}
if (appSettingsService.getBasicUserName().isNotEmpty() && appSettingsService.getBasicPassword().isNotEmpty()) {
headers {
append(HttpHeaders.Authorization, constructBasicAuthValue(BasicAuthCredentials(username = appSettingsService.getBasicUserName(), password = appSettingsService.getBasicPassword()))
)
}
}
})
suspend fun unmarkAsRead(id: String): SuccessResponse =
@ -216,6 +316,12 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
parameter("username", appSettingsService.getUserName())
parameter("password", appSettingsService.getPassword())
}
if (appSettingsService.getBasicUserName().isNotEmpty() && appSettingsService.getBasicPassword().isNotEmpty()) {
headers {
append(HttpHeaders.Authorization, constructBasicAuthValue(BasicAuthCredentials(username = appSettingsService.getBasicUserName(), password = appSettingsService.getBasicPassword()))
)
}
}
})
suspend fun starr(id: String): SuccessResponse =
@ -224,6 +330,12 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
parameter("username", appSettingsService.getUserName())
parameter("password", appSettingsService.getPassword())
}
if (appSettingsService.getBasicUserName().isNotEmpty() && appSettingsService.getBasicPassword().isNotEmpty()) {
headers {
append(HttpHeaders.Authorization, constructBasicAuthValue(BasicAuthCredentials(username = appSettingsService.getBasicUserName(), password = appSettingsService.getBasicPassword()))
)
}
}
})
suspend fun unstarr(id: String): SuccessResponse =
@ -232,6 +344,12 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
parameter("username", appSettingsService.getUserName())
parameter("password", appSettingsService.getPassword())
}
if (appSettingsService.getBasicUserName().isNotEmpty() && appSettingsService.getBasicPassword().isNotEmpty()) {
headers {
append(HttpHeaders.Authorization, constructBasicAuthValue(BasicAuthCredentials(username = appSettingsService.getBasicUserName(), password = appSettingsService.getBasicPassword()))
)
}
}
})
suspend fun markAllAsRead(ids: List<String>): SuccessResponse =
@ -243,6 +361,14 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
append("password", appSettingsService.getPassword())
}
ids.map { append("ids[]", it) }
},
block = {
if (appSettingsService.getBasicUserName().isNotEmpty() && appSettingsService.getBasicPassword().isNotEmpty()) {
headers {
append(HttpHeaders.Authorization, constructBasicAuthValue(BasicAuthCredentials(username = appSettingsService.getBasicUserName(), password = appSettingsService.getBasicPassword()))
)
}
}
}
))
@ -278,6 +404,14 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
append("url", url)
append("spout", spout)
append(tagsParamName, tags)
},
block = {
if (appSettingsService.getBasicUserName().isNotEmpty() && appSettingsService.getBasicPassword().isNotEmpty()) {
headers {
append(HttpHeaders.Authorization, constructBasicAuthValue(BasicAuthCredentials(username = appSettingsService.getBasicUserName(), password = appSettingsService.getBasicPassword()))
)
}
}
}
)
@ -315,6 +449,14 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
append("url", url)
append("spout", spout)
append(tagsParamName, tags)
},
block = {
if (appSettingsService.getBasicUserName().isNotEmpty() && appSettingsService.getBasicPassword().isNotEmpty()) {
headers {
append(HttpHeaders.Authorization, constructBasicAuthValue(BasicAuthCredentials(username = appSettingsService.getBasicUserName(), password = appSettingsService.getBasicPassword()))
)
}
}
}
)
@ -324,5 +466,18 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
parameter("username", appSettingsService.getUserName())
parameter("password", appSettingsService.getPassword())
}
if (appSettingsService.getBasicUserName().isNotEmpty() && appSettingsService.getBasicPassword().isNotEmpty()) {
headers {
append(
HttpHeaders.Authorization,
constructBasicAuthValue(
BasicAuthCredentials(
username = appSettingsService.getBasicUserName(),
password = appSettingsService.getBasicPassword()
)
)
)
}
}
})
}

View File

@ -10,7 +10,9 @@ class AppSettingsService(acraSenderServiceProcess: Boolean = false) {
private var _publicAccess: Boolean? = null
private var _baseUrl: String = ""
private var _userName: String = ""
private var _basicUserName: String = ""
private var _password: String = ""
private var _basicPassword: String = ""
// User settings related
private var _itemsCaching: Boolean? = null
@ -96,6 +98,20 @@ class AppSettingsService(acraSenderServiceProcess: Boolean = false) {
return _password
}
fun getBasicUserName(): String {
if (_basicUserName.isEmpty()) {
refreshBasicUsername()
}
return _basicUserName
}
fun getBasicPassword(): String {
if (_basicPassword.isEmpty()) {
refreshBasicPassword()
}
return _basicPassword
}
fun getItemsNumber(): Int {
if (_itemsNumber == null) {
refreshItemsNumber()
@ -149,6 +165,14 @@ class AppSettingsService(acraSenderServiceProcess: Boolean = false) {
_password = settings.getString(PASSWORD, "")
}
private fun refreshBasicUsername() {
_basicUserName = settings.getString(BASIC_LOGIN, "")
}
private fun refreshBasicPassword() {
_basicPassword = settings.getString(BASIC_PASSWORD, "")
}
private fun refreshArticleViewerEnabled() {
_articleViewer = settings.getBoolean(PREFER_ARTICLE_VIEWER, true)
}
@ -354,6 +378,8 @@ class AppSettingsService(acraSenderServiceProcess: Boolean = false) {
fun refreshApiSettings() {
refreshPassword()
refreshUsername()
refreshBasicUsername()
refreshBasicPassword()
refreshBaseUrl()
refreshApiVersion()
refreshPublicAccess()
@ -387,7 +413,17 @@ class AppSettingsService(acraSenderServiceProcess: Boolean = false) {
login: String,
password: String
) {
settings.putString(BASE_URL, url)
val regex = """\/\/(\D+):(\D+)@""".toRegex()
val matchResult = regex.find(url)
if (matchResult != null) {
val (basicLogin, basicPassword) = matchResult.destructured
settings.putString(BASIC_LOGIN, basicLogin)
settings.putString(BASIC_PASSWORD, basicPassword)
val urlWithoutBasicAuth = url.replace(regex, "//")
settings.putString(BASE_URL, urlWithoutBasicAuth)
} else {
settings.putString(BASE_URL, url)
}
settings.putString(LOGIN, login)
settings.putString(PASSWORD, password)
refreshApiSettings()
@ -397,6 +433,8 @@ class AppSettingsService(acraSenderServiceProcess: Boolean = false) {
settings.remove(BASE_URL)
settings.remove(LOGIN)
settings.remove(PASSWORD)
settings.remove(BASIC_LOGIN)
settings.remove(BASIC_PASSWORD)
refreshApiSettings()
}
@ -440,6 +478,10 @@ class AppSettingsService(acraSenderServiceProcess: Boolean = false) {
const val PASSWORD = "password"
const val BASIC_LOGIN = "basic_login"
const val BASIC_PASSWORD = "basic_password"
const val PREFER_ARTICLE_VIEWER = "prefer_article_viewer"
const val CARD_VIEW_ACTIVE = "card_view_active"
@ -470,7 +512,6 @@ class AppSettingsService(acraSenderServiceProcess: Boolean = false) {
const val PERIODIC_REFRESH_MINUTES = "periodic_refresh_minutes"
const val INFINITE_LOADING = "infinite_loading"
const val ITEMS_CACHING = "items_caching"