Compare commits
8 Commits
172362b533
...
20aab0ea62
Author | SHA1 | Date | |
---|---|---|---|
20aab0ea62 | |||
dcb9b1cb1f | |||
776d5d36f6 | |||
990a354229 | |||
bd6b96d09d | |||
d26f3979cd | |||
b59b1abc6d | |||
baca7cffed |
@ -8,15 +8,15 @@ plugins {
|
|||||||
kotlin("android")
|
kotlin("android")
|
||||||
kotlin("kapt")
|
kotlin("kapt")
|
||||||
id("com.mikepenz.aboutlibraries.plugin")
|
id("com.mikepenz.aboutlibraries.plugin")
|
||||||
id("org.jetbrains.kotlinx.kover") version "0.6.1"
|
id("org.jetbrains.kotlinx.kover")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Project.execWithOutput(cmd: String, ignore: Boolean = false): String {
|
fun Project.execWithOutput(cmd: String, ignore: Boolean = false): String {
|
||||||
var result: String = ByteArrayOutputStream().use { outputStream ->
|
val result: String = ByteArrayOutputStream().use { outputStream ->
|
||||||
project.exec {
|
project.exec {
|
||||||
commandLine = cmd.split(" ")
|
commandLine = cmd.split(" ")
|
||||||
standardOutput = outputStream
|
standardOutput = outputStream
|
||||||
isIgnoreExitValue = ignore ?: false
|
isIgnoreExitValue = ignore
|
||||||
}
|
}
|
||||||
outputStream.toString()
|
outputStream.toString()
|
||||||
}
|
}
|
||||||
@ -24,9 +24,8 @@ fun Project.execWithOutput(cmd: String, ignore: Boolean = false): String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun gitVersion(): String {
|
fun gitVersion(): String {
|
||||||
var process = ""
|
|
||||||
val maybeTagOfCurrentCommit = execWithOutput("git -C ../ describe --contains HEAD", true)
|
val maybeTagOfCurrentCommit = execWithOutput("git -C ../ describe --contains HEAD", true)
|
||||||
process = if (maybeTagOfCurrentCommit.isEmpty()) {
|
val process = if (maybeTagOfCurrentCommit.isEmpty()) {
|
||||||
println("No tag on current commit. Will take the latest one.")
|
println("No tag on current commit. Will take the latest one.")
|
||||||
execWithOutput("git -C ../ for-each-ref refs/tags --sort=-refname --format='%(refname:short)' --count=1")
|
execWithOutput("git -C ../ for-each-ref refs/tags --sort=-refname --format='%(refname:short)' --count=1")
|
||||||
} else {
|
} else {
|
||||||
@ -58,23 +57,22 @@ android {
|
|||||||
compileOptions {
|
compileOptions {
|
||||||
isCoreLibraryDesugaringEnabled = true
|
isCoreLibraryDesugaringEnabled = true
|
||||||
// Flag to enable support for the new language APIs
|
// Flag to enable support for the new language APIs
|
||||||
sourceCompatibility = JavaVersion.VERSION_11
|
sourceCompatibility = JavaVersion.VERSION_17
|
||||||
targetCompatibility = JavaVersion.VERSION_11
|
targetCompatibility = JavaVersion.VERSION_17
|
||||||
}
|
}
|
||||||
|
|
||||||
// For Kotlin projects
|
// For Kotlin projects
|
||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
jvmTarget = "11"
|
jvmTarget = "17"
|
||||||
}
|
}
|
||||||
compileSdk = 33
|
compileSdk = 34
|
||||||
buildToolsVersion = "33.0.0"
|
|
||||||
buildFeatures {
|
buildFeatures {
|
||||||
viewBinding = true
|
viewBinding = true
|
||||||
}
|
}
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId = "bou.amine.apps.readerforselfossv2.android"
|
applicationId = "bou.amine.apps.readerforselfossv2.android"
|
||||||
minSdk = 21
|
minSdk = 21
|
||||||
targetSdk = 33
|
targetSdk = 34
|
||||||
versionCode = versionCodeFromGit()
|
versionCode = versionCodeFromGit()
|
||||||
versionName = versionNameFromGit()
|
versionName = versionNameFromGit()
|
||||||
|
|
||||||
@ -87,7 +85,7 @@ android {
|
|||||||
// tests
|
// tests
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
packagingOptions {
|
packaging {
|
||||||
resources {
|
resources {
|
||||||
excludes += "/META-INF/{AL2.0,LGPL2.1}"
|
excludes += "/META-INF/{AL2.0,LGPL2.1}"
|
||||||
}
|
}
|
||||||
@ -116,25 +114,25 @@ dependencies {
|
|||||||
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.0.3")
|
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.0.3")
|
||||||
|
|
||||||
implementation(project(":shared"))
|
implementation(project(":shared"))
|
||||||
implementation("com.google.android.material:material:1.5.0")
|
implementation("com.google.android.material:material:1.9.0")
|
||||||
implementation("androidx.appcompat:appcompat:1.4.1")
|
implementation("androidx.appcompat:appcompat:1.6.1")
|
||||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.0")
|
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.1")
|
||||||
|
|
||||||
implementation("androidx.preference:preference-ktx:1.1.1")
|
implementation("androidx.preference:preference-ktx:1.2.1")
|
||||||
|
|
||||||
implementation(fileTree(mapOf("include" to listOf("*.jar"), "dir" to "libs")))
|
implementation(fileTree(mapOf("include" to listOf("*.jar"), "dir" to "libs")))
|
||||||
|
|
||||||
// Android Support
|
// Android Support
|
||||||
implementation("androidx.appcompat:appcompat:1.4.1")
|
implementation("androidx.appcompat:appcompat:1.6.1")
|
||||||
implementation("com.google.android.material:material:1.5.0")
|
implementation("com.google.android.material:material:1.9.0")
|
||||||
implementation("androidx.recyclerview:recyclerview:1.3.0-alpha01")
|
implementation("androidx.recyclerview:recyclerview:1.3.1")
|
||||||
implementation("androidx.legacy:legacy-support-v4:1.0.0")
|
implementation("androidx.legacy:legacy-support-v4:1.0.0")
|
||||||
implementation("androidx.vectordrawable:vectordrawable:1.2.0-alpha02")
|
implementation("androidx.vectordrawable:vectordrawable:1.2.0-beta01")
|
||||||
implementation("androidx.cardview:cardview:1.0.0")
|
implementation("androidx.cardview:cardview:1.0.0")
|
||||||
implementation("androidx.annotation:annotation:1.3.0")
|
implementation("androidx.annotation:annotation:1.7.0")
|
||||||
implementation("androidx.work:work-runtime-ktx:2.7.1")
|
implementation("androidx.work:work-runtime-ktx:2.8.1")
|
||||||
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
|
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
|
||||||
implementation("org.jsoup:jsoup:1.14.3")
|
implementation("org.jsoup:jsoup:1.15.4")
|
||||||
|
|
||||||
//multidex
|
//multidex
|
||||||
implementation("androidx.multidex:multidex:2.0.1")
|
implementation("androidx.multidex:multidex:2.0.1")
|
||||||
@ -155,7 +153,7 @@ dependencies {
|
|||||||
|
|
||||||
// Pager
|
// Pager
|
||||||
implementation("me.relex:circleindicator:2.1.6")
|
implementation("me.relex:circleindicator:2.1.6")
|
||||||
implementation("androidx.viewpager2:viewpager2:1.1.0-beta01")
|
implementation("androidx.viewpager2:viewpager2:1.1.0-beta02")
|
||||||
|
|
||||||
//Dependency Injection
|
//Dependency Injection
|
||||||
implementation("org.kodein.di:kodein-di:7.14.0")
|
implementation("org.kodein.di:kodein-di:7.14.0")
|
||||||
@ -171,7 +169,7 @@ dependencies {
|
|||||||
//PhotoView
|
//PhotoView
|
||||||
implementation("com.github.chrisbanes:PhotoView:2.3.0")
|
implementation("com.github.chrisbanes:PhotoView:2.3.0")
|
||||||
|
|
||||||
implementation("androidx.core:core-ktx:1.8.0")
|
implementation("androidx.core:core-ktx:1.12.0")
|
||||||
|
|
||||||
implementation("androidx.lifecycle:lifecycle-extensions:2.2.0")
|
implementation("androidx.lifecycle:lifecycle-extensions:2.2.0")
|
||||||
|
|
||||||
@ -184,7 +182,7 @@ dependencies {
|
|||||||
//test
|
//test
|
||||||
testImplementation("junit:junit:4.13.2")
|
testImplementation("junit:junit:4.13.2")
|
||||||
testImplementation("io.mockk:mockk:1.12.0")
|
testImplementation("io.mockk:mockk:1.12.0")
|
||||||
testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0")
|
testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.1")
|
||||||
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.4.0")
|
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.4.0")
|
||||||
|
|
||||||
implementation("ch.acra:acra-http:$acraVersion")
|
implementation("ch.acra:acra-http:$acraVersion")
|
||||||
|
1
androidApp/proguard-rules.pro
vendored
1
androidApp/proguard-rules.pro
vendored
@ -55,6 +55,7 @@
|
|||||||
# maybe remove later ?
|
# maybe remove later ?
|
||||||
-keep class * extends androidx.fragment.app.Fragment
|
-keep class * extends androidx.fragment.app.Fragment
|
||||||
|
|
||||||
|
-dontwarn org.slf4j.impl.StaticLoggerBinder
|
||||||
|
|
||||||
# Keep `Companion` object fields of serializable classes.
|
# Keep `Companion` object fields of serializable classes.
|
||||||
# This avoids serializer lookup through `getDeclaredClasses` as done for named companion objects.
|
# This avoids serializer lookup through `getDeclaredClasses` as done for named companion objects.
|
||||||
|
@ -5,6 +5,7 @@ import android.content.res.ColorStateList
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import bou.amine.apps.readerforselfossv2.android.adapters.SourcesListAdapter
|
import bou.amine.apps.readerforselfossv2.android.adapters.SourcesListAdapter
|
||||||
import bou.amine.apps.readerforselfossv2.android.databinding.ActivitySourcesBinding
|
import bou.amine.apps.readerforselfossv2.android.databinding.ActivitySourcesBinding
|
||||||
@ -36,8 +37,10 @@ class SourcesActivity : AppCompatActivity(), DIAware {
|
|||||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||||
supportActionBar?.setDisplayShowHomeEnabled(true)
|
supportActionBar?.setDisplayShowHomeEnabled(true)
|
||||||
|
|
||||||
binding.fab.rippleColor = resources.getColor(R.color.colorAccentDark)
|
binding.fab.rippleColor = ContextCompat.getColor(this, R.color.colorAccentDark)
|
||||||
binding.fab.backgroundTintList = ColorStateList.valueOf(resources.getColor(R.color.colorAccent))
|
|
||||||
|
binding.fab.backgroundTintList =
|
||||||
|
ColorStateList.valueOf(ContextCompat.getColor(this, R.color.colorAccent))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStop() {
|
override fun onStop() {
|
||||||
|
@ -6,6 +6,7 @@ import android.view.LayoutInflater
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.ImageView.ScaleType
|
import android.widget.ImageView.ScaleType
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import bou.amine.apps.readerforselfossv2.android.R
|
import bou.amine.apps.readerforselfossv2.android.R
|
||||||
import bou.amine.apps.readerforselfossv2.android.databinding.CardItemBinding
|
import bou.amine.apps.readerforselfossv2.android.databinding.CardItemBinding
|
||||||
@ -60,7 +61,7 @@ class ItemCardAdapter(
|
|||||||
|
|
||||||
binding.title.setOnTouchListener(LinkOnTouchListener())
|
binding.title.setOnTouchListener(LinkOnTouchListener())
|
||||||
|
|
||||||
binding.title.setLinkTextColor(c.resources.getColor(R.color.colorAccent))
|
binding.title.setLinkTextColor(ContextCompat.getColor(c, R.color.colorAccent))
|
||||||
|
|
||||||
binding.sourceTitleAndDate.text = itm.sourceAuthorAndDate()
|
binding.sourceTitleAndDate.text = itm.sourceAuthorAndDate()
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import android.app.Activity
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import bou.amine.apps.readerforselfossv2.android.R
|
import bou.amine.apps.readerforselfossv2.android.R
|
||||||
import bou.amine.apps.readerforselfossv2.android.databinding.ListItemBinding
|
import bou.amine.apps.readerforselfossv2.android.databinding.ListItemBinding
|
||||||
@ -44,7 +45,8 @@ class ItemListAdapter(
|
|||||||
|
|
||||||
binding.title.setOnTouchListener(LinkOnTouchListener())
|
binding.title.setOnTouchListener(LinkOnTouchListener())
|
||||||
|
|
||||||
binding.title.setLinkTextColor(c.resources.getColor(R.color.colorAccent))
|
binding.title.setLinkTextColor(ContextCompat.getColor(c, R.color.colorAccent))
|
||||||
|
|
||||||
|
|
||||||
binding.sourceTitleAndDate.text = itm.sourceAuthorAndDate()
|
binding.sourceTitleAndDate.text = itm.sourceAuthorAndDate()
|
||||||
|
|
||||||
|
@ -10,13 +10,21 @@ import android.graphics.drawable.ColorDrawable
|
|||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.TypedValue
|
import android.util.TypedValue
|
||||||
import android.view.*
|
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.webkit.WebResourceResponse
|
import android.webkit.WebResourceResponse
|
||||||
import android.webkit.WebSettings
|
import android.webkit.WebSettings
|
||||||
import android.webkit.WebView
|
import android.webkit.WebView
|
||||||
import android.webkit.WebViewClient
|
import android.webkit.WebViewClient
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.widget.NestedScrollView
|
import androidx.core.widget.NestedScrollView
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import bou.amine.apps.readerforselfossv2.android.ImageActivity
|
import bou.amine.apps.readerforselfossv2.android.ImageActivity
|
||||||
@ -35,6 +43,7 @@ import bou.amine.apps.readerforselfossv2.model.SelfossModel
|
|||||||
import bou.amine.apps.readerforselfossv2.repository.Repository
|
import bou.amine.apps.readerforselfossv2.repository.Repository
|
||||||
import bou.amine.apps.readerforselfossv2.rest.MercuryApi
|
import bou.amine.apps.readerforselfossv2.rest.MercuryApi
|
||||||
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
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.getHtmlDecoded
|
||||||
import bou.amine.apps.readerforselfossv2.utils.getImages
|
import bou.amine.apps.readerforselfossv2.utils.getImages
|
||||||
import bou.amine.apps.readerforselfossv2.utils.getThumbnail
|
import bou.amine.apps.readerforselfossv2.utils.getThumbnail
|
||||||
@ -54,7 +63,7 @@ import org.kodein.di.instance
|
|||||||
import java.net.MalformedURLException
|
import java.net.MalformedURLException
|
||||||
import java.net.SocketTimeoutException
|
import java.net.SocketTimeoutException
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
import java.util.*
|
import java.util.Locale
|
||||||
import java.util.concurrent.ExecutionException
|
import java.util.concurrent.ExecutionException
|
||||||
|
|
||||||
|
|
||||||
@ -116,9 +125,15 @@ class ArticleFragment : Fragment(), DIAware {
|
|||||||
|
|
||||||
fab = binding.fab
|
fab = binding.fab
|
||||||
|
|
||||||
fab.backgroundTintList = ColorStateList.valueOf(resources.getColor(R.color.colorAccent))
|
fab.backgroundTintList =
|
||||||
|
ColorStateList.valueOf(
|
||||||
|
ContextCompat.getColor(
|
||||||
|
requireContext(),
|
||||||
|
R.color.colorAccent
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
fab.rippleColor = resources.getColor(R.color.colorAccentDark)
|
fab.rippleColor = ContextCompat.getColor(requireContext(), R.color.colorAccentDark)
|
||||||
|
|
||||||
val floatingToolbar: FloatingToolbar = handleFloatingToolbar()
|
val floatingToolbar: FloatingToolbar = handleFloatingToolbar()
|
||||||
|
|
||||||
@ -203,7 +218,8 @@ class ArticleFragment : Fragment(), DIAware {
|
|||||||
}
|
}
|
||||||
floatingToolbar.attachFab(fab)
|
floatingToolbar.attachFab(fab)
|
||||||
|
|
||||||
floatingToolbar.background = ColorDrawable(resources.getColor(R.color.colorAccent))
|
floatingToolbar.background =
|
||||||
|
ColorDrawable(ContextCompat.getColor(requireContext(), R.color.colorAccent))
|
||||||
|
|
||||||
floatingToolbar.setClickListener(
|
floatingToolbar.setClickListener(
|
||||||
object : FloatingToolbar.ItemClickListener {
|
object : FloatingToolbar.ItemClickListener {
|
||||||
@ -288,7 +304,7 @@ class ArticleFragment : Fragment(), DIAware {
|
|||||||
contentText = data.content.orEmpty()
|
contentText = data.content.orEmpty()
|
||||||
htmlToWebview()
|
htmlToWebview()
|
||||||
|
|
||||||
handleLeadImage(data?.lead_image_url)
|
handleLeadImage(data.lead_image_url)
|
||||||
|
|
||||||
binding.nestedScrollView.scrollTo(0, 0)
|
binding.nestedScrollView.scrollTo(0, 0)
|
||||||
binding.progressBar.visibility = View.GONE
|
binding.progressBar.visibility = View.GONE
|
||||||
@ -313,11 +329,19 @@ class ArticleFragment : Fragment(), DIAware {
|
|||||||
|
|
||||||
private fun handleImageLoading() {
|
private fun handleImageLoading() {
|
||||||
binding.webcontent.webViewClient = object : WebViewClient() {
|
binding.webcontent.webViewClient = object : WebViewClient() {
|
||||||
@Deprecated("Deprecated in Java")
|
override fun shouldOverrideUrlLoading(
|
||||||
override fun shouldOverrideUrlLoading(view: WebView?, url: String): Boolean {
|
view: WebView?,
|
||||||
return if (context != null && url.isUrlValid() && binding.webcontent.hitTestResult.type != WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE) {
|
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) {
|
||||||
try {
|
try {
|
||||||
requireContext().startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url)))
|
requireContext().startActivity(
|
||||||
|
Intent(
|
||||||
|
Intent.ACTION_VIEW,
|
||||||
|
Uri.parse(url)
|
||||||
|
)
|
||||||
|
)
|
||||||
} catch (e: ActivityNotFoundException) {
|
} catch (e: ActivityNotFoundException) {
|
||||||
e.sendSilentlyWithAcraWithName("activityNotFound > $url")
|
e.sendSilentlyWithAcraWithName("activityNotFound > $url")
|
||||||
}
|
}
|
||||||
@ -327,50 +351,42 @@ class ArticleFragment : Fragment(), DIAware {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated("Deprecated in Java")
|
override fun shouldInterceptRequest(
|
||||||
override fun shouldInterceptRequest(view: WebView, url: String): WebResourceResponse? {
|
view: WebView,
|
||||||
|
request: WebResourceRequest
|
||||||
|
): WebResourceResponse? {
|
||||||
|
val url = request.url.toString()
|
||||||
val glideOptions = RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.ALL)
|
val glideOptions = RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.ALL)
|
||||||
if (url.lowercase(Locale.US).contains(".jpg") || url.lowercase(Locale.US)
|
|
||||||
.contains(".jpeg")
|
val supportedExtensions = ImageMimeType.values().map { it.extension }
|
||||||
) {
|
|
||||||
|
val matchingExtension = supportedExtensions.find {
|
||||||
|
url.lowercase(Locale.US).contains(it)
|
||||||
|
}
|
||||||
|
|
||||||
|
matchingExtension?.let {
|
||||||
try {
|
try {
|
||||||
val image =
|
val image = Glide.with(view)
|
||||||
Glide.with(view).asBitmap().apply(glideOptions).load(url).submit().get()
|
.asBitmap()
|
||||||
return WebResourceResponse(
|
.apply(glideOptions)
|
||||||
IMAGE_JPG,
|
.load(url)
|
||||||
"UTF-8",
|
.submit()
|
||||||
getBitmapInputStream(image, Bitmap.CompressFormat.JPEG)
|
.get()
|
||||||
)
|
|
||||||
} catch (e: ExecutionException) {
|
val mimeType = ImageMimeType.findMimeTypeByExtension(it)
|
||||||
// Do nothing
|
if (mimeType != null) {
|
||||||
}
|
return WebResourceResponse(
|
||||||
} else if (url.lowercase(Locale.US).contains(".png")) {
|
mimeType,
|
||||||
try {
|
"UTF-8",
|
||||||
val image =
|
getBitmapInputStream(image, Bitmap.CompressFormat.WEBP)
|
||||||
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) {
|
} catch (e: ExecutionException) {
|
||||||
// Do nothing
|
// Do nothing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.shouldInterceptRequest(view, url)
|
return super.shouldInterceptRequest(view, request)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -382,13 +398,23 @@ class ArticleFragment : Fragment(), DIAware {
|
|||||||
|
|
||||||
|
|
||||||
binding.webcontent.settings.standardFontFamily = a.getString(0)
|
binding.webcontent.settings.standardFontFamily = a.getString(0)
|
||||||
|
a.recycle()
|
||||||
|
|
||||||
binding.webcontent.visibility = View.VISIBLE
|
binding.webcontent.visibility = View.VISIBLE
|
||||||
|
|
||||||
val colorOnSurface = TypedValue()
|
val colorOnSurface = TypedValue()
|
||||||
requireContext().theme.resolveAttribute(R.attr.colorOnSurface, colorOnSurface, true)
|
requireContext().theme.resolveAttribute(
|
||||||
|
com.google.android.material.R.attr.colorOnSurface,
|
||||||
|
colorOnSurface,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
|
||||||
val colorSurface = TypedValue()
|
val colorSurface = TypedValue()
|
||||||
requireContext().theme.resolveAttribute(R.attr.colorSurface, colorSurface, true)
|
requireContext().theme.resolveAttribute(
|
||||||
|
com.google.android.material.R.attr.colorSurface,
|
||||||
|
colorSurface,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
|
||||||
binding.webcontent.settings.useWideViewPort = true
|
binding.webcontent.settings.useWideViewPort = true
|
||||||
binding.webcontent.settings.loadWithOverviewMode = true
|
binding.webcontent.settings.loadWithOverviewMode = true
|
||||||
@ -457,7 +483,7 @@ class ArticleFragment : Fragment(), DIAware {
|
|||||||
| color: ${
|
| color: ${
|
||||||
String.format(
|
String.format(
|
||||||
"#%06X",
|
"#%06X",
|
||||||
0xFFFFFF and resources.getColor(R.color.colorAccent)
|
0xFFFFFF and ContextCompat.getColor(requireContext(), R.color.colorAccent)
|
||||||
)
|
)
|
||||||
} !important;
|
} !important;
|
||||||
| }
|
| }
|
||||||
|
@ -12,6 +12,7 @@ import android.view.View
|
|||||||
import android.view.View.GONE
|
import android.view.View.GONE
|
||||||
import android.view.View.VISIBLE
|
import android.view.View.VISIBLE
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
import bou.amine.apps.readerforselfossv2.android.HomeActivity
|
import bou.amine.apps.readerforselfossv2.android.HomeActivity
|
||||||
import bou.amine.apps.readerforselfossv2.android.R
|
import bou.amine.apps.readerforselfossv2.android.R
|
||||||
import bou.amine.apps.readerforselfossv2.android.databinding.FilterFragmentBinding
|
import bou.amine.apps.readerforselfossv2.android.databinding.FilterFragmentBinding
|
||||||
@ -20,7 +21,7 @@ import bou.amine.apps.readerforselfossv2.repository.Repository
|
|||||||
import bou.amine.apps.readerforselfossv2.utils.getHtmlDecoded
|
import bou.amine.apps.readerforselfossv2.utils.getHtmlDecoded
|
||||||
import bou.amine.apps.readerforselfossv2.utils.getIcon
|
import bou.amine.apps.readerforselfossv2.utils.getIcon
|
||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
import com.bumptech.glide.request.target.ViewTarget
|
import com.bumptech.glide.request.target.CustomViewTarget
|
||||||
import com.bumptech.glide.request.transition.Transition
|
import com.bumptech.glide.request.transition.Transition
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||||
import com.google.android.material.chip.Chip
|
import com.google.android.material.chip.Chip
|
||||||
@ -82,13 +83,13 @@ class FilterSheetFragment : BottomSheetDialogFragment(), DIAware {
|
|||||||
) {
|
) {
|
||||||
val sourceGroup = binding.sourcesGroup
|
val sourceGroup = binding.sourcesGroup
|
||||||
|
|
||||||
repository.getSourcesDetailsOrStats().forEach { source ->
|
repository.getSourcesDetailsOrStats().forEachIndexed { _, source ->
|
||||||
val c = Chip(context)
|
val c = Chip(context)
|
||||||
c.ellipsize = TextUtils.TruncateAt.END
|
c.ellipsize = TextUtils.TruncateAt.END
|
||||||
|
|
||||||
Glide.with(context)
|
Glide.with(context)
|
||||||
.load(source.getIcon(repository.baseUrl))
|
.load(source.getIcon(repository.baseUrl))
|
||||||
.into(object : ViewTarget<Chip?, Drawable?>(c) {
|
.into(object : CustomViewTarget<Chip, Drawable>(c) {
|
||||||
override fun onResourceReady(
|
override fun onResourceReady(
|
||||||
resource: Drawable,
|
resource: Drawable,
|
||||||
transition: Transition<in Drawable?>?
|
transition: Transition<in Drawable?>?
|
||||||
@ -100,6 +101,13 @@ 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()
|
c.text = source.title.getHtmlDecoded()
|
||||||
@ -144,7 +152,7 @@ class FilterSheetFragment : BottomSheetDialogFragment(), DIAware {
|
|||||||
|
|
||||||
val tags = repository.getTags()
|
val tags = repository.getTags()
|
||||||
|
|
||||||
tags.forEach { tag ->
|
tags.forEachIndexed { _, tag ->
|
||||||
val c = Chip(context)
|
val c = Chip(context)
|
||||||
c.ellipsize = TextUtils.TruncateAt.END
|
c.ellipsize = TextUtils.TruncateAt.END
|
||||||
c.text = tag.tag
|
c.text = tag.tag
|
||||||
@ -156,7 +164,7 @@ class FilterSheetFragment : BottomSheetDialogFragment(), DIAware {
|
|||||||
Color.parseColor(tag.color)
|
Color.parseColor(tag.color)
|
||||||
} catch (e: IllegalArgumentException) {
|
} catch (e: IllegalArgumentException) {
|
||||||
e.sendSilentlyWithAcraWithName("color issue " + tag.color)
|
e.sendSilentlyWithAcraWithName("color issue " + tag.color)
|
||||||
resources.getColor(R.color.colorPrimary)
|
ContextCompat.getColor(context, R.color.colorPrimary)
|
||||||
}
|
}
|
||||||
gd.setColor(gdColor)
|
gd.setColor(gdColor)
|
||||||
gd.shape = GradientDrawable.RECTANGLE
|
gd.shape = GradientDrawable.RECTANGLE
|
||||||
|
@ -71,23 +71,25 @@ class SettingsActivity : AppCompatActivity(),
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onPreferenceStartFragment(
|
override fun onPreferenceStartFragment(
|
||||||
caller: PreferenceFragmentCompat,
|
caller: PreferenceFragmentCompat,
|
||||||
pref: Preference
|
pref: Preference
|
||||||
): Boolean {
|
): Boolean {
|
||||||
|
val fragmentClassName = pref.fragment ?: return false
|
||||||
|
|
||||||
// Instantiate the new Fragment
|
// Instantiate the new Fragment
|
||||||
val args = pref.extras
|
val args = pref.extras
|
||||||
val fragment = supportFragmentManager.fragmentFactory.instantiate(
|
val fragment = supportFragmentManager.fragmentFactory.instantiate(
|
||||||
classLoader,
|
classLoader,
|
||||||
pref.fragment
|
fragmentClassName
|
||||||
).apply {
|
).apply {
|
||||||
arguments = args
|
arguments = args
|
||||||
setTargetFragment(caller, 0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace the existing Fragment with the new Fragment
|
// Replace the existing Fragment with the new Fragment
|
||||||
supportFragmentManager.beginTransaction()
|
supportFragmentManager.beginTransaction()
|
||||||
.replace(R.id.settings, fragment)
|
.replace(R.id.settings, fragment)
|
||||||
.addToBackStack(null)
|
.addToBackStack(null)
|
||||||
.commit()
|
.commit()
|
||||||
title = pref.title
|
title = pref.title
|
||||||
supportActionBar?.title = title
|
supportActionBar?.title = title
|
||||||
return true
|
return true
|
||||||
|
@ -95,6 +95,7 @@ class LinkOnTouchListener : View.OnTouchListener {
|
|||||||
if (link.isNotEmpty()) {
|
if (link.isNotEmpty()) {
|
||||||
if (action == MotionEvent.ACTION_UP) {
|
if (action == MotionEvent.ACTION_UP) {
|
||||||
link[0].onClick(widget)
|
link[0].onClick(widget)
|
||||||
|
widget.performClick()
|
||||||
}
|
}
|
||||||
ret = true
|
ret = true
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
buildscript {
|
buildscript {
|
||||||
dependencies {
|
dependencies {
|
||||||
// SqlDelight
|
// SqlDelight
|
||||||
classpath("com.squareup.sqldelight:gradle-plugin:1.5.4")
|
classpath("com.squareup.sqldelight:gradle-plugin:1.5.5")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
//trick: for the same plugin versions in all sub-modules
|
//trick: for the same plugin versions in all sub-modules
|
||||||
id("com.android.application").version("7.4.0").apply(false)
|
id("com.android.application").version("8.1.0").apply(false)
|
||||||
id("com.android.library").version("7.4.0").apply(false)
|
id("com.android.library").version("8.1.0").apply(false)
|
||||||
kotlin("android").version("1.7.20").apply(false)
|
id("org.jetbrains.kotlin.android").version("1.9.10").apply(false)
|
||||||
kotlin("multiplatform").version("1.7.20").apply(false)
|
kotlin("multiplatform").version("1.9.10").apply(false)
|
||||||
id("com.mikepenz.aboutlibraries.plugin").version("10.5.1").apply(false)
|
id("com.mikepenz.aboutlibraries.plugin").version("10.5.1").apply(false)
|
||||||
id("org.jetbrains.kotlinx.kover") version "0.6.1"
|
id("org.jetbrains.kotlinx.kover").version("0.6.1").apply(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
@ -20,7 +20,6 @@ allprojects {
|
|||||||
// maven { url = uri("https://nexus.amine-louveau.fr/repository/maven-public/")}
|
// maven { url = uri("https://nexus.amine-louveau.fr/repository/maven-public/")}
|
||||||
google()
|
google()
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
jcenter()
|
|
||||||
maven { url = uri("https://www.jitpack.io") }
|
maven { url = uri("https://www.jitpack.io") }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,22 +13,15 @@
|
|||||||
#Tue Mar 22 16:50:00 CET 2022
|
#Tue Mar 22 16:50:00 CET 2022
|
||||||
#Gradle
|
#Gradle
|
||||||
org.gradle.jvmargs=-Xmx2048M -Dfile.encoding=UTF-8 -Dkotlin.daemon.jvm.options\="-Xmx2048M"
|
org.gradle.jvmargs=-Xmx2048M -Dfile.encoding=UTF-8 -Dkotlin.daemon.jvm.options\="-Xmx2048M"
|
||||||
|
|
||||||
#Kotlin
|
#Kotlin
|
||||||
kotlin.code.style=official
|
kotlin.code.style=official
|
||||||
|
|
||||||
#Android
|
#Android
|
||||||
android.useAndroidX=true
|
android.useAndroidX=true
|
||||||
kotlin.native.enableDependencyPropagation=false
|
|
||||||
#android.nonTransitiveRClass=true
|
#android.nonTransitiveRClass=true
|
||||||
android.enableJetifier=true
|
android.enableJetifier=true
|
||||||
|
android.nonTransitiveRClass=true
|
||||||
|
|
||||||
#MPP
|
#MPP
|
||||||
kotlin.mpp.enableCInteropCommonization=true
|
kotlin.mpp.enableCInteropCommonization=true
|
||||||
kotlin.mpp.enableGranularSourceSetsMetadata=true
|
|
||||||
|
|
||||||
|
|
||||||
org.gradle.parallel=true
|
org.gradle.parallel=true
|
||||||
org.gradle.caching=true
|
org.gradle.caching=true
|
||||||
ignoreGitVersion=false
|
ignoreGitVersion=false
|
||||||
|
6
gradle/wrapper/gradle-wrapper.properties
vendored
6
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,6 +1,6 @@
|
|||||||
#Mon Jan 23 20:47:46 CET 2023
|
#Thu Jul 13 11:41:19 CEST 2023
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
|
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStorePath=wrapper/dists
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
zipStorePath=wrapper/dists
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
val ktorVersion = "2.3.2"
|
||||||
|
|
||||||
object SqlDelight {
|
object SqlDelight {
|
||||||
const val runtime = "com.squareup.sqldelight:runtime:1.5.4"
|
const val runtime = "com.squareup.sqldelight:runtime:1.5.4"
|
||||||
const val android = "com.squareup.sqldelight:android-driver:1.5.4"
|
const val android = "com.squareup.sqldelight:android-driver:1.5.4"
|
||||||
@ -9,12 +11,12 @@ plugins {
|
|||||||
kotlin("multiplatform")
|
kotlin("multiplatform")
|
||||||
id("com.android.library")
|
id("com.android.library")
|
||||||
id("com.squareup.sqldelight")
|
id("com.squareup.sqldelight")
|
||||||
kotlin("plugin.serialization") version "1.4.10"
|
kotlin("plugin.serialization") version "1.9.0"
|
||||||
id("org.jetbrains.kotlinx.kover") version "0.6.1"
|
id("org.jetbrains.kotlinx.kover")
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
android()
|
androidTarget()
|
||||||
|
|
||||||
listOf(
|
listOf(
|
||||||
iosX64(),
|
iosX64(),
|
||||||
@ -29,16 +31,17 @@ kotlin {
|
|||||||
sourceSets {
|
sourceSets {
|
||||||
val commonMain by getting {
|
val commonMain by getting {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("io.ktor:ktor-client-core:2.1.1")
|
implementation("io.ktor:ktor-client-core:$ktorVersion")
|
||||||
implementation("io.ktor:ktor-client-content-negotiation:2.1.1")
|
implementation("io.ktor:ktor-client-content-negotiation:$ktorVersion")
|
||||||
implementation("io.ktor:ktor-serialization-kotlinx-json:2.1.1")
|
implementation("io.ktor:ktor-serialization-kotlinx-json:$ktorVersion")
|
||||||
implementation("io.ktor:ktor-client-logging:2.1.1")
|
implementation("io.ktor:ktor-client-logging:$ktorVersion")
|
||||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0")
|
implementation("io.ktor:ktor-client-auth:$ktorVersion")
|
||||||
implementation("io.ktor:ktor-client-auth:2.1.1")
|
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.1")
|
||||||
implementation("org.jsoup:jsoup:1.14.3")
|
|
||||||
|
implementation("org.jsoup:jsoup:1.15.4")
|
||||||
|
|
||||||
//Dependency Injection
|
//Dependency Injection
|
||||||
implementation("org.kodein.di:kodein-di:7.12.0")
|
implementation("org.kodein.di:kodein-di:7.14.0")
|
||||||
|
|
||||||
//Settings
|
//Settings
|
||||||
implementation("com.russhwolf:multiplatform-settings-no-arg:1.0.0-RC")
|
implementation("com.russhwolf:multiplatform-settings-no-arg:1.0.0-RC")
|
||||||
@ -58,14 +61,15 @@ kotlin {
|
|||||||
}
|
}
|
||||||
val androidMain by getting {
|
val androidMain by getting {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("io.ktor:ktor-client-okhttp:2.1.1")
|
implementation("com.squareup.okhttp3:okhttp:4.11.0")
|
||||||
|
implementation("io.ktor:ktor-client-okhttp:2.2.4")
|
||||||
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.4.0")
|
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.4.0")
|
||||||
|
|
||||||
// Sql
|
// Sql
|
||||||
implementation(SqlDelight.android)
|
implementation(SqlDelight.android)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val androidTest by getting {
|
val androidUnitTest by getting {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(kotlin("test-junit"))
|
implementation(kotlin("test-junit"))
|
||||||
implementation("junit:junit:4.13.2")
|
implementation("junit:junit:4.13.2")
|
||||||
@ -98,15 +102,14 @@ kotlin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdk = 32
|
compileSdk = 33
|
||||||
sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
|
sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdk = 21
|
minSdk = 21
|
||||||
targetSdk = 32
|
|
||||||
}
|
}
|
||||||
compileOptions {
|
compileOptions {
|
||||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
sourceCompatibility = JavaVersion.VERSION_17
|
||||||
targetCompatibility = JavaVersion.VERSION_1_8
|
targetCompatibility = JavaVersion.VERSION_17
|
||||||
}
|
}
|
||||||
namespace = "bou.amine.apps.readerforselfossv2"
|
namespace = "bou.amine.apps.readerforselfossv2"
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,19 @@
|
|||||||
package bou.amine.apps.readerforselfossv2.utils
|
package bou.amine.apps.readerforselfossv2.utils
|
||||||
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
import android.os.Build
|
||||||
import android.text.Html
|
import android.text.Html
|
||||||
import bou.amine.apps.readerforselfossv2.model.SelfossModel
|
import bou.amine.apps.readerforselfossv2.model.SelfossModel
|
||||||
import org.jsoup.Jsoup
|
import org.jsoup.Jsoup
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
actual fun String.getHtmlDecoded(): String {
|
actual fun String.getHtmlDecoded(): String {
|
||||||
return Html.fromHtml(this).toString()
|
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()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
actual fun SelfossModel.Item.getIcon(baseUrl: String): String {
|
actual fun SelfossModel.Item.getIcon(baseUrl: String): String {
|
||||||
@ -19,19 +25,10 @@ actual fun SelfossModel.Item.getThumbnail(baseUrl: String): String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
actual fun SelfossModel.Item.getImages(): ArrayList<String> {
|
actual fun SelfossModel.Item.getImages(): ArrayList<String> {
|
||||||
val allImages = ArrayList<String>()
|
val doc = Jsoup.parse(content)
|
||||||
|
val images = doc.getElementsByTag("img")
|
||||||
|
|
||||||
for ( image in Jsoup.parse(content).getElementsByTag("img")) {
|
return ArrayList(images.map { it.attr("src") })
|
||||||
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 {
|
actual fun SelfossModel.Source.getIcon(baseUrl: String): String {
|
||||||
|
@ -17,7 +17,7 @@ fun SOURCE.toView(): SelfossModel.SourceDetail =
|
|||||||
this.id.toInt(),
|
this.id.toInt(),
|
||||||
this.title,
|
this.title,
|
||||||
null,
|
null,
|
||||||
this.tags?.split(","),
|
this.tags.split(","),
|
||||||
this.spout,
|
this.spout,
|
||||||
this.error,
|
this.error,
|
||||||
this.icon,
|
this.icon,
|
||||||
|
@ -9,3 +9,19 @@ enum class ItemType(val position: Int, val type: String) {
|
|||||||
fun fromInt(value: Int) = values().first { it.position == value }
|
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
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user