chore: lint cleaning.
This commit is contained in:
@ -7,4 +7,4 @@ actual class DriverFactory(private val context: Context) {
|
||||
actual fun createDriver(): SqlDriver {
|
||||
return AndroidSqliteDriver(ReaderForSelfossDB.Schema, context, "ReaderForSelfossV2-android.db")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,13 +5,19 @@ import java.security.cert.X509Certificate
|
||||
import javax.net.ssl.X509TrustManager
|
||||
|
||||
class NaiveTrustManager : X509TrustManager {
|
||||
override fun checkClientTrusted(chain: Array<out X509Certificate>?, authType: String?) {}
|
||||
override fun checkClientTrusted(
|
||||
chain: Array<out X509Certificate>?,
|
||||
authType: String?,
|
||||
) {}
|
||||
|
||||
override fun checkServerTrusted(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()
|
||||
}
|
||||
}
|
||||
|
@ -3,40 +3,40 @@ package bou.amine.apps.readerforselfossv2.utils
|
||||
import android.text.format.DateUtils
|
||||
import kotlinx.datetime.*
|
||||
|
||||
|
||||
actual class DateUtils {
|
||||
actual companion object {
|
||||
|
||||
// Possible formats are
|
||||
// yyyy-mm-dd hh:mm:ss format
|
||||
private val oldVersionFormat = "\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}(.()\\d*)?".toRegex()
|
||||
|
||||
// yyyy-MM-dd'T'HH:mm:ss[.SSS]XXX (RFC3339)
|
||||
private val newVersionFormat = "\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\+\\d{2}(:\\d{2})?".toRegex()
|
||||
|
||||
// We may need to consider moving the formatting to platform specific code, even if the tests are doubled
|
||||
// For now, we handle this in a hacky way, because kotlin only accepts iso formats
|
||||
actual fun parseDate(dateString: String): Long {
|
||||
var isoDateString: String = if (dateString.matches(oldVersionFormat)) {
|
||||
dateString.replace(" ", "T")
|
||||
} else if (dateString.matches(newVersionFormat)) {
|
||||
dateString.split("+")[0]
|
||||
} else {
|
||||
throw Exception("Unrecognized format for $dateString")
|
||||
}
|
||||
var isoDateString: String =
|
||||
if (dateString.matches(oldVersionFormat)) {
|
||||
dateString.replace(" ", "T")
|
||||
} else if (dateString.matches(newVersionFormat)) {
|
||||
dateString.split("+")[0]
|
||||
} else {
|
||||
throw Exception("Unrecognized format for $dateString")
|
||||
}
|
||||
|
||||
return LocalDateTime.parse(isoDateString).toInstant(TimeZone.currentSystemDefault()).toEpochMilliseconds()
|
||||
}
|
||||
|
||||
actual fun parseRelativeDate(dateString: String): String {
|
||||
|
||||
val date = parseDate(dateString)
|
||||
|
||||
return " " + DateUtils.getRelativeTimeSpanString(
|
||||
date,
|
||||
Clock.System.now().toEpochMilliseconds(),
|
||||
DateUtils.MINUTE_IN_MILLIS,
|
||||
DateUtils.FORMAT_ABBREV_RELATIVE
|
||||
)
|
||||
return " " +
|
||||
DateUtils.getRelativeTimeSpanString(
|
||||
date,
|
||||
Clock.System.now().toEpochMilliseconds(),
|
||||
DateUtils.MINUTE_IN_MILLIS,
|
||||
DateUtils.FORMAT_ABBREV_RELATIVE,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,13 +21,13 @@ actual fun SelfossModel.Item.getThumbnail(baseUrl: String): String {
|
||||
actual fun SelfossModel.Item.getImages(): ArrayList<String> {
|
||||
val allImages = ArrayList<String>()
|
||||
|
||||
for ( image in Jsoup.parse(content).getElementsByTag("img")) {
|
||||
for (image in Jsoup.parse(content).getElementsByTag("img")) {
|
||||
val url = image.attr("src")
|
||||
if (url.lowercase(Locale.US).contains(".jpg") ||
|
||||
url.lowercase(Locale.US).contains(".jpeg") ||
|
||||
url.lowercase(Locale.US).contains(".png") ||
|
||||
url.lowercase(Locale.US).contains(".webp"))
|
||||
{
|
||||
url.lowercase(Locale.US).contains(".webp")
|
||||
) {
|
||||
allImages.add(url)
|
||||
}
|
||||
}
|
||||
@ -38,7 +38,11 @@ actual fun SelfossModel.Source.getIcon(baseUrl: String): String {
|
||||
return constructUrl(baseUrl, "favicons", icon)
|
||||
}
|
||||
|
||||
actual fun constructUrl(baseUrl: String, path: String, file: String?): String {
|
||||
actual fun constructUrl(
|
||||
baseUrl: String,
|
||||
path: String,
|
||||
file: String?,
|
||||
): String {
|
||||
return if (file == null || file == "null" || file.isEmpty()) {
|
||||
""
|
||||
} else {
|
||||
@ -47,4 +51,4 @@ actual fun constructUrl(baseUrl: String, path: String, file: String?): String {
|
||||
|
||||
baseUriBuilder.toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ package bou.amine.apps.readerforselfossv2.DI
|
||||
|
||||
import bou.amine.apps.readerforselfossv2.rest.MercuryApi
|
||||
import bou.amine.apps.readerforselfossv2.rest.SelfossApi
|
||||
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
||||
import org.kodein.di.DI
|
||||
import org.kodein.di.bind
|
||||
import org.kodein.di.instance
|
||||
@ -11,4 +10,4 @@ import org.kodein.di.singleton
|
||||
val networkModule by DI.Module {
|
||||
bind<SelfossApi>() with singleton { SelfossApi(instance()) }
|
||||
bind<MercuryApi>() with singleton { MercuryApi() }
|
||||
}
|
||||
}
|
||||
|
@ -4,4 +4,4 @@ import com.squareup.sqldelight.db.SqlDriver
|
||||
|
||||
expect class DriverFactory {
|
||||
fun createDriver(): SqlDriver
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ package bou.amine.apps.readerforselfossv2.model
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
class MercuryModel {
|
||||
|
||||
@Serializable
|
||||
class ParsedContent(
|
||||
val title: String? = null,
|
||||
@ -12,6 +11,6 @@ class MercuryModel {
|
||||
val url: String? = null,
|
||||
val error: Boolean? = null,
|
||||
val message: String? = null,
|
||||
val failed: Boolean? = null
|
||||
val failed: Boolean? = null,
|
||||
)
|
||||
}
|
||||
|
@ -1,3 +1,3 @@
|
||||
package bou.amine.apps.readerforselfossv2.model
|
||||
|
||||
class NetworkUnavailableException : Exception()
|
||||
class NetworkUnavailableException : Exception()
|
||||
|
@ -18,4 +18,4 @@ class StatusAndData<T>(val success: Boolean, val data: T? = null) {
|
||||
return StatusAndData(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,32 +13,31 @@ import kotlinx.serialization.encoding.encodeCollection
|
||||
import kotlinx.serialization.json.*
|
||||
|
||||
class SelfossModel {
|
||||
|
||||
@Serializable
|
||||
data class Tag(
|
||||
val tag: String,
|
||||
val color: String,
|
||||
val unread: Int
|
||||
val unread: Int,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
class Stats(
|
||||
val total: Int,
|
||||
val unread: Int? = null,
|
||||
val starred: Int? = null
|
||||
val starred: Int? = null,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class Spout(
|
||||
val name: String,
|
||||
val description: String
|
||||
val description: String,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class ApiInformation(
|
||||
val version: String? = null,
|
||||
val apiversion: String? = null,
|
||||
val configuration: ApiConfiguration? = null
|
||||
val configuration: ApiConfiguration? = null,
|
||||
) {
|
||||
fun getApiMajorVersion(): Int {
|
||||
var versionNumber = 0
|
||||
@ -56,7 +55,7 @@ class SelfossModel {
|
||||
@Serializable(with = BooleanSerializer::class)
|
||||
val publicMode: Boolean? = null,
|
||||
@Serializable(with = BooleanSerializer::class)
|
||||
val authEnabled: Boolean? = null
|
||||
val authEnabled: Boolean? = null,
|
||||
) {
|
||||
fun isAuthEnabled() = authEnabled ?: true
|
||||
|
||||
@ -77,8 +76,8 @@ class SelfossModel {
|
||||
override var title: String,
|
||||
override var unread: Int? = null,
|
||||
override var error: String? = null,
|
||||
override var icon: String? = null
|
||||
) : Source
|
||||
override var icon: String? = null,
|
||||
) : Source
|
||||
|
||||
@Serializable
|
||||
data class SourceDetail(
|
||||
@ -90,13 +89,14 @@ class SelfossModel {
|
||||
var spout: String? = null,
|
||||
override var error: String? = null,
|
||||
override var icon: String? = null,
|
||||
var params: SourceParams? = null
|
||||
var params: SourceParams? = null,
|
||||
) : Source
|
||||
|
||||
@Serializable
|
||||
data class SourceParams(
|
||||
val url: String? = null
|
||||
val url: String? = null,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class Item(
|
||||
val id: Int,
|
||||
@ -113,15 +113,16 @@ class SelfossModel {
|
||||
val sourcetitle: String,
|
||||
@Serializable(with = TagsListSerializer::class)
|
||||
val tags: List<String>,
|
||||
val author: String? = null
|
||||
val author: String? = null,
|
||||
) {
|
||||
fun getLinkDecoded(): String {
|
||||
var stringUrl: String
|
||||
stringUrl = if (link.contains("//news.google.com/news/") && link.contains("&url=")) {
|
||||
link.substringAfter("&url=")
|
||||
} else {
|
||||
this.link.replace("&", "&")
|
||||
}
|
||||
stringUrl =
|
||||
if (link.contains("//news.google.com/news/") && link.contains("&url=")) {
|
||||
link.substringAfter("&url=")
|
||||
} else {
|
||||
this.link.replace("&", "&")
|
||||
}
|
||||
|
||||
// handle :443 => https
|
||||
if (stringUrl.contains(":443")) {
|
||||
@ -151,21 +152,22 @@ class SelfossModel {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// TODO: this seems to be super slow.
|
||||
object TagsListSerializer : KSerializer<List<String>> {
|
||||
override fun deserialize(decoder: Decoder): List<String> {
|
||||
return when(val json = ((decoder as JsonDecoder).decodeJsonElement())) {
|
||||
return when (val json = ((decoder as JsonDecoder).decodeJsonElement())) {
|
||||
is JsonArray -> json.toList().map { it.toString().replace("^\"|\"$".toRegex(), "") }
|
||||
else -> json.toString().split(",")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override val descriptor: SerialDescriptor
|
||||
get() = PrimitiveSerialDescriptor("tags", PrimitiveKind.STRING)
|
||||
|
||||
override fun serialize(encoder: Encoder, value: List<String>) {
|
||||
override fun serialize(
|
||||
encoder: Encoder,
|
||||
value: List<String>,
|
||||
) {
|
||||
encoder.encodeCollection(PrimitiveSerialDescriptor("tags", PrimitiveKind.STRING), value.size) { this.toString() }
|
||||
}
|
||||
}
|
||||
@ -183,7 +185,10 @@ class SelfossModel {
|
||||
override val descriptor: SerialDescriptor
|
||||
get() = PrimitiveSerialDescriptor("b", PrimitiveKind.BOOLEAN)
|
||||
|
||||
override fun serialize(encoder: Encoder, value: Boolean) {
|
||||
override fun serialize(
|
||||
encoder: Encoder,
|
||||
value: Boolean,
|
||||
) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
}
|
||||
|
@ -19,9 +19,8 @@ class Repository(
|
||||
private val api: SelfossApi,
|
||||
private val appSettingsService: AppSettingsService,
|
||||
val isConnectionAvailable: MutableStateFlow<Boolean>,
|
||||
private val db: ReaderForSelfossDB
|
||||
private val db: ReaderForSelfossDB,
|
||||
) {
|
||||
|
||||
var items = ArrayList<SelfossModel.Item>()
|
||||
var connectionMonitored = false
|
||||
|
||||
@ -53,20 +52,22 @@ class Repository(
|
||||
suspend fun getNewerItems(): ArrayList<SelfossModel.Item> {
|
||||
var fetchedItems: StatusAndData<List<SelfossModel.Item>> = StatusAndData.error()
|
||||
if (isNetworkAvailable()) {
|
||||
fetchedItems = api.getItems(
|
||||
displayedItems.type,
|
||||
offset = 0,
|
||||
tagFilter.value?.tag,
|
||||
sourceFilter.value?.id?.toLong(),
|
||||
searchFilter,
|
||||
null
|
||||
)
|
||||
fetchedItems =
|
||||
api.getItems(
|
||||
displayedItems.type,
|
||||
offset = 0,
|
||||
tagFilter.value?.tag,
|
||||
sourceFilter.value?.id?.toLong(),
|
||||
searchFilter,
|
||||
null,
|
||||
)
|
||||
} else if (appSettingsService.isItemCachingEnabled()) {
|
||||
var dbItems = getDBItems().filter {
|
||||
displayedItems == ItemType.ALL ||
|
||||
var dbItems =
|
||||
getDBItems().filter {
|
||||
displayedItems == ItemType.ALL ||
|
||||
(it.unread && displayedItems == ItemType.UNREAD) ||
|
||||
(it.starred && displayedItems == ItemType.STARRED)
|
||||
}
|
||||
}
|
||||
if (tagFilter.value != null) {
|
||||
dbItems = dbItems.filter { it.tags.split(',').contains(tagFilter.value!!.tag) }
|
||||
}
|
||||
@ -75,9 +76,10 @@ class Repository(
|
||||
}
|
||||
val itemsList = ArrayList(dbItems.map { it.toView() })
|
||||
itemsList.sortByDescending { DateUtils.parseDate(it.datetime) }
|
||||
fetchedItems = StatusAndData.succes(
|
||||
itemsList
|
||||
)
|
||||
fetchedItems =
|
||||
StatusAndData.succes(
|
||||
itemsList,
|
||||
)
|
||||
}
|
||||
|
||||
if (fetchedItems.success && fetchedItems.data != null) {
|
||||
@ -90,14 +92,15 @@ class Repository(
|
||||
var fetchedItems: StatusAndData<List<SelfossModel.Item>> = StatusAndData.error()
|
||||
if (isNetworkAvailable()) {
|
||||
val offset = items.size
|
||||
fetchedItems = api.getItems(
|
||||
displayedItems.type,
|
||||
offset,
|
||||
tagFilter.value?.tag,
|
||||
sourceFilter.value?.id?.toLong(),
|
||||
searchFilter,
|
||||
null
|
||||
)
|
||||
fetchedItems =
|
||||
api.getItems(
|
||||
displayedItems.type,
|
||||
offset,
|
||||
tagFilter.value?.tag,
|
||||
sourceFilter.value?.id?.toLong(),
|
||||
searchFilter,
|
||||
null,
|
||||
)
|
||||
} // When using the db cache, we load everything the first time, so there should be nothing more to load.
|
||||
|
||||
if (fetchedItems.success && fetchedItems.data != null) {
|
||||
@ -108,15 +111,16 @@ class Repository(
|
||||
|
||||
private suspend fun getMaxItemsForBackground(itemType: ItemType): List<SelfossModel.Item> {
|
||||
return if (isNetworkAvailable()) {
|
||||
val items = api.getItems(
|
||||
itemType.type,
|
||||
0,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
200
|
||||
)
|
||||
val items =
|
||||
api.getItems(
|
||||
itemType.type,
|
||||
0,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
200,
|
||||
)
|
||||
return if (items.success && items.data != null) {
|
||||
items.data
|
||||
} else {
|
||||
@ -374,7 +378,7 @@ class Repository(
|
||||
title: String,
|
||||
url: String,
|
||||
spout: String,
|
||||
tags: String
|
||||
tags: String,
|
||||
): Boolean {
|
||||
var response = false
|
||||
if (isNetworkAvailable()) {
|
||||
@ -384,7 +388,10 @@ class Repository(
|
||||
return response
|
||||
}
|
||||
|
||||
suspend fun deleteSource(id: Int, title: String): Boolean {
|
||||
suspend fun deleteSource(
|
||||
id: Int,
|
||||
title: String,
|
||||
): Boolean {
|
||||
var success = false
|
||||
if (isNetworkAvailable()) {
|
||||
val response = api.deleteSource(id)
|
||||
@ -456,7 +463,11 @@ class Repository(
|
||||
}
|
||||
}
|
||||
|
||||
fun refreshLoginInformation(url: String, login: String, password: String) {
|
||||
fun refreshLoginInformation(
|
||||
url: String,
|
||||
login: String,
|
||||
password: String,
|
||||
) {
|
||||
appSettingsService.refreshLoginInformation(url, login, password)
|
||||
baseUrl = url
|
||||
api.refreshLoginInformation()
|
||||
@ -474,9 +485,10 @@ class Repository(
|
||||
// Check if we're accessing the instance in public mode
|
||||
// This happens when auth and public mode are enabled but
|
||||
// no credentials are provided to login
|
||||
if (appSettingsService.getUserName().isEmpty()
|
||||
&& fetchedInformation.data.getApiConfiguration().isAuthEnabled()
|
||||
&& fetchedInformation.data.getApiConfiguration().isPublicModeEnabled()) {
|
||||
if (appSettingsService.getUserName().isEmpty() &&
|
||||
fetchedInformation.data.getApiConfiguration().isAuthEnabled() &&
|
||||
fetchedInformation.data.getApiConfiguration().isPublicModeEnabled()
|
||||
) {
|
||||
appSettingsService.updatePublicAccess(true)
|
||||
}
|
||||
}
|
||||
@ -485,11 +497,9 @@ class Repository(
|
||||
|
||||
fun isNetworkAvailable() = isConnectionAvailable.value && !offlineOverride
|
||||
|
||||
private fun getDBActions(): List<ACTION> =
|
||||
db.actionsQueries.actions().executeAsList()
|
||||
private fun getDBActions(): List<ACTION> = db.actionsQueries.actions().executeAsList()
|
||||
|
||||
private fun deleteDBAction(action: ACTION) =
|
||||
db.actionsQueries.deleteAction(action.id)
|
||||
private fun deleteDBAction(action: ACTION) = db.actionsQueries.deleteAction(action.id)
|
||||
|
||||
private fun getDBTags(): List<TAG> = db.tagsQueries.tags().executeAsList()
|
||||
|
||||
@ -530,9 +540,8 @@ class Repository(
|
||||
read: Boolean = false,
|
||||
unread: Boolean = false,
|
||||
starred: Boolean = false,
|
||||
unstarred: Boolean = false
|
||||
) =
|
||||
db.actionsQueries.insertAction(articleid, read, unread, starred, unstarred)
|
||||
unstarred: Boolean = false,
|
||||
) = db.actionsQueries.insertAction(articleid, read, unread, starred, unstarred)
|
||||
|
||||
private fun updateDBItem(item: SelfossModel.Item) =
|
||||
db.itemsQueries.updateItem(
|
||||
@ -547,7 +556,7 @@ class Repository(
|
||||
item.sourcetitle,
|
||||
item.tags.joinToString(","),
|
||||
item.author,
|
||||
item.id.toString()
|
||||
item.id.toString(),
|
||||
)
|
||||
|
||||
suspend fun tryToCacheItemsAndGetNewOnes(): List<SelfossModel.Item> {
|
||||
@ -564,32 +573,38 @@ class Repository(
|
||||
}
|
||||
|
||||
suspend fun handleDBActions() {
|
||||
|
||||
val actions: List<ACTION> = getDBActions()
|
||||
|
||||
actions.forEach { action ->
|
||||
when {
|
||||
action.read -> doAndReportOnFail(
|
||||
markAsReadById(action.articleid.toInt()),
|
||||
action
|
||||
)
|
||||
action.unread -> doAndReportOnFail(
|
||||
unmarkAsReadById(action.articleid.toInt()),
|
||||
action
|
||||
)
|
||||
action.starred -> doAndReportOnFail(
|
||||
starrById(action.articleid.toInt()),
|
||||
action
|
||||
)
|
||||
action.unstarred -> doAndReportOnFail(
|
||||
unstarrById(action.articleid.toInt()),
|
||||
action
|
||||
)
|
||||
action.read ->
|
||||
doAndReportOnFail(
|
||||
markAsReadById(action.articleid.toInt()),
|
||||
action,
|
||||
)
|
||||
action.unread ->
|
||||
doAndReportOnFail(
|
||||
unmarkAsReadById(action.articleid.toInt()),
|
||||
action,
|
||||
)
|
||||
action.starred ->
|
||||
doAndReportOnFail(
|
||||
starrById(action.articleid.toInt()),
|
||||
action,
|
||||
)
|
||||
action.unstarred ->
|
||||
doAndReportOnFail(
|
||||
unstarrById(action.articleid.toInt()),
|
||||
action,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun doAndReportOnFail(result: Boolean, action: ACTION) {
|
||||
private fun doAndReportOnFail(
|
||||
result: Boolean,
|
||||
action: ACTION,
|
||||
) {
|
||||
if (result) {
|
||||
deleteDBAction(action)
|
||||
}
|
||||
@ -626,4 +641,4 @@ class Repository(
|
||||
fun getSelectedSource(): SelfossModel.SourceDetail? {
|
||||
return _selectedSource
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,25 +11,27 @@ import io.ktor.serialization.kotlinx.json.*
|
||||
import kotlinx.serialization.json.Json
|
||||
|
||||
class MercuryApi() {
|
||||
|
||||
var client = createHttpClient()
|
||||
|
||||
private fun createHttpClient(): HttpClient {
|
||||
return HttpClient {
|
||||
install(ContentNegotiation) {
|
||||
install(HttpCache)
|
||||
json(Json {
|
||||
prettyPrint = true
|
||||
isLenient = true
|
||||
ignoreUnknownKeys = true
|
||||
})
|
||||
json(
|
||||
Json {
|
||||
prettyPrint = true
|
||||
isLenient = true
|
||||
ignoreUnknownKeys = true
|
||||
},
|
||||
)
|
||||
}
|
||||
install(Logging) {
|
||||
logger = object : Logger {
|
||||
override fun log(message: String) {
|
||||
Napier.d(message, tag = "LogMercuryCalls")
|
||||
logger =
|
||||
object : Logger {
|
||||
override fun log(message: String) {
|
||||
Napier.d(message, tag = "LogMercuryCalls")
|
||||
}
|
||||
}
|
||||
}
|
||||
level = LogLevel.INFO
|
||||
}
|
||||
expectSuccess = false
|
||||
@ -37,7 +39,9 @@ class MercuryApi() {
|
||||
}
|
||||
|
||||
suspend fun query(url: String): StatusAndData<MercuryModel.ParsedContent> =
|
||||
bodyOrFailure(client.get("https://amine-louveau.fr/parser.php") {
|
||||
parameter("link", url)
|
||||
})
|
||||
}
|
||||
bodyOrFailure(
|
||||
client.get("https://amine-louveau.fr/parser.php") {
|
||||
parameter("link", url)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
@ -10,7 +10,6 @@ import io.ktor.client.request.forms.*
|
||||
import io.ktor.client.statement.*
|
||||
import io.ktor.http.*
|
||||
|
||||
|
||||
suspend fun responseOrSuccessIf404(r: HttpResponse?): SuccessResponse {
|
||||
return if (r != null && r.status === HttpStatusCode.NotFound) {
|
||||
SuccessResponse(true)
|
||||
@ -40,7 +39,7 @@ suspend inline fun <reified T> bodyOrFailure(r: HttpResponse?): StatusAndData<T>
|
||||
|
||||
inline fun tryToRequest(
|
||||
requestType: String,
|
||||
fn: () -> HttpResponse
|
||||
fn: () -> HttpResponse,
|
||||
): HttpResponse? {
|
||||
var response: HttpResponse? = null
|
||||
try {
|
||||
@ -53,30 +52,46 @@ inline fun tryToRequest(
|
||||
|
||||
suspend inline fun HttpClient.tryToGet(
|
||||
urlString: String,
|
||||
crossinline block: HttpRequestBuilder.() -> Unit = {}
|
||||
): HttpResponse? = tryToRequest("Get") { return this.get { url(urlString); block() } }
|
||||
|
||||
crossinline block: HttpRequestBuilder.() -> Unit = {},
|
||||
): HttpResponse? =
|
||||
tryToRequest("Get") {
|
||||
return this.get {
|
||||
url(urlString)
|
||||
block()
|
||||
}
|
||||
}
|
||||
|
||||
suspend inline fun HttpClient.tryToPost(
|
||||
urlString: String,
|
||||
block: HttpRequestBuilder.() -> Unit = {}
|
||||
): HttpResponse? = tryToRequest("Post") { return this.post { url(urlString); block() } }
|
||||
block: HttpRequestBuilder.() -> Unit = {},
|
||||
): HttpResponse? =
|
||||
tryToRequest("Post") {
|
||||
return this.post {
|
||||
url(urlString)
|
||||
block()
|
||||
}
|
||||
}
|
||||
|
||||
suspend inline fun HttpClient.tryToDelete(
|
||||
urlString: String,
|
||||
block: HttpRequestBuilder.() -> Unit = {}
|
||||
): HttpResponse? = tryToRequest("Delete") { return this.delete { url(urlString); block() } }
|
||||
|
||||
block: HttpRequestBuilder.() -> Unit = {},
|
||||
): HttpResponse? =
|
||||
tryToRequest("Delete") {
|
||||
return this.delete {
|
||||
url(urlString)
|
||||
block()
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun HttpClient.tryToSubmitForm(
|
||||
url: String,
|
||||
formParameters: Parameters = Parameters.Empty,
|
||||
encodeInQuery: Boolean = false,
|
||||
block: HttpRequestBuilder.() -> Unit = {}
|
||||
block: HttpRequestBuilder.() -> Unit = {},
|
||||
): HttpResponse? =
|
||||
tryToRequest("SubmitForm") {
|
||||
return this.submitForm(formParameters, encodeInQuery) {
|
||||
url(url)
|
||||
block()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -36,8 +36,8 @@ import kotlinx.serialization.json.Json
|
||||
expect fun setupInsecureHTTPEngine(config: CIOEngineConfig)
|
||||
|
||||
class SelfossApi(private val appSettingsService: AppSettingsService) {
|
||||
|
||||
var client = createHttpClient()
|
||||
|
||||
fun createHttpClient() =
|
||||
HttpClient(CIO) {
|
||||
if (appSettingsService.getSelfSigned()) {
|
||||
@ -47,19 +47,22 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
|
||||
}
|
||||
install(ContentNegotiation) {
|
||||
install(HttpCache)
|
||||
json(Json {
|
||||
prettyPrint = true
|
||||
isLenient = true
|
||||
ignoreUnknownKeys = true
|
||||
explicitNulls = false
|
||||
})
|
||||
json(
|
||||
Json {
|
||||
prettyPrint = true
|
||||
isLenient = true
|
||||
ignoreUnknownKeys = true
|
||||
explicitNulls = false
|
||||
},
|
||||
)
|
||||
}
|
||||
install(Logging) {
|
||||
logger = object : Logger {
|
||||
override fun log(message: String) {
|
||||
Napier.d(message, tag = "LogApiCalls")
|
||||
logger =
|
||||
object : Logger {
|
||||
override fun log(message: String) {
|
||||
Napier.d(message, tag = "LogApiCalls")
|
||||
}
|
||||
}
|
||||
}
|
||||
level = LogLevel.INFO
|
||||
}
|
||||
install(HttpTimeout) {
|
||||
@ -83,8 +86,7 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
|
||||
expectSuccess = false
|
||||
}
|
||||
|
||||
fun url(path: String) =
|
||||
"${appSettingsService.getBaseUrl()}$path"
|
||||
fun url(path: String) = "${appSettingsService.getBaseUrl()}$path"
|
||||
|
||||
fun refreshLoginInformation() {
|
||||
appSettingsService.refreshApiSettings()
|
||||
@ -100,12 +102,15 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
|
||||
|
||||
// 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() =
|
||||
appSettingsService.getUserName().isNotEmpty() && appSettingsService.getPassword()
|
||||
.isNotEmpty()
|
||||
appSettingsService.getUserName().isNotEmpty() &&
|
||||
appSettingsService.getPassword()
|
||||
.isNotEmpty()
|
||||
|
||||
suspend fun login(): SuccessResponse =
|
||||
if (appSettingsService.getUserName().isNotEmpty() && appSettingsService.getPassword()
|
||||
if (appSettingsService.getUserName().isNotEmpty() &&
|
||||
appSettingsService.getPassword()
|
||||
.isNotEmpty()
|
||||
) {
|
||||
if (shouldHavePostLogin()) {
|
||||
@ -117,30 +122,49 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
|
||||
SuccessResponse(true)
|
||||
}
|
||||
|
||||
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 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 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() =
|
||||
appSettingsService.getApiVersion() >= 5 // We are missing 4.1.0
|
||||
private fun shouldHaveNewLogout() = appSettingsService.getApiVersion() >= 5 // We are missing 4.1.0
|
||||
|
||||
suspend fun logout(): SuccessResponse =
|
||||
if (shouldHaveNewLogout()) {
|
||||
@ -150,23 +174,42 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
|
||||
}
|
||||
|
||||
private suspend fun maybeLogoutIfAvailable() =
|
||||
responseOrSuccessIf404(client.tryToGet(url("/logout")) {
|
||||
if (appSettingsService.getBasicUserName().isNotEmpty() && appSettingsService.getBasicPassword().isNotEmpty()) {
|
||||
headers {
|
||||
append(HttpHeaders.Authorization, constructBasicAuthValue(BasicAuthCredentials(username = appSettingsService.getBasicUserName(), password = appSettingsService.getBasicPassword()))
|
||||
)
|
||||
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")) {
|
||||
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")) {
|
||||
if (appSettingsService.getBasicUserName().isNotEmpty() && appSettingsService.getBasicPassword().isNotEmpty()) {
|
||||
headers {
|
||||
append(
|
||||
HttpHeaders.Authorization,
|
||||
constructBasicAuthValue(
|
||||
BasicAuthCredentials(
|
||||
username = appSettingsService.getBasicUserName(),
|
||||
password = appSettingsService.getBasicPassword(),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
suspend fun getItems(
|
||||
type: String,
|
||||
@ -175,213 +218,340 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
|
||||
source: Long?,
|
||||
search: String?,
|
||||
updatedSince: String?,
|
||||
items: Int? = null
|
||||
items: Int? = null,
|
||||
): StatusAndData<List<SelfossModel.Item>> =
|
||||
bodyOrFailure(client.tryToGet(url("/items")) {
|
||||
if (!shouldHavePostLogin()) {
|
||||
parameter("username", appSettingsService.getUserName())
|
||||
parameter("password", appSettingsService.getPassword())
|
||||
}
|
||||
parameter("type", type)
|
||||
parameter("tag", tag)
|
||||
parameter("source", source)
|
||||
parameter("search", search)
|
||||
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>> =
|
||||
bodyOrFailure(client.get(url("/items")) {
|
||||
if (!shouldHavePostLogin()) {
|
||||
parameter("username", appSettingsService.getUserName())
|
||||
parameter("password", appSettingsService.getPassword())
|
||||
}
|
||||
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> =
|
||||
bodyOrFailure(client.tryToGet(url("/stats")) {
|
||||
if (!shouldHavePostLogin()) {
|
||||
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>> =
|
||||
bodyOrFailure(client.tryToGet(url("/tags")) {
|
||||
if (!shouldHavePostLogin()) {
|
||||
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> =
|
||||
bodyOrFailure(client.tryToGet(url("/update")) {
|
||||
if (!shouldHavePostLogin()) {
|
||||
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>> =
|
||||
bodyOrFailure(client.tryToGet(url("/sources/spouts")) {
|
||||
if (!shouldHavePostLogin()) {
|
||||
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>> =
|
||||
bodyOrFailure(client.tryToGet(url("/sources/stats")) {
|
||||
if (!shouldHavePostLogin()) {
|
||||
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>> =
|
||||
bodyOrFailure(client.tryToGet(url("/sources/list")) {
|
||||
if (!shouldHavePostLogin()) {
|
||||
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")) {
|
||||
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")) {
|
||||
if (!shouldHavePostLogin()) {
|
||||
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 =
|
||||
maybeResponse(client.tryToPost(url("/unmark/$id")) {
|
||||
if (!shouldHavePostLogin()) {
|
||||
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 =
|
||||
maybeResponse(client.tryToPost(url("/starr/$id")) {
|
||||
if (!shouldHavePostLogin()) {
|
||||
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 =
|
||||
maybeResponse(client.tryToPost(url("/unstarr/$id")) {
|
||||
if (!shouldHavePostLogin()) {
|
||||
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 =
|
||||
maybeResponse(client.tryToSubmitForm(
|
||||
url = url("/mark"),
|
||||
formParameters = Parameters.build {
|
||||
bodyOrFailure(
|
||||
client.tryToGet(url("/items")) {
|
||||
if (!shouldHavePostLogin()) {
|
||||
append("username", appSettingsService.getUserName())
|
||||
append("password", appSettingsService.getPassword())
|
||||
parameter("username", appSettingsService.getUserName())
|
||||
parameter("password", appSettingsService.getPassword())
|
||||
}
|
||||
ids.map { append("ids[]", it) }
|
||||
},
|
||||
block = {
|
||||
parameter("type", type)
|
||||
parameter("tag", tag)
|
||||
parameter("source", source)
|
||||
parameter("search", search)
|
||||
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()))
|
||||
append(
|
||||
HttpHeaders.Authorization,
|
||||
constructBasicAuthValue(
|
||||
BasicAuthCredentials(
|
||||
username = appSettingsService.getBasicUserName(),
|
||||
password = appSettingsService.getBasicPassword(),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
))
|
||||
},
|
||||
)
|
||||
|
||||
suspend fun getItemsWithoutCatch(): StatusAndData<List<SelfossModel.Item>> =
|
||||
bodyOrFailure(
|
||||
client.get(url("/items")) {
|
||||
if (!shouldHavePostLogin()) {
|
||||
parameter("username", appSettingsService.getUserName())
|
||||
parameter("password", appSettingsService.getPassword())
|
||||
}
|
||||
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> =
|
||||
bodyOrFailure(
|
||||
client.tryToGet(url("/stats")) {
|
||||
if (!shouldHavePostLogin()) {
|
||||
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>> =
|
||||
bodyOrFailure(
|
||||
client.tryToGet(url("/tags")) {
|
||||
if (!shouldHavePostLogin()) {
|
||||
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> =
|
||||
bodyOrFailure(
|
||||
client.tryToGet(url("/update")) {
|
||||
if (!shouldHavePostLogin()) {
|
||||
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>> =
|
||||
bodyOrFailure(
|
||||
client.tryToGet(url("/sources/spouts")) {
|
||||
if (!shouldHavePostLogin()) {
|
||||
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>> =
|
||||
bodyOrFailure(
|
||||
client.tryToGet(url("/sources/stats")) {
|
||||
if (!shouldHavePostLogin()) {
|
||||
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>> =
|
||||
bodyOrFailure(
|
||||
client.tryToGet(url("/sources/list")) {
|
||||
if (!shouldHavePostLogin()) {
|
||||
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")) {
|
||||
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")) {
|
||||
if (!shouldHavePostLogin()) {
|
||||
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 =
|
||||
maybeResponse(
|
||||
client.tryToPost(url("/unmark/$id")) {
|
||||
if (!shouldHavePostLogin()) {
|
||||
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 =
|
||||
maybeResponse(
|
||||
client.tryToPost(url("/starr/$id")) {
|
||||
if (!shouldHavePostLogin()) {
|
||||
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 =
|
||||
maybeResponse(
|
||||
client.tryToPost(url("/unstarr/$id")) {
|
||||
if (!shouldHavePostLogin()) {
|
||||
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 =
|
||||
maybeResponse(
|
||||
client.tryToSubmitForm(
|
||||
url = url("/mark"),
|
||||
formParameters =
|
||||
Parameters.build {
|
||||
if (!shouldHavePostLogin()) {
|
||||
append("username", appSettingsService.getUserName())
|
||||
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(),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suspend fun createSourceForVersion(
|
||||
title: String,
|
||||
@ -394,7 +564,7 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
|
||||
createSource("tags[]", title, url, spout, tags)
|
||||
} else {
|
||||
createSource("tags", title, url, spout, tags)
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
private suspend fun createSource(
|
||||
@ -402,28 +572,36 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
|
||||
title: String,
|
||||
url: String,
|
||||
spout: String,
|
||||
tags: String
|
||||
tags: String,
|
||||
): HttpResponse? =
|
||||
client.tryToSubmitForm(
|
||||
url = url("/source"),
|
||||
formParameters = Parameters.build {
|
||||
if (!shouldHavePostLogin()) {
|
||||
append("username", appSettingsService.getUserName())
|
||||
append("password", appSettingsService.getPassword())
|
||||
}
|
||||
append("title", title)
|
||||
append("url", url)
|
||||
append("spout", spout)
|
||||
append(tagsParamName, tags)
|
||||
},
|
||||
formParameters =
|
||||
Parameters.build {
|
||||
if (!shouldHavePostLogin()) {
|
||||
append("username", appSettingsService.getUserName())
|
||||
append("password", appSettingsService.getPassword())
|
||||
}
|
||||
append("title", title)
|
||||
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()))
|
||||
append(
|
||||
HttpHeaders.Authorization,
|
||||
constructBasicAuthValue(
|
||||
BasicAuthCredentials(
|
||||
username = appSettingsService.getBasicUserName(),
|
||||
password = appSettingsService.getBasicPassword(),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
suspend fun updateSourceForVersion(
|
||||
@ -431,14 +609,14 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
|
||||
title: String,
|
||||
url: String,
|
||||
spout: String,
|
||||
tags: String
|
||||
tags: String,
|
||||
): SuccessResponse =
|
||||
maybeResponse(
|
||||
if (appSettingsService.getApiVersion() > 1) {
|
||||
updateSource(id, "tags[]", title, url, spout, tags)
|
||||
} else {
|
||||
updateSource(id, "tags", title, url, spout, tags)
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
private suspend fun updateSource(
|
||||
@ -451,44 +629,54 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
|
||||
): HttpResponse? =
|
||||
client.tryToSubmitForm(
|
||||
url = url("/source/$id"),
|
||||
formParameters = Parameters.build {
|
||||
if (!shouldHavePostLogin()) {
|
||||
append("username", appSettingsService.getUserName())
|
||||
append("password", appSettingsService.getPassword())
|
||||
}
|
||||
append("title", title)
|
||||
append("url", url)
|
||||
append("spout", spout)
|
||||
append(tagsParamName, tags)
|
||||
},
|
||||
formParameters =
|
||||
Parameters.build {
|
||||
if (!shouldHavePostLogin()) {
|
||||
append("username", appSettingsService.getUserName())
|
||||
append("password", appSettingsService.getPassword())
|
||||
}
|
||||
append("title", title)
|
||||
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()))
|
||||
append(
|
||||
HttpHeaders.Authorization,
|
||||
constructBasicAuthValue(
|
||||
BasicAuthCredentials(
|
||||
username = appSettingsService.getBasicUserName(),
|
||||
password = appSettingsService.getBasicPassword(),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
suspend fun deleteSource(id: Int): SuccessResponse =
|
||||
maybeResponse(client.tryToDelete(url("/source/$id")) {
|
||||
if (!shouldHavePostLogin()) {
|
||||
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()
|
||||
)
|
||||
)
|
||||
)
|
||||
maybeResponse(
|
||||
client.tryToDelete(url("/source/$id")) {
|
||||
if (!shouldHavePostLogin()) {
|
||||
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(),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
@ -13,58 +13,93 @@ class ACRASettings : Settings {
|
||||
// Nothing
|
||||
}
|
||||
|
||||
override fun getBoolean(key: String, defaultValue: Boolean): Boolean = false
|
||||
override fun getBoolean(
|
||||
key: String,
|
||||
defaultValue: Boolean,
|
||||
): Boolean = false
|
||||
|
||||
override fun getBooleanOrNull(key: String): Boolean? = null
|
||||
|
||||
override fun getDouble(key: String, defaultValue: Double): Double = 0.0
|
||||
override fun getDouble(
|
||||
key: String,
|
||||
defaultValue: Double,
|
||||
): Double = 0.0
|
||||
|
||||
override fun getDoubleOrNull(key: String): Double? = null
|
||||
|
||||
override fun getFloat(key: String, defaultValue: Float): Float = 0.0F
|
||||
override fun getFloat(
|
||||
key: String,
|
||||
defaultValue: Float,
|
||||
): Float = 0.0F
|
||||
|
||||
override fun getFloatOrNull(key: String): Float? = null
|
||||
|
||||
override fun getInt(key: String, defaultValue: Int): Int = 0
|
||||
override fun getInt(
|
||||
key: String,
|
||||
defaultValue: Int,
|
||||
): Int = 0
|
||||
|
||||
override fun getIntOrNull(key: String): Int? = null
|
||||
|
||||
override fun getLong(key: String, defaultValue: Long): Long = 0
|
||||
override fun getLong(
|
||||
key: String,
|
||||
defaultValue: Long,
|
||||
): Long = 0
|
||||
|
||||
override fun getLongOrNull(key: String): Long? = null
|
||||
|
||||
override fun getString(key: String, defaultValue: String): String = "0"
|
||||
override fun getString(
|
||||
key: String,
|
||||
defaultValue: String,
|
||||
): String = "0"
|
||||
|
||||
override fun getStringOrNull(key: String): String? = null
|
||||
|
||||
override fun hasKey(key: String): Boolean = false
|
||||
|
||||
override fun putBoolean(key: String, value: Boolean) {
|
||||
override fun putBoolean(
|
||||
key: String,
|
||||
value: Boolean,
|
||||
) {
|
||||
// Nothing
|
||||
}
|
||||
|
||||
override fun putDouble(key: String, value: Double) {
|
||||
override fun putDouble(
|
||||
key: String,
|
||||
value: Double,
|
||||
) {
|
||||
// Nothing
|
||||
}
|
||||
|
||||
override fun putFloat(key: String, value: Float) {
|
||||
override fun putFloat(
|
||||
key: String,
|
||||
value: Float,
|
||||
) {
|
||||
// Nothing
|
||||
}
|
||||
|
||||
override fun putInt(key: String, value: Int) {
|
||||
override fun putInt(
|
||||
key: String,
|
||||
value: Int,
|
||||
) {
|
||||
// Nothing
|
||||
}
|
||||
|
||||
override fun putLong(key: String, value: Long) {
|
||||
override fun putLong(
|
||||
key: String,
|
||||
value: Long,
|
||||
) {
|
||||
// Nothing
|
||||
}
|
||||
|
||||
override fun putString(key: String, value: String) {
|
||||
override fun putString(
|
||||
key: String,
|
||||
value: String,
|
||||
) {
|
||||
// Nothing
|
||||
}
|
||||
|
||||
override fun remove(key: String) {
|
||||
// Nothing
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,12 @@ package bou.amine.apps.readerforselfossv2.service
|
||||
import com.russhwolf.settings.Settings
|
||||
|
||||
class AppSettingsService(acraSenderServiceProcess: Boolean = false) {
|
||||
val settings: Settings = if (acraSenderServiceProcess) { ACRASettings() } else { Settings() }
|
||||
val settings: Settings =
|
||||
if (acraSenderServiceProcess) {
|
||||
ACRASettings()
|
||||
} else {
|
||||
Settings()
|
||||
}
|
||||
|
||||
// Api related
|
||||
private var _apiVersion: Int = -1
|
||||
@ -38,7 +43,6 @@ class AppSettingsService(acraSenderServiceProcess: Boolean = false) {
|
||||
private var _font: String = ""
|
||||
private var _theme: Int? = null
|
||||
|
||||
|
||||
init {
|
||||
refreshApiSettings()
|
||||
refreshUserSettings()
|
||||
@ -52,7 +56,6 @@ class AppSettingsService(acraSenderServiceProcess: Boolean = false) {
|
||||
return _apiVersion
|
||||
}
|
||||
|
||||
|
||||
fun updateApiVersion(apiMajorVersion: Int) {
|
||||
settings.putInt(API_VERSION_MAJOR, apiMajorVersion)
|
||||
refreshApiVersion()
|
||||
@ -137,13 +140,13 @@ class AppSettingsService(acraSenderServiceProcess: Boolean = false) {
|
||||
}
|
||||
|
||||
private fun refreshItemsNumber() {
|
||||
_itemsNumber = try {
|
||||
settings.getString(API_ITEMS_NUMBER, "20").toInt()
|
||||
} catch (e: Exception) {
|
||||
settings.remove(API_ITEMS_NUMBER)
|
||||
20
|
||||
}
|
||||
|
||||
_itemsNumber =
|
||||
try {
|
||||
settings.getString(API_ITEMS_NUMBER, "20").toInt()
|
||||
} catch (e: Exception) {
|
||||
settings.remove(API_ITEMS_NUMBER)
|
||||
20
|
||||
}
|
||||
}
|
||||
|
||||
fun getApiTimeout(): Long {
|
||||
@ -156,18 +159,21 @@ class AppSettingsService(acraSenderServiceProcess: Boolean = false) {
|
||||
private fun secToMs(n: Long) = n * 1000
|
||||
|
||||
private fun refreshApiTimeout() {
|
||||
_apiTimeout = secToMs(try {
|
||||
val settingsTimeout = settings.getString(API_TIMEOUT, "60")
|
||||
if (settingsTimeout.toLong() > 0) {
|
||||
settingsTimeout.toLong()
|
||||
} else {
|
||||
settings.remove(API_TIMEOUT)
|
||||
60
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
settings.remove(API_TIMEOUT)
|
||||
60
|
||||
})
|
||||
_apiTimeout =
|
||||
secToMs(
|
||||
try {
|
||||
val settingsTimeout = settings.getString(API_TIMEOUT, "60")
|
||||
if (settingsTimeout.toLong() > 0) {
|
||||
settingsTimeout.toLong()
|
||||
} else {
|
||||
settings.remove(API_TIMEOUT)
|
||||
60
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
settings.remove(API_TIMEOUT)
|
||||
60
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
private fun refreshBaseUrl() {
|
||||
@ -200,6 +206,7 @@ class AppSettingsService(acraSenderServiceProcess: Boolean = false) {
|
||||
}
|
||||
return _articleViewer == true
|
||||
}
|
||||
|
||||
private fun refreshShouldBeCardViewEnabled() {
|
||||
_shouldBeCardView = settings.getBoolean(CARD_VIEW_ACTIVE, false)
|
||||
}
|
||||
@ -210,6 +217,7 @@ class AppSettingsService(acraSenderServiceProcess: Boolean = false) {
|
||||
}
|
||||
return _shouldBeCardView == true
|
||||
}
|
||||
|
||||
private fun refreshDisplayUnreadCountEnabled() {
|
||||
_displayUnreadCount = settings.getBoolean(DISPLAY_UNREAD_COUNT, true)
|
||||
}
|
||||
@ -220,6 +228,7 @@ class AppSettingsService(acraSenderServiceProcess: Boolean = false) {
|
||||
}
|
||||
return _displayUnreadCount == true
|
||||
}
|
||||
|
||||
private fun refreshDisplayAllCountEnabled() {
|
||||
_displayAllCount = settings.getBoolean(DISPLAY_OTHER_COUNT, false)
|
||||
}
|
||||
@ -230,6 +239,7 @@ class AppSettingsService(acraSenderServiceProcess: Boolean = false) {
|
||||
}
|
||||
return _displayAllCount == true
|
||||
}
|
||||
|
||||
private fun refreshFullHeightCardsEnabled() {
|
||||
_fullHeightCards = settings.getBoolean(FULL_HEIGHT_CARDS, false)
|
||||
}
|
||||
@ -240,6 +250,7 @@ class AppSettingsService(acraSenderServiceProcess: Boolean = false) {
|
||||
}
|
||||
return _fullHeightCards == true
|
||||
}
|
||||
|
||||
private fun refreshUpdateSourcesEnabled() {
|
||||
_updateSources = settings.getBoolean(UPDATE_SOURCES, true)
|
||||
}
|
||||
@ -250,6 +261,7 @@ class AppSettingsService(acraSenderServiceProcess: Boolean = false) {
|
||||
}
|
||||
return _updateSources == true
|
||||
}
|
||||
|
||||
private fun refreshPeriodicRefreshEnabled() {
|
||||
_periodicRefresh = settings.getBoolean(PERIODIC_REFRESH, false)
|
||||
}
|
||||
@ -319,7 +331,6 @@ class AppSettingsService(acraSenderServiceProcess: Boolean = false) {
|
||||
return _notifyNewItems == true
|
||||
}
|
||||
|
||||
|
||||
private fun refreshMarkOnScrollEnabled() {
|
||||
_markOnScroll = settings.getBoolean(MARK_ON_SCROLL, false)
|
||||
}
|
||||
@ -331,7 +342,6 @@ class AppSettingsService(acraSenderServiceProcess: Boolean = false) {
|
||||
return _markOnScroll == true
|
||||
}
|
||||
|
||||
|
||||
private fun refreshActiveAllignment() {
|
||||
_activeAlignment = settings.getInt(TEXT_ALIGN, JUSTIFY)
|
||||
}
|
||||
@ -429,7 +439,7 @@ class AppSettingsService(acraSenderServiceProcess: Boolean = false) {
|
||||
fun refreshLoginInformation(
|
||||
url: String,
|
||||
login: String,
|
||||
password: String
|
||||
password: String,
|
||||
) {
|
||||
val regex = """\/\/(\D+):(\D+)@""".toRegex()
|
||||
val matchResult = regex.find(url)
|
||||
@ -537,6 +547,5 @@ class AppSettingsService(acraSenderServiceProcess: Boolean = false) {
|
||||
const val ITEMS_CACHING = "items_caching"
|
||||
|
||||
const val CURRENT_THEME = "currentMode"
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ fun TAG.toView(): SelfossModel.Tag =
|
||||
SelfossModel.Tag(
|
||||
this.name,
|
||||
this.color,
|
||||
this.unread.toInt()
|
||||
this.unread.toInt(),
|
||||
)
|
||||
|
||||
fun SOURCE.toView(): SelfossModel.SourceDetail =
|
||||
@ -21,7 +21,7 @@ fun SOURCE.toView(): SelfossModel.SourceDetail =
|
||||
this.spout,
|
||||
this.error,
|
||||
this.icon,
|
||||
if (this.url != null) SelfossModel.SourceParams(this.url) else null
|
||||
if (this.url != null) SelfossModel.SourceParams(this.url) else null,
|
||||
)
|
||||
|
||||
fun SelfossModel.SourceDetail.toEntity(): SOURCE =
|
||||
@ -32,14 +32,14 @@ fun SelfossModel.SourceDetail.toEntity(): SOURCE =
|
||||
this.spout.orEmpty(),
|
||||
this.error.orEmpty(),
|
||||
this.icon.orEmpty(),
|
||||
this.params?.url
|
||||
this.params?.url,
|
||||
)
|
||||
|
||||
fun SelfossModel.Tag.toEntity(): TAG =
|
||||
TAG(
|
||||
this.tag,
|
||||
this.color,
|
||||
this.unread.toLong()
|
||||
this.unread.toLong(),
|
||||
)
|
||||
|
||||
fun ITEM.toView(): SelfossModel.Item =
|
||||
@ -55,7 +55,7 @@ fun ITEM.toView(): SelfossModel.Item =
|
||||
this.link,
|
||||
this.sourcetitle,
|
||||
this.tags.split(","),
|
||||
this.author
|
||||
this.author,
|
||||
)
|
||||
|
||||
fun SelfossModel.Item.toEntity(): ITEM =
|
||||
@ -71,5 +71,5 @@ fun SelfossModel.Item.toEntity(): ITEM =
|
||||
this.link,
|
||||
this.sourcetitle.getHtmlDecoded(),
|
||||
this.tags.joinToString(","),
|
||||
this.author
|
||||
)
|
||||
this.author,
|
||||
)
|
||||
|
@ -3,9 +3,10 @@ package bou.amine.apps.readerforselfossv2.utils
|
||||
enum class ItemType(val position: Int, val type: String) {
|
||||
UNREAD(1, "unread"),
|
||||
ALL(2, "all"),
|
||||
STARRED(3, "starred");
|
||||
STARRED(3, "starred"),
|
||||
;
|
||||
|
||||
companion object {
|
||||
fun fromInt(value: Int) = values().first { it.position == value }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,4 +12,8 @@ expect fun SelfossModel.Item.getImages(): ArrayList<String>
|
||||
|
||||
expect fun SelfossModel.Source.getIcon(baseUrl: String): String
|
||||
|
||||
expect fun constructUrl(baseUrl: String, path: String, file: String?): String
|
||||
expect fun constructUrl(
|
||||
baseUrl: String,
|
||||
path: String,
|
||||
file: String?,
|
||||
): String
|
||||
|
@ -1,7 +1,6 @@
|
||||
package bou.amine.apps.readerforselfossv2.utils
|
||||
|
||||
fun String?.isEmptyOrNullOrNullString(): Boolean =
|
||||
this == null || this == "null" || this.isEmpty()
|
||||
fun String?.isEmptyOrNullOrNullString(): Boolean = this == null || this == "null" || this.isEmpty()
|
||||
|
||||
fun String.longHash(): Long {
|
||||
var h = 98764321261L
|
||||
@ -19,4 +18,4 @@ fun String.toStringUriWithHttp(): String =
|
||||
"http://" + this
|
||||
} else {
|
||||
this
|
||||
}
|
||||
}
|
||||
|
@ -7,4 +7,4 @@ actual class DriverFactory {
|
||||
actual fun createDriver(): SqlDriver {
|
||||
return NativeSqliteDriver(ReaderForSelfossDB.Schema, "ReaderForSelfossV2-IOS.db")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,4 +3,4 @@ package bou.amine.apps.readerforselfossv2.rest
|
||||
import io.ktor.client.engine.cio.CIOEngineConfig
|
||||
|
||||
actual fun setupInsecureHTTPEngine(config: CIOEngineConfig) {
|
||||
}
|
||||
}
|
||||
|
@ -10,4 +10,4 @@ actual class DateUtils {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,10 @@ actual fun SelfossModel.Source.getIcon(baseUrl: String): String {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
actual fun constructUrl(baseUrl: String, path: String, file: String?): String {
|
||||
actual fun constructUrl(
|
||||
baseUrl: String,
|
||||
path: String,
|
||||
file: String?,
|
||||
): String {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
}
|
||||
|
@ -7,4 +7,4 @@ actual class DriverFactory {
|
||||
actual fun createDriver(): SqlDriver {
|
||||
return NativeSqliteDriver(ReaderForSelfossDB.Schema, "ReaderForSelfossV2-IOS.db")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,4 +3,4 @@ package bou.amine.apps.readerforselfossv2.rest
|
||||
import io.ktor.client.engine.cio.CIOEngineConfig
|
||||
|
||||
actual fun setupInsecureHTTPEngine(config: CIOEngineConfig) {
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,5 @@
|
||||
package bou.amine.apps.readerforselfossv2.utils
|
||||
|
||||
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
||||
|
||||
actual class DateUtils {
|
||||
actual companion object {
|
||||
actual fun parseDate(dateString: String): Long {
|
||||
@ -12,5 +10,4 @@ actual class DateUtils {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,10 @@ actual fun SelfossModel.Source.getIcon(baseUrl: String): String {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
actual fun constructUrl(baseUrl: String, path: String, file: String?): String {
|
||||
actual fun constructUrl(
|
||||
baseUrl: String,
|
||||
path: String,
|
||||
file: String?,
|
||||
): String {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user