forked from Louvorg/ReaderForSelfoss-multiplatform
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 68aedb7641 | |||
| 754d526b49 | |||
| c458871569 | |||
| 056825aa0c | |||
| 16b19fc5ce | |||
| 4ad4a23ed8 | |||
| d8c215eacc | |||
| 2b446ab22b | |||
| a029d8a7dc | |||
| 4482234e1a | |||
| b5de30f561 | |||
| 70ad5f322c | |||
| d167092c83 | |||
| c4f4bafe85 | |||
| ed06b22a77 |
+37
-30
@@ -3,35 +3,38 @@ type: docker
|
||||
name: test
|
||||
|
||||
steps:
|
||||
- name: Lint
|
||||
failure: ignore
|
||||
image: mingc/android-build-box:latest
|
||||
commands:
|
||||
- echo "---------------------------------------------------------"
|
||||
- echo "Install linters..."
|
||||
- curl -sSLO https://github.com/pinterest/ktlint/releases/download/1.0.0/ktlint && chmod a+x ktlint && mv ktlint /usr/local/bin/
|
||||
- curl -sSLO https://github.com/detekt/detekt/releases/download/v1.23.1/detekt-cli-1.23.1.zip && unzip detekt-cli-1.23.1.zip
|
||||
- echo "---------------------------------------------------------"
|
||||
- echo "Linting..."
|
||||
- ktlint || true
|
||||
- echo "---------------------------------------------------------"
|
||||
- echo "Detecting..."
|
||||
- ./detekt-cli-1.23.1/bin/detekt-cli --all-rules || true
|
||||
- echo "---------------------------------------------------------"
|
||||
command_timeout: 1m
|
||||
- name: BuildAndTest
|
||||
image: mingc/android-build-box:latest
|
||||
commands:
|
||||
- echo "---------------------------------------------------------"
|
||||
- echo "Configure gradle..."
|
||||
- mkdir -p ~/.gradle && echo "org.gradle.daemon=false\nignoreGitVersion=true\npushCache=false\nsystemProp.org.gradle.internal.http.connectionTimeout=180000\nsystemProp.org.gradle.internal.http.socketTimeout=180000" >> ~/.gradle/gradle.properties
|
||||
- mkdir -p ~/.gradle && echo "org.gradle.daemon=false\nignoreGitVersion=true\nsystemProp.org.gradle.internal.http.connectionTimeout=180000\nsystemProp.org.gradle.internal.http.socketTimeout=180000" >> ~/.gradle/gradle.properties
|
||||
- echo "---------------------------------------------------------"
|
||||
- echo "Building..."
|
||||
- ./gradlew build -x test
|
||||
- echo "Configure java..."
|
||||
- . ~/.bash_profile
|
||||
- jenv global 17.0
|
||||
- java --version
|
||||
- date
|
||||
- echo "---------------------------------------------------------"
|
||||
- echo "Testing..."
|
||||
- echo "Building and testing..."
|
||||
- ./gradlew build
|
||||
- echo "---------------------------------------------------------"
|
||||
- ./gradlew koverMergedXmlReport
|
||||
environment:
|
||||
TZ: Europe/Paris
|
||||
SONAR_HOST_URL:
|
||||
from_secret: sonarScannerHostUrl
|
||||
SONAR_LOGIN:
|
||||
from_secret: sonarScannerLogin
|
||||
- name: Analyse
|
||||
image: kytay/sonar-node-plugin
|
||||
settings:
|
||||
sonar_host:
|
||||
from_secret: sonarScannerHostUrl
|
||||
sonar_token:
|
||||
from_secret: sonarScannerLogin
|
||||
use_node_version: 16.18.1
|
||||
sonar_debug: true
|
||||
sonar_project_settings: ./sonar-project.properties
|
||||
trigger:
|
||||
event:
|
||||
- push
|
||||
@@ -50,20 +53,24 @@ steps:
|
||||
- git fetch --tags -p
|
||||
- PREV=$(git describe --tags --abbrev=0)
|
||||
- ./build.sh --publish --from-ci
|
||||
- git remote add pushing https://$GITEA_USR:$GITEA_PASS@gitea.amine-louveau.fr/Louvorg/ReaderForSelfoss-multiplatform.git
|
||||
- VER=$(git describe --tags --abbrev=0)
|
||||
- CHANGELOG=$(git log $PREV..HEAD --pretty="- %s")
|
||||
- echo "**$VER**\n\n$CHANGELOG\n\n--------------------------------------------------------------------\n\n$(cat CHANGELOG.md)" > CHANGELOG.md
|
||||
- git add CHANGELOG.md
|
||||
- git commit -m "Changelog for $VER [CI SKIP]"
|
||||
- git push pushing master
|
||||
- git push pushing --tags
|
||||
environment:
|
||||
TZ: Europe/Paris
|
||||
GITEA_USR:
|
||||
from_secret: giteaUsr
|
||||
GITEA_PASS:
|
||||
from_secret: giteaPass
|
||||
|
||||
- name: git-push
|
||||
image: appleboy/drone-git-push
|
||||
settings:
|
||||
branch: master
|
||||
remote:
|
||||
from_secret: remoteUrl
|
||||
followtags: true
|
||||
ssh_key:
|
||||
from_secret: privateKey
|
||||
skip_verify: true
|
||||
|
||||
- name: scpFiles
|
||||
image: appleboy/drone-scp
|
||||
@@ -107,10 +114,10 @@ steps:
|
||||
- git fetch --tags
|
||||
- echo "---------------------------------------------------------"
|
||||
- echo "Configure gradle..."
|
||||
- mkdir -p ~/.gradle && echo "org.gradle.daemon=false\nignoreGitVersion=false\npushCache=false\nsystemProp.org.gradle.internal.http.connectionTimeout=180000\nsystemProp.org.gradle.internal.http.socketTimeout=180000" >> ~/.gradle/gradle.properties
|
||||
- mkdir -p ~/.gradle && echo "org.gradle.daemon=false\nignoreGitVersion=false\nsystemProp.org.gradle.internal.http.connectionTimeout=180000\nsystemProp.org.gradle.internal.http.socketTimeout=180000" >> ~/.gradle/gradle.properties
|
||||
- echo "---------------------------------------------------------"
|
||||
- echo "Generate APK"
|
||||
- ./gradlew :androidApp:assembleGithubConfigRelease -P pushCache=false
|
||||
- ./gradlew :androidApp:assembleGithubConfigRelease
|
||||
- echo "---------------------------------------------------------"
|
||||
- echo "Get Key"
|
||||
- wget https://amine-louveau.fr/key
|
||||
|
||||
@@ -71,7 +71,7 @@ android {
|
||||
}
|
||||
defaultConfig {
|
||||
applicationId = "bou.amine.apps.readerforselfossv2.android"
|
||||
minSdk = 21
|
||||
minSdk = 25
|
||||
targetSdk = 34
|
||||
versionCode = versionCodeFromGit()
|
||||
versionName = versionNameFromGit()
|
||||
|
||||
@@ -139,9 +139,12 @@ class LoginActivity : AppCompatActivity(), DIAware {
|
||||
|
||||
showProgress(true)
|
||||
|
||||
appSettingsService.updateSelfSigned(binding.selfSigned.isChecked)
|
||||
|
||||
repository.refreshLoginInformation(url, login, password)
|
||||
|
||||
CoroutineScope(Dispatchers.Main).launch {
|
||||
repository.updateApiInformation()
|
||||
val result = repository.login()
|
||||
if (result) {
|
||||
val (errorFetching, displaySelfossOnly) = repository.shouldBeSelfossInstance()
|
||||
|
||||
+2
-5
@@ -5,7 +5,6 @@ import android.content.res.ColorStateList
|
||||
import android.os.Bundle
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import bou.amine.apps.readerforselfossv2.android.adapters.SourcesListAdapter
|
||||
import bou.amine.apps.readerforselfossv2.android.databinding.ActivitySourcesBinding
|
||||
@@ -37,10 +36,8 @@ class SourcesActivity : AppCompatActivity(), DIAware {
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
supportActionBar?.setDisplayShowHomeEnabled(true)
|
||||
|
||||
binding.fab.rippleColor = ContextCompat.getColor(this, R.color.colorAccentDark)
|
||||
|
||||
binding.fab.backgroundTintList =
|
||||
ColorStateList.valueOf(ContextCompat.getColor(this, R.color.colorAccent))
|
||||
binding.fab.rippleColor = resources.getColor(R.color.colorAccentDark)
|
||||
binding.fab.backgroundTintList = ColorStateList.valueOf(resources.getColor(R.color.colorAccent))
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
|
||||
+1
-2
@@ -6,7 +6,6 @@ import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView.ScaleType
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import bou.amine.apps.readerforselfossv2.android.R
|
||||
import bou.amine.apps.readerforselfossv2.android.databinding.CardItemBinding
|
||||
@@ -61,7 +60,7 @@ class ItemCardAdapter(
|
||||
|
||||
binding.title.setOnTouchListener(LinkOnTouchListener())
|
||||
|
||||
binding.title.setLinkTextColor(ContextCompat.getColor(c, R.color.colorAccent))
|
||||
binding.title.setLinkTextColor(c.resources.getColor(R.color.colorAccent))
|
||||
|
||||
binding.sourceTitleAndDate.text = itm.sourceAuthorAndDate()
|
||||
|
||||
|
||||
+1
-3
@@ -4,7 +4,6 @@ import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import bou.amine.apps.readerforselfossv2.android.R
|
||||
import bou.amine.apps.readerforselfossv2.android.databinding.ListItemBinding
|
||||
@@ -45,8 +44,7 @@ class ItemListAdapter(
|
||||
|
||||
binding.title.setOnTouchListener(LinkOnTouchListener())
|
||||
|
||||
binding.title.setLinkTextColor(ContextCompat.getColor(c, R.color.colorAccent))
|
||||
|
||||
binding.title.setLinkTextColor(c.resources.getColor(R.color.colorAccent))
|
||||
|
||||
binding.sourceTitleAndDate.text = itm.sourceAuthorAndDate()
|
||||
|
||||
|
||||
+50
-76
@@ -10,21 +10,13 @@ import android.graphics.drawable.ColorDrawable
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.util.TypedValue
|
||||
import android.view.GestureDetector
|
||||
import android.view.InflateException
|
||||
import android.view.LayoutInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.webkit.WebResourceRequest
|
||||
import android.view.*
|
||||
import android.webkit.WebResourceResponse
|
||||
import android.webkit.WebSettings
|
||||
import android.webkit.WebView
|
||||
import android.webkit.WebViewClient
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.widget.NestedScrollView
|
||||
import androidx.fragment.app.Fragment
|
||||
import bou.amine.apps.readerforselfossv2.android.ImageActivity
|
||||
@@ -43,7 +35,6 @@ import bou.amine.apps.readerforselfossv2.model.SelfossModel
|
||||
import bou.amine.apps.readerforselfossv2.repository.Repository
|
||||
import bou.amine.apps.readerforselfossv2.rest.MercuryApi
|
||||
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
||||
import bou.amine.apps.readerforselfossv2.utils.ImageMimeType
|
||||
import bou.amine.apps.readerforselfossv2.utils.getHtmlDecoded
|
||||
import bou.amine.apps.readerforselfossv2.utils.getImages
|
||||
import bou.amine.apps.readerforselfossv2.utils.getThumbnail
|
||||
@@ -63,7 +54,7 @@ import org.kodein.di.instance
|
||||
import java.net.MalformedURLException
|
||||
import java.net.SocketTimeoutException
|
||||
import java.net.URL
|
||||
import java.util.Locale
|
||||
import java.util.*
|
||||
import java.util.concurrent.ExecutionException
|
||||
|
||||
|
||||
@@ -125,15 +116,9 @@ class ArticleFragment : Fragment(), DIAware {
|
||||
|
||||
fab = binding.fab
|
||||
|
||||
fab.backgroundTintList =
|
||||
ColorStateList.valueOf(
|
||||
ContextCompat.getColor(
|
||||
requireContext(),
|
||||
R.color.colorAccent
|
||||
)
|
||||
)
|
||||
fab.backgroundTintList = ColorStateList.valueOf(resources.getColor(R.color.colorAccent))
|
||||
|
||||
fab.rippleColor = ContextCompat.getColor(requireContext(), R.color.colorAccentDark)
|
||||
fab.rippleColor = resources.getColor(R.color.colorAccentDark)
|
||||
|
||||
val floatingToolbar: FloatingToolbar = handleFloatingToolbar()
|
||||
|
||||
@@ -218,8 +203,7 @@ class ArticleFragment : Fragment(), DIAware {
|
||||
}
|
||||
floatingToolbar.attachFab(fab)
|
||||
|
||||
floatingToolbar.background =
|
||||
ColorDrawable(ContextCompat.getColor(requireContext(), R.color.colorAccent))
|
||||
floatingToolbar.background = ColorDrawable(resources.getColor(R.color.colorAccent))
|
||||
|
||||
floatingToolbar.setClickListener(
|
||||
object : FloatingToolbar.ItemClickListener {
|
||||
@@ -304,7 +288,7 @@ class ArticleFragment : Fragment(), DIAware {
|
||||
contentText = data.content.orEmpty()
|
||||
htmlToWebview()
|
||||
|
||||
handleLeadImage(data.lead_image_url)
|
||||
handleLeadImage(data?.lead_image_url)
|
||||
|
||||
binding.nestedScrollView.scrollTo(0, 0)
|
||||
binding.progressBar.visibility = View.GONE
|
||||
@@ -329,19 +313,11 @@ class ArticleFragment : Fragment(), DIAware {
|
||||
|
||||
private fun handleImageLoading() {
|
||||
binding.webcontent.webViewClient = object : WebViewClient() {
|
||||
override fun shouldOverrideUrlLoading(
|
||||
view: WebView?,
|
||||
request: WebResourceRequest?
|
||||
): Boolean {
|
||||
val url = request?.url?.toString()
|
||||
return if (context != null && url != null && url.isUrlValid() && binding.webcontent.hitTestResult.type != WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE) {
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun shouldOverrideUrlLoading(view: WebView?, url: String): Boolean {
|
||||
return if (context != null && url.isUrlValid() && binding.webcontent.hitTestResult.type != WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE) {
|
||||
try {
|
||||
requireContext().startActivity(
|
||||
Intent(
|
||||
Intent.ACTION_VIEW,
|
||||
Uri.parse(url)
|
||||
)
|
||||
)
|
||||
requireContext().startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url)))
|
||||
} catch (e: ActivityNotFoundException) {
|
||||
e.sendSilentlyWithAcraWithName("activityNotFound > $url")
|
||||
}
|
||||
@@ -351,42 +327,50 @@ class ArticleFragment : Fragment(), DIAware {
|
||||
}
|
||||
}
|
||||
|
||||
override fun shouldInterceptRequest(
|
||||
view: WebView,
|
||||
request: WebResourceRequest
|
||||
): WebResourceResponse? {
|
||||
val url = request.url.toString()
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun shouldInterceptRequest(view: WebView, url: String): WebResourceResponse? {
|
||||
val glideOptions = RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.ALL)
|
||||
|
||||
val supportedExtensions = ImageMimeType.values().map { it.extension }
|
||||
|
||||
val matchingExtension = supportedExtensions.find {
|
||||
url.lowercase(Locale.US).contains(it)
|
||||
}
|
||||
|
||||
matchingExtension?.let {
|
||||
if (url.lowercase(Locale.US).contains(".jpg") || url.lowercase(Locale.US)
|
||||
.contains(".jpeg")
|
||||
) {
|
||||
try {
|
||||
val image = Glide.with(view)
|
||||
.asBitmap()
|
||||
.apply(glideOptions)
|
||||
.load(url)
|
||||
.submit()
|
||||
.get()
|
||||
|
||||
val mimeType = ImageMimeType.findMimeTypeByExtension(it)
|
||||
if (mimeType != null) {
|
||||
return WebResourceResponse(
|
||||
mimeType,
|
||||
"UTF-8",
|
||||
getBitmapInputStream(image, Bitmap.CompressFormat.WEBP)
|
||||
)
|
||||
}
|
||||
val image =
|
||||
Glide.with(view).asBitmap().apply(glideOptions).load(url).submit().get()
|
||||
return WebResourceResponse(
|
||||
IMAGE_JPG,
|
||||
"UTF-8",
|
||||
getBitmapInputStream(image, Bitmap.CompressFormat.JPEG)
|
||||
)
|
||||
} catch (e: ExecutionException) {
|
||||
// Do nothing
|
||||
}
|
||||
} else if (url.lowercase(Locale.US).contains(".png")) {
|
||||
try {
|
||||
val image =
|
||||
Glide.with(view).asBitmap().apply(glideOptions).load(url).submit().get()
|
||||
return WebResourceResponse(
|
||||
IMAGE_JPG,
|
||||
"UTF-8",
|
||||
getBitmapInputStream(image, Bitmap.CompressFormat.PNG)
|
||||
)
|
||||
} catch (e: ExecutionException) {
|
||||
// Do nothing
|
||||
}
|
||||
} else if (url.lowercase(Locale.US).contains(".webp")) {
|
||||
try {
|
||||
val image =
|
||||
Glide.with(view).asBitmap().apply(glideOptions).load(url).submit().get()
|
||||
return WebResourceResponse(
|
||||
IMAGE_JPG,
|
||||
"UTF-8",
|
||||
getBitmapInputStream(image, Bitmap.CompressFormat.WEBP)
|
||||
)
|
||||
} catch (e: ExecutionException) {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
|
||||
return super.shouldInterceptRequest(view, request)
|
||||
return super.shouldInterceptRequest(view, url)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -398,23 +382,13 @@ class ArticleFragment : Fragment(), DIAware {
|
||||
|
||||
|
||||
binding.webcontent.settings.standardFontFamily = a.getString(0)
|
||||
a.recycle()
|
||||
|
||||
binding.webcontent.visibility = View.VISIBLE
|
||||
|
||||
val colorOnSurface = TypedValue()
|
||||
requireContext().theme.resolveAttribute(
|
||||
com.google.android.material.R.attr.colorOnSurface,
|
||||
colorOnSurface,
|
||||
true
|
||||
)
|
||||
requireContext().theme.resolveAttribute(R.attr.colorOnSurface, colorOnSurface, true)
|
||||
|
||||
val colorSurface = TypedValue()
|
||||
requireContext().theme.resolveAttribute(
|
||||
com.google.android.material.R.attr.colorSurface,
|
||||
colorSurface,
|
||||
true
|
||||
)
|
||||
requireContext().theme.resolveAttribute(R.attr.colorSurface, colorSurface, true)
|
||||
|
||||
binding.webcontent.settings.useWideViewPort = true
|
||||
binding.webcontent.settings.loadWithOverviewMode = true
|
||||
@@ -483,7 +457,7 @@ class ArticleFragment : Fragment(), DIAware {
|
||||
| color: ${
|
||||
String.format(
|
||||
"#%06X",
|
||||
0xFFFFFF and ContextCompat.getColor(requireContext(), R.color.colorAccent)
|
||||
0xFFFFFF and resources.getColor(R.color.colorAccent)
|
||||
)
|
||||
} !important;
|
||||
| }
|
||||
|
||||
+3
-11
@@ -12,7 +12,6 @@ import android.view.View
|
||||
import android.view.View.GONE
|
||||
import android.view.View.VISIBLE
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.content.ContextCompat
|
||||
import bou.amine.apps.readerforselfossv2.android.HomeActivity
|
||||
import bou.amine.apps.readerforselfossv2.android.R
|
||||
import bou.amine.apps.readerforselfossv2.android.databinding.FilterFragmentBinding
|
||||
@@ -21,7 +20,7 @@ import bou.amine.apps.readerforselfossv2.repository.Repository
|
||||
import bou.amine.apps.readerforselfossv2.utils.getHtmlDecoded
|
||||
import bou.amine.apps.readerforselfossv2.utils.getIcon
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.request.target.CustomViewTarget
|
||||
import com.bumptech.glide.request.target.ViewTarget
|
||||
import com.bumptech.glide.request.transition.Transition
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||
import com.google.android.material.chip.Chip
|
||||
@@ -89,7 +88,7 @@ class FilterSheetFragment : BottomSheetDialogFragment(), DIAware {
|
||||
|
||||
Glide.with(context)
|
||||
.load(source.getIcon(repository.baseUrl))
|
||||
.into(object : CustomViewTarget<Chip, Drawable>(c) {
|
||||
.into(object : ViewTarget<Chip?, Drawable?>(c) {
|
||||
override fun onResourceReady(
|
||||
resource: Drawable,
|
||||
transition: Transition<in Drawable?>?
|
||||
@@ -101,13 +100,6 @@ class FilterSheetFragment : BottomSheetDialogFragment(), DIAware {
|
||||
}
|
||||
}
|
||||
|
||||
override fun onLoadFailed(errorDrawable: Drawable?) {
|
||||
c.chipIcon = errorDrawable
|
||||
}
|
||||
|
||||
override fun onResourceCleared(placeholder: Drawable?) {
|
||||
c.chipIcon = placeholder
|
||||
}
|
||||
})
|
||||
|
||||
c.text = source.title.getHtmlDecoded()
|
||||
@@ -164,7 +156,7 @@ class FilterSheetFragment : BottomSheetDialogFragment(), DIAware {
|
||||
Color.parseColor(tag.color)
|
||||
} catch (e: IllegalArgumentException) {
|
||||
e.sendSilentlyWithAcraWithName("color issue " + tag.color)
|
||||
ContextCompat.getColor(context, R.color.colorPrimary)
|
||||
resources.getColor(R.color.colorPrimary)
|
||||
}
|
||||
gd.setColor(gdColor)
|
||||
gd.shape = GradientDrawable.RECTANGLE
|
||||
|
||||
+8
-10
@@ -71,25 +71,23 @@ class SettingsActivity : AppCompatActivity(),
|
||||
}
|
||||
|
||||
override fun onPreferenceStartFragment(
|
||||
caller: PreferenceFragmentCompat,
|
||||
pref: Preference
|
||||
caller: PreferenceFragmentCompat,
|
||||
pref: Preference
|
||||
): Boolean {
|
||||
val fragmentClassName = pref.fragment ?: return false
|
||||
|
||||
// Instantiate the new Fragment
|
||||
val args = pref.extras
|
||||
val fragment = supportFragmentManager.fragmentFactory.instantiate(
|
||||
classLoader,
|
||||
fragmentClassName
|
||||
classLoader,
|
||||
pref.fragment.toString()
|
||||
).apply {
|
||||
arguments = args
|
||||
setTargetFragment(caller, 0)
|
||||
}
|
||||
|
||||
// Replace the existing Fragment with the new Fragment
|
||||
supportFragmentManager.beginTransaction()
|
||||
.replace(R.id.settings, fragment)
|
||||
.addToBackStack(null)
|
||||
.commit()
|
||||
.replace(R.id.settings, fragment)
|
||||
.addToBackStack(null)
|
||||
.commit()
|
||||
title = pref.title
|
||||
supportActionBar?.title = title
|
||||
return true
|
||||
|
||||
@@ -95,7 +95,6 @@ class LinkOnTouchListener : View.OnTouchListener {
|
||||
if (link.isNotEmpty()) {
|
||||
if (action == MotionEvent.ACTION_UP) {
|
||||
link[0].onClick(widget)
|
||||
widget.performClick()
|
||||
}
|
||||
ret = true
|
||||
}
|
||||
|
||||
@@ -51,6 +51,13 @@
|
||||
android:maxLines="1"
|
||||
android:minHeight="48dp" />
|
||||
|
||||
<com.google.android.material.switchmaterial.SwitchMaterial
|
||||
android:id="@+id/selfSigned"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/disable_ssl"
|
||||
android:textAlignment="viewStart" />
|
||||
|
||||
<com.google.android.material.switchmaterial.SwitchMaterial
|
||||
android:id="@+id/withLogin"
|
||||
android:layout_width="match_parent"
|
||||
|
||||
@@ -130,4 +130,5 @@
|
||||
<string name="update_source">Update source</string>
|
||||
<string name="confirm_disconnect_title">Disconnect ?</string>
|
||||
<string name="confirm_disconnect_description">You will be disconnected from your selfoss instance.</string>
|
||||
<string name="disable_ssl">Disable SSL</string>
|
||||
</resources>
|
||||
|
||||
@@ -130,4 +130,5 @@
|
||||
<string name="update_source">Update source</string>
|
||||
<string name="confirm_disconnect_title">Disconnect ?</string>
|
||||
<string name="confirm_disconnect_description">You will be disconnected from your selfoss instance.</string>
|
||||
<string name="disable_ssl">Disable SSL</string>
|
||||
</resources>
|
||||
|
||||
@@ -130,4 +130,5 @@
|
||||
<string name="update_source">Update source</string>
|
||||
<string name="confirm_disconnect_title">Disconnect ?</string>
|
||||
<string name="confirm_disconnect_description">You will be disconnected from your selfoss instance.</string>
|
||||
<string name="disable_ssl">Disable SSL</string>
|
||||
</resources>
|
||||
|
||||
@@ -130,4 +130,5 @@
|
||||
<string name="update_source">Update source</string>
|
||||
<string name="confirm_disconnect_title">Disconnect ?</string>
|
||||
<string name="confirm_disconnect_description">You will be disconnected from your selfoss instance.</string>
|
||||
<string name="disable_ssl">Disable SSL</string>
|
||||
</resources>
|
||||
|
||||
@@ -130,4 +130,5 @@
|
||||
<string name="update_source">Update source</string>
|
||||
<string name="confirm_disconnect_title">Disconnect ?</string>
|
||||
<string name="confirm_disconnect_description">You will be disconnected from your selfoss instance.</string>
|
||||
<string name="disable_ssl">Disable SSL</string>
|
||||
</resources>
|
||||
|
||||
@@ -130,4 +130,5 @@
|
||||
<string name="update_source">Update source</string>
|
||||
<string name="confirm_disconnect_title">Disconnect ?</string>
|
||||
<string name="confirm_disconnect_description">You will be disconnected from your selfoss instance.</string>
|
||||
<string name="disable_ssl">Disable SSL</string>
|
||||
</resources>
|
||||
|
||||
@@ -130,4 +130,5 @@
|
||||
<string name="update_source">Update source</string>
|
||||
<string name="confirm_disconnect_title">Disconnect ?</string>
|
||||
<string name="confirm_disconnect_description">You will be disconnected from your selfoss instance.</string>
|
||||
<string name="disable_ssl">Disable SSL</string>
|
||||
</resources>
|
||||
|
||||
@@ -130,4 +130,5 @@
|
||||
<string name="update_source">Update source</string>
|
||||
<string name="confirm_disconnect_title">Disconnect ?</string>
|
||||
<string name="confirm_disconnect_description">You will be disconnected from your selfoss instance.</string>
|
||||
<string name="disable_ssl">Disable SSL</string>
|
||||
</resources>
|
||||
|
||||
@@ -130,4 +130,5 @@
|
||||
<string name="update_source">Update source</string>
|
||||
<string name="confirm_disconnect_title">Disconnect ?</string>
|
||||
<string name="confirm_disconnect_description">You will be disconnected from your selfoss instance.</string>
|
||||
<string name="disable_ssl">Disable SSL</string>
|
||||
</resources>
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="gdpr_dialog_title">The app does not share any personal data about you.</string>
|
||||
<string name="gdpr_dialog_message"><![CDATA[Crash reports sending is now enabled. It can be disabled from the settings page. Keep in mind that crash reports are essential for the app development.]]></string>
|
||||
<string name="crash_toast_text">A crash occured. Sending the details to the developper.</string>
|
||||
<string name="pref_switch_disable_acra">"Disable automatic bug reporting. "</string>
|
||||
<string name="menu_home_filter">Filters</string>
|
||||
<string name="application_selfoss_only">This app only works with a Selfoss instance, and no other RSS feed.</string>
|
||||
<string name="menu_home_sources">Sources</string>
|
||||
<string name="update_source">Update source</string>
|
||||
</resources>
|
||||
@@ -130,4 +130,5 @@
|
||||
<string name="update_source">Update source</string>
|
||||
<string name="confirm_disconnect_title">Disconnect ?</string>
|
||||
<string name="confirm_disconnect_description">You will be disconnected from your selfoss instance.</string>
|
||||
<string name="disable_ssl">Disable SSL</string>
|
||||
</resources>
|
||||
|
||||
@@ -130,4 +130,5 @@
|
||||
<string name="update_source">Update source</string>
|
||||
<string name="confirm_disconnect_title">Disconnect ?</string>
|
||||
<string name="confirm_disconnect_description">You will be disconnected from your selfoss instance.</string>
|
||||
<string name="disable_ssl">Disable SSL</string>
|
||||
</resources>
|
||||
|
||||
@@ -130,4 +130,5 @@
|
||||
<string name="update_source">Update source</string>
|
||||
<string name="confirm_disconnect_title">Disconnect ?</string>
|
||||
<string name="confirm_disconnect_description">You will be disconnected from your selfoss instance.</string>
|
||||
<string name="disable_ssl">Disable SSL</string>
|
||||
</resources>
|
||||
|
||||
@@ -130,4 +130,5 @@
|
||||
<string name="update_source">Update source</string>
|
||||
<string name="confirm_disconnect_title">Disconnect ?</string>
|
||||
<string name="confirm_disconnect_description">You will be disconnected from your selfoss instance.</string>
|
||||
<string name="disable_ssl">Disable SSL</string>
|
||||
</resources>
|
||||
|
||||
@@ -130,4 +130,5 @@
|
||||
<string name="update_source">Update source</string>
|
||||
<string name="confirm_disconnect_title">Disconnect ?</string>
|
||||
<string name="confirm_disconnect_description">You will be disconnected from your selfoss instance.</string>
|
||||
<string name="disable_ssl">Disable SSL</string>
|
||||
</resources>
|
||||
|
||||
@@ -130,4 +130,5 @@
|
||||
<string name="update_source">更新源</string>
|
||||
<string name="confirm_disconnect_title">Disconnect ?</string>
|
||||
<string name="confirm_disconnect_description">You will be disconnected from your selfoss instance.</string>
|
||||
<string name="disable_ssl">Disable SSL</string>
|
||||
</resources>
|
||||
|
||||
@@ -130,4 +130,5 @@
|
||||
<string name="update_source">Update source</string>
|
||||
<string name="confirm_disconnect_title">Disconnect ?</string>
|
||||
<string name="confirm_disconnect_description">You will be disconnected from your selfoss instance.</string>
|
||||
<string name="disable_ssl">Disable SSL</string>
|
||||
</resources>
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
<string name="error_invalid_password">"Password not long enough"</string>
|
||||
<string name="error_field_required">"Field required"</string>
|
||||
<string name="prompt_url">"Url"</string>
|
||||
<string name="disable_ssl">"Disable SSL"</string>
|
||||
<string name="withLoginSwitch">"Login required ?"</string>
|
||||
<string name="login_url_problem">"Oops. You may need to add a \"/\" at the end of the url."</string>
|
||||
<string name="prompt_login">"Username"</string>
|
||||
|
||||
@@ -9,38 +9,49 @@ import org.junit.Test
|
||||
|
||||
class DatesTest {
|
||||
|
||||
private val v3Date = "2013-04-07T13:43:00+01:00"
|
||||
private val v4Date = "2013-04-07 13:43:00"
|
||||
private val bug1Date = "2022-12-24T17:00:08+00"
|
||||
private val newVersionDateVariant = "2022-12-24T17:00:08+00"
|
||||
private val newVersionDate = "2013-04-07T13:43:00+01:00"
|
||||
private val oldVersionDate = "2013-05-07 13:46:00"
|
||||
private val oldVersionDateVariant = "2021-03-21 10:32:00.000000"
|
||||
|
||||
@Test
|
||||
fun v3_date_should_be_parsed() {
|
||||
val date = DateUtils.parseDate(v3Date)
|
||||
val expected =
|
||||
LocalDateTime(2013, 4, 7, 14, 43, 0, 0).toInstant(TimeZone.currentSystemDefault())
|
||||
.toEpochMilliseconds()
|
||||
|
||||
assertEquals(date, expected)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun v4_date_should_be_parsed() {
|
||||
val date = DateUtils.parseDate(v4Date)
|
||||
fun new_version_date_should_be_parsed() {
|
||||
val date = DateUtils.parseDate(newVersionDate)
|
||||
val expected =
|
||||
LocalDateTime(2013, 4, 7, 13, 43, 0, 0).toInstant(TimeZone.currentSystemDefault())
|
||||
.toEpochMilliseconds()
|
||||
|
||||
assertEquals(date, expected)
|
||||
assertEquals(expected, date)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun bug1_date_should_be_parsed() {
|
||||
val date = DateUtils.parseDate(bug1Date)
|
||||
fun old_version_date_should_be_parsed() {
|
||||
val date = DateUtils.parseDate(oldVersionDate)
|
||||
val expected =
|
||||
LocalDateTime(2022, 12, 24, 18, 0, 8, 0).toInstant(TimeZone.currentSystemDefault())
|
||||
LocalDateTime(2013, 5, 7, 13, 46, 0, 0).toInstant(TimeZone.currentSystemDefault())
|
||||
.toEpochMilliseconds()
|
||||
|
||||
assertEquals(date, expected)
|
||||
assertEquals(expected, date)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun old_version_variant_date_should_be_parsed() {
|
||||
val date = DateUtils.parseDate(oldVersionDateVariant)
|
||||
val expected =
|
||||
LocalDateTime(2021, 3, 21, 10, 32, 0, 0).toInstant(TimeZone.currentSystemDefault())
|
||||
.toEpochMilliseconds()
|
||||
|
||||
assertEquals(expected, date)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun new_version_variant_date_should_be_parsed() {
|
||||
val date = DateUtils.parseDate(newVersionDateVariant)
|
||||
val expected =
|
||||
LocalDateTime(2022, 12, 24, 17, 0, 8, 0).toInstant(TimeZone.currentSystemDefault())
|
||||
.toEpochMilliseconds()
|
||||
|
||||
assertEquals(expected, date)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -7,8 +7,8 @@ buildscript {
|
||||
|
||||
plugins {
|
||||
//trick: for the same plugin versions in all sub-modules
|
||||
id("com.android.application").version("8.1.0").apply(false)
|
||||
id("com.android.library").version("8.1.0").apply(false)
|
||||
id("com.android.application").version("8.1.2").apply(false)
|
||||
id("com.android.library").version("8.1.2").apply(false)
|
||||
id("org.jetbrains.kotlin.android").version("1.9.10").apply(false)
|
||||
kotlin("multiplatform").version("1.9.10").apply(false)
|
||||
id("com.mikepenz.aboutlibraries.plugin").version("10.5.1").apply(false)
|
||||
|
||||
+1
-2
@@ -19,11 +19,10 @@ kotlin.code.style=official
|
||||
android.useAndroidX=true
|
||||
#android.nonTransitiveRClass=true
|
||||
android.enableJetifier=true
|
||||
android.nonTransitiveRClass=true
|
||||
android.nonTransitiveRClass=false
|
||||
#MPP
|
||||
kotlin.mpp.enableCInteropCommonization=true
|
||||
org.gradle.parallel=true
|
||||
org.gradle.caching=true
|
||||
ignoreGitVersion=false
|
||||
kotlin.native.cacheKind.iosX64=none
|
||||
pushCache=true
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
val pushCache: String by settings
|
||||
|
||||
pluginManagement {
|
||||
repositories {
|
||||
// maven { url = uri("https://nexus.amine-louveau.fr/repository/maven-public/")}
|
||||
@@ -17,17 +15,6 @@ dependencyResolutionManagement {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
buildCache {
|
||||
remote<HttpBuildCache> {
|
||||
url = uri("http://18.0.0.7:3071/cache/")
|
||||
isAllowInsecureProtocol = true
|
||||
isAllowUntrustedServer = true
|
||||
isUseExpectContinue = true
|
||||
isPush = (pushCache == "true")
|
||||
}
|
||||
}
|
||||
|
||||
rootProject.name = "ReaderForSelfossV2"
|
||||
include(":androidApp")
|
||||
include(":shared")
|
||||
@@ -36,6 +36,7 @@ kotlin {
|
||||
implementation("io.ktor:ktor-serialization-kotlinx-json:$ktorVersion")
|
||||
implementation("io.ktor:ktor-client-logging:$ktorVersion")
|
||||
implementation("io.ktor:ktor-client-auth:$ktorVersion")
|
||||
implementation("io.ktor:ktor-client-cio:$ktorVersion")
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.1")
|
||||
|
||||
implementation("org.jsoup:jsoup:1.15.4")
|
||||
@@ -102,10 +103,10 @@ kotlin {
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdk = 33
|
||||
compileSdk = 34
|
||||
sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
|
||||
defaultConfig {
|
||||
minSdk = 21
|
||||
minSdk = 25
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package bou.amine.apps.readerforselfossv2.rest
|
||||
|
||||
import io.ktor.client.engine.cio.CIOEngineConfig
|
||||
import java.security.cert.X509Certificate
|
||||
import javax.net.ssl.X509TrustManager
|
||||
|
||||
class NaiveTrustManager : X509TrustManager {
|
||||
override fun checkClientTrusted(chain: Array<out X509Certificate>?, authType: String?) {}
|
||||
|
||||
override fun checkServerTrusted(chain: Array<out X509Certificate>?, authType: String?) {}
|
||||
|
||||
override fun getAcceptedIssuers(): Array<out X509Certificate> = arrayOf()
|
||||
}
|
||||
|
||||
actual fun setupInsecureHTTPEngine(config: CIOEngineConfig) {
|
||||
config.https.trustManager = NaiveTrustManager()
|
||||
}
|
||||
@@ -6,16 +6,25 @@ 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 {
|
||||
return try {
|
||||
Instant.parse(dateString).toEpochMilliseconds()
|
||||
} catch (e: Exception) {
|
||||
var str = dateString.replace(" ", "T")
|
||||
if (str.matches("\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\+\\d{2}".toRegex())) {
|
||||
str = str.split("+")[0]
|
||||
}
|
||||
LocalDateTime.parse(str).toInstant(TimeZone.currentSystemDefault()).toEpochMilliseconds()
|
||||
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 {
|
||||
|
||||
+13
-10
@@ -1,19 +1,13 @@
|
||||
package bou.amine.apps.readerforselfossv2.utils
|
||||
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.text.Html
|
||||
import bou.amine.apps.readerforselfossv2.model.SelfossModel
|
||||
import org.jsoup.Jsoup
|
||||
import java.util.*
|
||||
|
||||
actual fun String.getHtmlDecoded(): String {
|
||||
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
Html.fromHtml(this, Html.FROM_HTML_MODE_COMPACT).toString()
|
||||
} else {
|
||||
@Suppress("DEPRECATION")
|
||||
Html.fromHtml(this).toString()
|
||||
}
|
||||
return Html.fromHtml(this).toString()
|
||||
}
|
||||
|
||||
actual fun SelfossModel.Item.getIcon(baseUrl: String): String {
|
||||
@@ -25,10 +19,19 @@ actual fun SelfossModel.Item.getThumbnail(baseUrl: String): String {
|
||||
}
|
||||
|
||||
actual fun SelfossModel.Item.getImages(): ArrayList<String> {
|
||||
val doc = Jsoup.parse(content)
|
||||
val images = doc.getElementsByTag("img")
|
||||
val allImages = ArrayList<String>()
|
||||
|
||||
return ArrayList(images.map { it.attr("src") })
|
||||
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"))
|
||||
{
|
||||
allImages.add(url)
|
||||
}
|
||||
}
|
||||
return allImages
|
||||
}
|
||||
|
||||
actual fun SelfossModel.Source.getIcon(baseUrl: String): String {
|
||||
|
||||
@@ -5,31 +5,46 @@ import bou.amine.apps.readerforselfossv2.model.StatusAndData
|
||||
import bou.amine.apps.readerforselfossv2.model.SuccessResponse
|
||||
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.*
|
||||
import io.ktor.client.plugins.logging.*
|
||||
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 io.ktor.client.HttpClient
|
||||
import io.ktor.client.engine.cio.CIO
|
||||
import io.ktor.client.engine.cio.CIOEngineConfig
|
||||
import io.ktor.client.plugins.HttpRequestRetry
|
||||
import io.ktor.client.plugins.HttpTimeout
|
||||
import io.ktor.client.plugins.auth.providers.BasicAuthCredentials
|
||||
import io.ktor.client.plugins.cache.HttpCache
|
||||
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
|
||||
import io.ktor.client.plugins.cookies.HttpCookies
|
||||
import io.ktor.client.plugins.logging.LogLevel
|
||||
import io.ktor.client.plugins.logging.Logger
|
||||
import io.ktor.client.plugins.logging.Logging
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.client.request.headers
|
||||
import io.ktor.client.request.parameter
|
||||
import io.ktor.client.statement.HttpResponse
|
||||
import io.ktor.http.HttpHeaders
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.http.Parameters
|
||||
import io.ktor.serialization.kotlinx.json.json
|
||||
import io.ktor.util.encodeBase64
|
||||
import io.ktor.utils.io.charsets.Charsets
|
||||
import io.ktor.utils.io.core.toByteArray
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.serialization.json.Json
|
||||
|
||||
expect fun setupInsecureHTTPEngine(config: CIOEngineConfig)
|
||||
|
||||
class SelfossApi(private val appSettingsService: AppSettingsService) {
|
||||
|
||||
var client = createHttpClient()
|
||||
|
||||
private fun createHttpClient(): HttpClient {
|
||||
val client = HttpClient {
|
||||
fun createHttpClient() =
|
||||
HttpClient(CIO) {
|
||||
if (appSettingsService.getSelfSigned()) {
|
||||
engine {
|
||||
setupInsecureHTTPEngine(this)
|
||||
}
|
||||
}
|
||||
install(ContentNegotiation) {
|
||||
install(HttpCache)
|
||||
json(Json {
|
||||
@@ -60,7 +75,7 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
|
||||
Napier.i("Will modify", tag = "HttpSend")
|
||||
CoroutineScope(Dispatchers.Main).launch {
|
||||
Napier.i("Will login", tag = "HttpSend")
|
||||
this@SelfossApi.login()
|
||||
login()
|
||||
Napier.i("Did login", tag = "HttpSend")
|
||||
}
|
||||
}
|
||||
@@ -68,10 +83,6 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
|
||||
expectSuccess = false
|
||||
}
|
||||
|
||||
|
||||
return client
|
||||
}
|
||||
|
||||
fun url(path: String) =
|
||||
"${appSettingsService.getBaseUrl()}$path"
|
||||
|
||||
|
||||
+20
@@ -8,6 +8,7 @@ class AppSettingsService(acraSenderServiceProcess: Boolean = false) {
|
||||
// Api related
|
||||
private var _apiVersion: Int = -1
|
||||
private var _publicAccess: Boolean? = null
|
||||
private var _selfSigned: Boolean? = null
|
||||
private var _baseUrl: String = ""
|
||||
private var _userName: String = ""
|
||||
private var _basicUserName: String = ""
|
||||
@@ -77,6 +78,22 @@ class AppSettingsService(acraSenderServiceProcess: Boolean = false) {
|
||||
_publicAccess = settings.getBoolean(API_PUBLIC_ACCESS, false)
|
||||
}
|
||||
|
||||
fun getSelfSigned(): Boolean {
|
||||
if (_selfSigned == null) {
|
||||
refreshSelfSigned()
|
||||
}
|
||||
return _selfSigned!!
|
||||
}
|
||||
|
||||
fun updateSelfSigned(selfSigned: Boolean) {
|
||||
settings.putBoolean(API_SELF_SIGNED, selfSigned)
|
||||
refreshSelfSigned()
|
||||
}
|
||||
|
||||
private fun refreshSelfSigned() {
|
||||
_selfSigned = settings.getBoolean(API_SELF_SIGNED, false)
|
||||
}
|
||||
|
||||
fun getBaseUrl(): String {
|
||||
if (_baseUrl.isEmpty()) {
|
||||
refreshBaseUrl()
|
||||
@@ -383,6 +400,7 @@ class AppSettingsService(acraSenderServiceProcess: Boolean = false) {
|
||||
refreshBaseUrl()
|
||||
refreshApiVersion()
|
||||
refreshPublicAccess()
|
||||
refreshSelfSigned()
|
||||
}
|
||||
|
||||
fun refreshUserSettings() {
|
||||
@@ -468,6 +486,8 @@ class AppSettingsService(acraSenderServiceProcess: Boolean = false) {
|
||||
|
||||
const val API_PUBLIC_ACCESS = "apiPublicAccess"
|
||||
|
||||
const val API_SELF_SIGNED = "apiSelfSigned"
|
||||
|
||||
const val API_ITEMS_NUMBER = "prefer_api_items_number"
|
||||
|
||||
const val API_TIMEOUT = "api_timeout"
|
||||
|
||||
@@ -17,7 +17,7 @@ fun SOURCE.toView(): SelfossModel.SourceDetail =
|
||||
this.id.toInt(),
|
||||
this.title,
|
||||
null,
|
||||
this.tags.split(","),
|
||||
this.tags?.split(","),
|
||||
this.spout,
|
||||
this.error,
|
||||
this.icon,
|
||||
|
||||
@@ -8,20 +8,4 @@ enum class ItemType(val position: Int, val type: String) {
|
||||
companion object {
|
||||
fun fromInt(value: Int) = values().first { it.position == value }
|
||||
}
|
||||
}
|
||||
|
||||
enum class ImageMimeType(val extension: String, val mimeType: String) {
|
||||
JPG(".jpg", "image/jpeg"),
|
||||
JPEG(".jpeg", "image/jpeg"),
|
||||
PNG(".png", "image/png"),
|
||||
WEBP(".webp", "image/webp"),
|
||||
GIF(".gif", "image/gif"),
|
||||
SVG(".svg", "image/svg+xml"),
|
||||
BMP(".bmp", "image/bmp"),
|
||||
TIFF(".tiff", "image/tiff"),
|
||||
TIF(".tif", "image/tiff");
|
||||
|
||||
companion object {
|
||||
fun findMimeTypeByExtension(ext: String) = values().find { it.extension == ext }?.mimeType
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
package bou.amine.apps.readerforselfossv2.rest
|
||||
|
||||
import io.ktor.client.engine.cio.CIOEngineConfig
|
||||
|
||||
actual fun setupInsecureHTTPEngine(config: CIOEngineConfig) {
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
package bou.amine.apps.readerforselfossv2.rest
|
||||
|
||||
import io.ktor.client.engine.cio.CIOEngineConfig
|
||||
|
||||
actual fun setupInsecureHTTPEngine(config: CIOEngineConfig) {
|
||||
}
|
||||
Reference in New Issue
Block a user