Compare commits
12 Commits
v122123483
...
v122123601
Author | SHA1 | Date | |
---|---|---|---|
a5e86bfb77 | |||
23be633798 | |||
813e0707d8 | |||
9ed9bf07fc | |||
47265c10d0 | |||
5cc633246a | |||
1f40385786 | |||
eb2876324a | |||
633b817d76 | |||
2cfaa9b285 | |||
f42ae97326 | |||
3b0028164b |
@ -17,6 +17,7 @@ steps:
|
||||
- echo "---------------------------------------------------------"
|
||||
- ./gradlew koverMergedXmlReport
|
||||
environment:
|
||||
TZ: Europe/Paris
|
||||
SONAR_HOST_URL:
|
||||
from_secret: sonarScannerHostUrl
|
||||
SONAR_LOGIN:
|
||||
@ -50,6 +51,7 @@ steps:
|
||||
- git remote add pushing https://$GITEA_USR:$GITEA_PASS@gitea.amine-louveau.fr/Louvorg/ReaderForSelfoss-multiplatform.git
|
||||
- git push pushing --tags
|
||||
environment:
|
||||
TZ: Europe/Paris
|
||||
GITEA_USR:
|
||||
from_secret: giteaUsr
|
||||
GITEA_PASS:
|
||||
@ -117,6 +119,7 @@ steps:
|
||||
- echo "Verify"
|
||||
- $ANDROID_HOME/build-tools/31.0.0/apksigner verify signed.apk
|
||||
environment:
|
||||
TZ: Europe/Paris
|
||||
YOUR_KEYSTORE_PASSWORD:
|
||||
from_secret: keyPass
|
||||
YOUR_KEY_ALIAS:
|
||||
|
@ -146,8 +146,8 @@ dependencies {
|
||||
implementation("com.amulyakhare:com.amulyakhare.textdrawable:1.0.1")
|
||||
|
||||
// glide
|
||||
kapt("com.github.bumptech.glide:compiler:4.11.0")
|
||||
implementation("com.github.bumptech.glide:okhttp3-integration:4.1.1")
|
||||
kapt("com.github.bumptech.glide:compiler:4.14.2")
|
||||
implementation("com.github.bumptech.glide:okhttp3-integration:4.14.2")
|
||||
|
||||
// Themes
|
||||
implementation("com.github.rubensousa:floatingtoolbar:1.5.1")
|
||||
@ -188,9 +188,6 @@ dependencies {
|
||||
|
||||
implementation("ch.acra:acra-http:$acraVersion")
|
||||
implementation("ch.acra:acra-toast:$acraVersion")
|
||||
|
||||
// Matomo
|
||||
implementation("com.github.matomo-org:matomo-sdk-android:4.1.4")
|
||||
}
|
||||
|
||||
tasks.withType<Test> {
|
||||
|
@ -4,6 +4,6 @@ import org.acra.ACRA
|
||||
import org.acra.ktx.sendSilentlyWithAcra
|
||||
|
||||
fun Throwable.sendSilentlyWithAcraWithName(name: String) {
|
||||
ACRA.errorReporter.putCustomData("error_source", name)
|
||||
ACRA.errorReporter.putCustomData("error_source", name)
|
||||
this.sendSilentlyWithAcra()
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
package bou.amine.apps.readerforselfossv2.android
|
||||
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
@ -40,8 +39,6 @@ import kotlinx.coroutines.launch
|
||||
import org.kodein.di.DIAware
|
||||
import org.kodein.di.android.closestDI
|
||||
import org.kodein.di.instance
|
||||
import org.matomo.sdk.Tracker
|
||||
import org.matomo.sdk.extra.TrackHelper
|
||||
import java.security.MessageDigest
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
@ -72,7 +69,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
|
||||
override val di by closestDI()
|
||||
private val repository : Repository by instance()
|
||||
private val appSettingsService : AppSettingsService by instance()
|
||||
private val tracker : Tracker by instance()
|
||||
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
@ -80,8 +76,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
|
||||
binding = ActivityHomeBinding.inflate(layoutInflater)
|
||||
val view = binding.root
|
||||
|
||||
TrackHelper.track().screen("/home").with(tracker)
|
||||
|
||||
fromTabShortcut = intent.getIntExtra("shortcutTab", -1) != -1
|
||||
repository.offlineOverride = intent.getBooleanExtra("startOffline", false)
|
||||
|
||||
@ -600,9 +594,9 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
|
||||
CoroutineScope(Dispatchers.Main).launch {
|
||||
repository.logout()
|
||||
}
|
||||
this@HomeActivity.finish()
|
||||
val intent = Intent(this, LoginActivity::class.java)
|
||||
this.startActivity(intent)
|
||||
this@HomeActivity.finish()
|
||||
return true
|
||||
}
|
||||
R.id.action_settings -> {
|
||||
|
@ -11,6 +11,7 @@ import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
@ -22,13 +23,10 @@ import com.mikepenz.aboutlibraries.LibsBuilder
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import org.acra.ACRA
|
||||
import org.kodein.di.DIAware
|
||||
import org.kodein.di.android.closestDI
|
||||
import org.kodein.di.instance
|
||||
import org.matomo.sdk.Tracker
|
||||
import org.matomo.sdk.extra.DimensionQueue
|
||||
import org.matomo.sdk.extra.DownloadTracker
|
||||
import org.matomo.sdk.extra.TrackHelper
|
||||
import java.security.MessageDigest
|
||||
|
||||
|
||||
@ -40,18 +38,13 @@ class LoginActivity : AppCompatActivity(), DIAware {
|
||||
private lateinit var binding: ActivityLoginBinding
|
||||
|
||||
override val di by closestDI()
|
||||
private val repository : Repository by instance()
|
||||
private val appSettingsService : AppSettingsService by instance()
|
||||
private val tracker : Tracker by instance()
|
||||
private val repository: Repository by instance()
|
||||
private val appSettingsService: AppSettingsService by instance()
|
||||
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
TrackHelper.track().download().identifier(DownloadTracker.Extra.ApkChecksum(applicationContext))
|
||||
.with(tracker)
|
||||
TrackHelper.track().screen("/login").with(tracker)
|
||||
|
||||
handleTheme()
|
||||
|
||||
binding = ActivityLoginBinding.inflate(layoutInflater)
|
||||
@ -64,7 +57,30 @@ class LoginActivity : AppCompatActivity(), DIAware {
|
||||
handleBaseUrlFail()
|
||||
|
||||
if (appSettingsService.getBaseUrl().isNotEmpty()) {
|
||||
goToMain()
|
||||
showProgress(true)
|
||||
// This should be reverted when "old" users connected with a non-selfoss rss
|
||||
// are handled. Revert to "simple" way.
|
||||
CoroutineScope(Dispatchers.Main).launch {
|
||||
try {
|
||||
val (errorFetching, displaySelfossOnly) = repository.shouldBeSelfossInstance()
|
||||
if (!errorFetching && !displaySelfossOnly) {
|
||||
goToMain()
|
||||
} else {
|
||||
showProgress(false)
|
||||
if (displaySelfossOnly) {
|
||||
Toast.makeText(
|
||||
applicationContext,
|
||||
R.string.application_selfoss_only,
|
||||
Toast.LENGTH_LONG
|
||||
).show()
|
||||
}
|
||||
repository.logout()
|
||||
}
|
||||
} catch (e: Throwable) {
|
||||
repository.logout()
|
||||
showProgress(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
handleActions()
|
||||
@ -114,15 +130,7 @@ class LoginActivity : AppCompatActivity(), DIAware {
|
||||
private fun goToMain() {
|
||||
CoroutineScope(Dispatchers.Main).launch {
|
||||
repository.updateApiVersion()
|
||||
|
||||
val messageDigest: MessageDigest = MessageDigest.getInstance("SHA-256")
|
||||
messageDigest.update(appSettingsService.getBaseUrl().toByteArray())
|
||||
tracker.userId = String(messageDigest.digest())
|
||||
|
||||
val mDimensionQueue = DimensionQueue(tracker)
|
||||
mDimensionQueue.add(1, appSettingsService.getApiVersion().toString())
|
||||
|
||||
tracker.isOptOut = !appSettingsService.isAnalyticsEnabled()
|
||||
ACRA.errorReporter.putCustomData("SELFOSS_API_VERSION", appSettingsService.getApiVersion().toString())
|
||||
}
|
||||
val intent = Intent(this, HomeActivity::class.java)
|
||||
startActivity(intent)
|
||||
@ -191,17 +199,27 @@ class LoginActivity : AppCompatActivity(), DIAware {
|
||||
|
||||
repository.refreshLoginInformation(url, login, password)
|
||||
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
CoroutineScope(Dispatchers.Main).launch {
|
||||
val result = repository.login()
|
||||
if (result) {
|
||||
goToMain()
|
||||
} else {
|
||||
CoroutineScope(Dispatchers.Main).launch {
|
||||
val (errorFetching, displaySelfossOnly) = repository.shouldBeSelfossInstance()
|
||||
if (!errorFetching && !displaySelfossOnly) {
|
||||
goToMain()
|
||||
} else {
|
||||
if (displaySelfossOnly) {
|
||||
Toast.makeText(
|
||||
applicationContext,
|
||||
R.string.application_selfoss_only,
|
||||
Toast.LENGTH_LONG
|
||||
).show()
|
||||
}
|
||||
preferenceError()
|
||||
}
|
||||
} else {
|
||||
preferenceError()
|
||||
}
|
||||
showProgress(false)
|
||||
}
|
||||
showProgress(false)
|
||||
}
|
||||
}
|
||||
|
||||
@ -215,11 +233,11 @@ class LoginActivity : AppCompatActivity(), DIAware {
|
||||
.alpha(
|
||||
if (show) 0F else 1F
|
||||
).setListener(object : AnimatorListenerAdapter() {
|
||||
override fun onAnimationEnd(animation: Animator) {
|
||||
binding.loginForm.visibility = if (show) View.GONE else View.VISIBLE
|
||||
override fun onAnimationEnd(animation: Animator) {
|
||||
binding.loginForm.visibility = if (show) View.GONE else View.VISIBLE
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
binding.loginProgress.visibility = if (show) View.VISIBLE else View.GONE
|
||||
binding.loginProgress
|
||||
@ -228,11 +246,11 @@ class LoginActivity : AppCompatActivity(), DIAware {
|
||||
.alpha(
|
||||
if (show) 1F else 0F
|
||||
).setListener(object : AnimatorListenerAdapter() {
|
||||
override fun onAnimationEnd(animation: Animator) {
|
||||
binding.loginProgress.visibility = if (show) View.VISIBLE else View.GONE
|
||||
override fun onAnimationEnd(animation: Animator) {
|
||||
binding.loginProgress.visibility = if (show) View.VISIBLE else View.GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
|
@ -35,9 +35,6 @@ import org.acra.data.StringFormat
|
||||
import org.acra.ktx.initAcra
|
||||
import org.acra.sender.HttpSender
|
||||
import org.kodein.di.*
|
||||
import org.matomo.sdk.Matomo
|
||||
import org.matomo.sdk.Tracker
|
||||
import org.matomo.sdk.TrackerBuilder
|
||||
|
||||
class MyApp : MultiDexApplication(), DIAware {
|
||||
|
||||
@ -48,8 +45,6 @@ class MyApp : MultiDexApplication(), DIAware {
|
||||
bind<Repository>() with singleton { Repository(instance(), instance(), isConnectionAvailable, instance()) }
|
||||
bind<ConnectivityStatus>() with singleton { ConnectivityStatus(applicationContext) }
|
||||
bind<AppViewModel>() with singleton { AppViewModel(repository = instance()) }
|
||||
bind<Tracker>() with singleton { TrackerBuilder.createDefault("https://matomo.amine-louveau.fr/matomo.php", if (BuildConfig.DEBUG) 4 else 5).build(
|
||||
Matomo.getInstance(applicationContext)) }
|
||||
}
|
||||
|
||||
private val repository: Repository by instance()
|
||||
|
@ -30,6 +30,8 @@ class ReaderActivity : AppCompatActivity(), DIAware {
|
||||
|
||||
private lateinit var binding: ActivityReaderBinding
|
||||
|
||||
private var allItems: ArrayList<SelfossModel.Item> = ArrayList()
|
||||
|
||||
override val di by closestDI()
|
||||
private val repository: Repository by instance()
|
||||
private val appSettingsService: AppSettingsService by instance()
|
||||
@ -61,12 +63,14 @@ class ReaderActivity : AppCompatActivity(), DIAware {
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
supportActionBar?.setDisplayShowHomeEnabled(true)
|
||||
|
||||
if (allItems.isEmpty()) {
|
||||
currentItem = intent.getIntExtra("currentItem", 0)
|
||||
|
||||
allItems = repository.getReaderItems()
|
||||
|
||||
if (allItems.isEmpty() || currentItem > allItems.size) {
|
||||
finish()
|
||||
}
|
||||
|
||||
currentItem = intent.getIntExtra("currentItem", 0)
|
||||
|
||||
readItem(allItems[currentItem])
|
||||
|
||||
binding.pager.adapter = ScreenSlidePagerAdapter(this)
|
||||
@ -214,8 +218,4 @@ class ReaderActivity : AppCompatActivity(), DIAware {
|
||||
startActivity(intent)
|
||||
overridePendingTransition(0, 0)
|
||||
}
|
||||
|
||||
companion object {
|
||||
var allItems: ArrayList<SelfossModel.Item> = ArrayList()
|
||||
}
|
||||
}
|
||||
|
@ -132,8 +132,8 @@ class ItemCardAdapter(
|
||||
|
||||
private fun handleLinkOpening() {
|
||||
binding.root.setOnClickListener {
|
||||
repository.setReaderItems(items)
|
||||
c.openItemUrl(
|
||||
items,
|
||||
bindingAdapterPosition,
|
||||
items[bindingAdapterPosition].getLinkDecoded(),
|
||||
appSettingsService.isArticleViewerEnabled(),
|
||||
|
@ -84,8 +84,8 @@ class ItemListAdapter(
|
||||
|
||||
private fun handleLinkOpening() {
|
||||
binding.root.setOnClickListener {
|
||||
repository.setReaderItems(items)
|
||||
c.openItemUrl(
|
||||
items,
|
||||
bindingAdapterPosition,
|
||||
items[bindingAdapterPosition].getLinkDecoded(),
|
||||
appSettingsService.isArticleViewerEnabled(),
|
||||
|
@ -36,9 +36,7 @@ abstract class ItemsAdapter<VH : RecyclerView.ViewHolder?> : RecyclerView.Adapte
|
||||
Snackbar.LENGTH_LONG
|
||||
)
|
||||
.setAction(R.string.undo_string) {
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
unreadItemAtIndex(item, position, false)
|
||||
}
|
||||
unreadItemAtIndex(item, position, false)
|
||||
}
|
||||
|
||||
val view = s.view
|
||||
|
@ -16,7 +16,6 @@ import android.webkit.WebView
|
||||
import android.webkit.WebViewClient
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.content.res.ResourcesCompat
|
||||
import androidx.core.widget.NestedScrollView
|
||||
import androidx.fragment.app.Fragment
|
||||
import bou.amine.apps.readerforselfossv2.android.ImageActivity
|
||||
@ -45,8 +44,6 @@ import com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import org.acra.ktx.sendSilentlyWithAcra
|
||||
import org.acra.ktx.sendWithAcra
|
||||
import org.kodein.di.DI
|
||||
import org.kodein.di.DIAware
|
||||
import org.kodein.di.android.x.closestDI
|
||||
@ -343,14 +340,14 @@ class ArticleFragment : Fragment(), DIAware {
|
||||
}
|
||||
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun shouldInterceptRequest(view: WebView?, url: String): WebResourceResponse? {
|
||||
override fun shouldInterceptRequest(view: WebView, url: String): WebResourceResponse? {
|
||||
val glideOptions = RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.ALL)
|
||||
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()
|
||||
return WebResourceResponse("image/jpg", "UTF-8", getBitmapInputStream(image, Bitmap.CompressFormat.JPEG))
|
||||
} catch ( e : ExecutionException) {
|
||||
e.sendSilentlyWithAcraWithName("shouldInterceptRequest > jpeg")
|
||||
e.sendSilentlyWithAcraWithName("shouldInterceptRequest > jpeg > $url")
|
||||
}
|
||||
}
|
||||
else if (url.lowercase(Locale.US).contains(".png")) {
|
||||
@ -358,7 +355,7 @@ class ArticleFragment : Fragment(), DIAware {
|
||||
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) {
|
||||
e.sendSilentlyWithAcraWithName("shouldInterceptRequest > png")
|
||||
e.sendSilentlyWithAcraWithName("shouldInterceptRequest > png > $url")
|
||||
}
|
||||
}
|
||||
else if (url.lowercase(Locale.US).contains(".webp")) {
|
||||
@ -366,7 +363,7 @@ class ArticleFragment : Fragment(), DIAware {
|
||||
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) {
|
||||
e.sendSilentlyWithAcraWithName("shouldInterceptRequest > webp")
|
||||
e.sendSilentlyWithAcraWithName("shouldInterceptRequest > webp > $url")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
package bou.amine.apps.readerforselfossv2.android.fragments
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.graphics.drawable.GradientDrawable
|
||||
@ -13,9 +13,7 @@ import android.view.ViewGroup
|
||||
import bou.amine.apps.readerforselfossv2.android.HomeActivity
|
||||
import bou.amine.apps.readerforselfossv2.android.R
|
||||
import bou.amine.apps.readerforselfossv2.android.sendSilentlyWithAcraWithName
|
||||
import bou.amine.apps.readerforselfossv2.model.SelfossModel
|
||||
import bou.amine.apps.readerforselfossv2.repository.Repository
|
||||
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
||||
import bou.amine.apps.readerforselfossv2.utils.getHtmlDecoded
|
||||
import bou.amine.apps.readerforselfossv2.utils.getIcon
|
||||
import com.bumptech.glide.Glide
|
||||
@ -38,16 +36,14 @@ class FilterSheetFragment : BottomSheetDialogFragment(), DIAware {
|
||||
|
||||
override val di: DI by closestDI()
|
||||
private val repository: Repository by instance()
|
||||
private val appSettingsService: AppSettingsService by instance()
|
||||
|
||||
private var selectedChip: Chip? = null
|
||||
|
||||
@SuppressLint("ResourceAsColor")
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
): View {
|
||||
val binding =
|
||||
bou.amine.apps.readerforselfossv2.android.databinding.FilterFragmentBinding.inflate(
|
||||
inflater,
|
||||
@ -55,74 +51,118 @@ class FilterSheetFragment : BottomSheetDialogFragment(), DIAware {
|
||||
false
|
||||
)
|
||||
|
||||
val context: Context? = context
|
||||
|
||||
val tagGroup = binding.tagsGroup
|
||||
val sourceGroup = binding.sourcesGroup
|
||||
|
||||
CoroutineScope(Dispatchers.Main).launch {
|
||||
val tags = repository.getTags()
|
||||
if (context == null) {
|
||||
dismiss()
|
||||
Exception("FilterSheetFragment context is null").sendSilentlyWithAcraWithName("FilterSheetFragment > onCreateView")
|
||||
} else {
|
||||
CoroutineScope(Dispatchers.Main).launch {
|
||||
val tags = repository.getTags()
|
||||
|
||||
tags.forEach { tag ->
|
||||
val c = chipForTag(tag)
|
||||
tagGroup.addView(c)
|
||||
}
|
||||
tags.forEach { tag ->
|
||||
val c = Chip(context)
|
||||
c.text = tag.tag
|
||||
|
||||
repository.getSources().forEach { source ->
|
||||
val c = Chip(requireContext())
|
||||
|
||||
Glide.with(requireContext())
|
||||
.load(source.getIcon(repository.baseUrl))
|
||||
.listener(object : RequestListener<Drawable?> {
|
||||
override fun onLoadFailed(
|
||||
e: GlideException?,
|
||||
model: Any?,
|
||||
target: Target<Drawable?>?,
|
||||
isFirstResource: Boolean
|
||||
): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onResourceReady(
|
||||
resource: Drawable?,
|
||||
model: Any?,
|
||||
target: Target<Drawable?>?,
|
||||
dataSource: DataSource?,
|
||||
isFirstResource: Boolean
|
||||
): Boolean {
|
||||
c.chipIcon = resource
|
||||
return false
|
||||
}
|
||||
}).preload()
|
||||
|
||||
c.text = source.title.getHtmlDecoded()
|
||||
|
||||
c.setOnCloseIconClickListener {
|
||||
(it as Chip).isCloseIconVisible = false
|
||||
selectedChip = null
|
||||
repository.setSourceFilter(null)
|
||||
}
|
||||
|
||||
c.setOnClickListener {
|
||||
if (selectedChip != null) {
|
||||
selectedChip!!.isCloseIconVisible = false
|
||||
val gd = GradientDrawable()
|
||||
val gdColor = try {
|
||||
Color.parseColor(tag.color)
|
||||
} catch (e: IllegalArgumentException) {
|
||||
e.sendSilentlyWithAcraWithName("color issue " + tag.color)
|
||||
resources.getColor(R.color.colorPrimary)
|
||||
}
|
||||
(it as Chip).isCloseIconVisible = true
|
||||
selectedChip = it
|
||||
repository.setSourceFilter(source)
|
||||
gd.setColor(gdColor)
|
||||
gd.shape = GradientDrawable.RECTANGLE
|
||||
gd.setSize(30, 30)
|
||||
gd.cornerRadius = 30F
|
||||
c.chipIcon = gd
|
||||
|
||||
repository.setTagFilter(null)
|
||||
c.setOnCloseIconClickListener {
|
||||
(it as Chip).isCloseIconVisible = false
|
||||
selectedChip = null
|
||||
repository.setTagFilter(null)
|
||||
}
|
||||
|
||||
c.setOnClickListener {
|
||||
if (selectedChip != null) {
|
||||
selectedChip!!.isCloseIconVisible = false
|
||||
}
|
||||
(it as Chip).isCloseIconVisible = true
|
||||
selectedChip = it
|
||||
repository.setTagFilter(tag)
|
||||
|
||||
repository.setSourceFilter(null)
|
||||
}
|
||||
|
||||
if (repository.tagFilter.value?.equals(tag) == true) {
|
||||
c.isCloseIconVisible = true
|
||||
selectedChip = c
|
||||
}
|
||||
|
||||
tagGroup.addView(c)
|
||||
}
|
||||
|
||||
repository.getSources().forEach { source ->
|
||||
val c = Chip(context)
|
||||
|
||||
if (repository.sourceFilter.value?.equals(source) == true) {
|
||||
c.isCloseIconVisible = true
|
||||
selectedChip = c
|
||||
Glide.with(context)
|
||||
.load(source.getIcon(repository.baseUrl))
|
||||
.listener(object : RequestListener<Drawable?> {
|
||||
override fun onLoadFailed(
|
||||
e: GlideException?,
|
||||
model: Any?,
|
||||
target: Target<Drawable?>?,
|
||||
isFirstResource: Boolean
|
||||
): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onResourceReady(
|
||||
resource: Drawable?,
|
||||
model: Any?,
|
||||
target: Target<Drawable?>?,
|
||||
dataSource: DataSource?,
|
||||
isFirstResource: Boolean
|
||||
): Boolean {
|
||||
c.chipIcon = resource
|
||||
return false
|
||||
}
|
||||
}).preload()
|
||||
|
||||
c.text = source.title.getHtmlDecoded()
|
||||
|
||||
c.setOnCloseIconClickListener {
|
||||
(it as Chip).isCloseIconVisible = false
|
||||
selectedChip = null
|
||||
repository.setSourceFilter(null)
|
||||
}
|
||||
|
||||
c.setOnClickListener {
|
||||
if (selectedChip != null) {
|
||||
selectedChip!!.isCloseIconVisible = false
|
||||
}
|
||||
(it as Chip).isCloseIconVisible = true
|
||||
selectedChip = it
|
||||
repository.setSourceFilter(source)
|
||||
|
||||
repository.setTagFilter(null)
|
||||
}
|
||||
|
||||
|
||||
if (repository.sourceFilter.value?.equals(source) == true) {
|
||||
c.isCloseIconVisible = true
|
||||
selectedChip = c
|
||||
}
|
||||
|
||||
sourceGroup.addView(c)
|
||||
}
|
||||
|
||||
sourceGroup.addView(c)
|
||||
binding.progressBar2.visibility = GONE
|
||||
binding.filterView.visibility = VISIBLE
|
||||
}
|
||||
|
||||
binding.progressBar2.visibility = GONE
|
||||
binding.filterView.visibility = VISIBLE
|
||||
}
|
||||
|
||||
binding.floatingActionButton2.setOnClickListener {
|
||||
@ -133,49 +173,8 @@ class FilterSheetFragment : BottomSheetDialogFragment(), DIAware {
|
||||
return binding.root
|
||||
}
|
||||
|
||||
private fun chipForTag(tag: SelfossModel.Tag): Chip {
|
||||
val c = Chip(requireContext())
|
||||
c.text = tag.tag
|
||||
|
||||
val gd = GradientDrawable()
|
||||
val gdColor = try {
|
||||
Color.parseColor(tag.color)
|
||||
} catch (e: IllegalArgumentException) {
|
||||
e.sendSilentlyWithAcraWithName("color issue " + tag.color)
|
||||
resources.getColor(R.color.colorPrimary)
|
||||
}
|
||||
gd.setColor(gdColor)
|
||||
gd.shape = GradientDrawable.RECTANGLE
|
||||
gd.setSize(30, 30)
|
||||
gd.cornerRadius = 30F
|
||||
c.chipIcon = gd
|
||||
|
||||
c.setOnCloseIconClickListener {
|
||||
(it as Chip).isCloseIconVisible = false
|
||||
selectedChip = null
|
||||
repository.setTagFilter(null)
|
||||
}
|
||||
|
||||
c.setOnClickListener {
|
||||
if (selectedChip != null) {
|
||||
selectedChip!!.isCloseIconVisible = false
|
||||
}
|
||||
(it as Chip).isCloseIconVisible = true
|
||||
selectedChip = it
|
||||
repository.setTagFilter(tag)
|
||||
|
||||
repository.setSourceFilter(null)
|
||||
}
|
||||
|
||||
if (repository.tagFilter.value?.equals(tag) == true) {
|
||||
c.isCloseIconVisible = true
|
||||
selectedChip = c
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TAG = "ModalBottomSheet"
|
||||
const val TAG = "FilterModalBottomSheet"
|
||||
}
|
||||
|
||||
|
||||
|
@ -28,7 +28,7 @@ class ImageFragment : Fragment() {
|
||||
val view = binding?.root
|
||||
|
||||
binding!!.photoView.visibility = View.VISIBLE
|
||||
Glide.with(activity)
|
||||
Glide.with(requireActivity())
|
||||
.asBitmap()
|
||||
.apply(glideOptions)
|
||||
.load(imageUrl)
|
||||
|
@ -19,13 +19,9 @@ import bou.amine.apps.readerforselfossv2.android.databinding.ActivitySettingsBin
|
||||
import bou.amine.apps.readerforselfossv2.android.sendSilentlyWithAcraWithName
|
||||
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
||||
import com.mikepenz.aboutlibraries.LibsBuilder
|
||||
import org.acra.ktx.sendSilentlyWithAcra
|
||||
import org.acra.ktx.sendWithAcra
|
||||
import org.kodein.di.DIAware
|
||||
import org.kodein.di.android.closestDI
|
||||
import org.kodein.di.instance
|
||||
import org.matomo.sdk.Tracker
|
||||
import org.matomo.sdk.extra.TrackHelper
|
||||
|
||||
private const val TITLE_TAG = "settingsActivityTitle"
|
||||
|
||||
@ -33,14 +29,10 @@ class SettingsActivity : AppCompatActivity(),
|
||||
PreferenceFragmentCompat.OnPreferenceStartFragmentCallback, DIAware {
|
||||
override val di by closestDI()
|
||||
|
||||
private val tracker : Tracker by instance()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
val binding = ActivitySettingsBinding.inflate(layoutInflater)
|
||||
|
||||
TrackHelper.track().screen("/settings").with(tracker)
|
||||
|
||||
setContentView(binding.root)
|
||||
if (savedInstanceState == null) {
|
||||
supportFragmentManager
|
||||
|
@ -18,7 +18,6 @@ import bou.amine.apps.readerforselfossv2.utils.toStringUriWithHttp
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||
|
||||
fun Context.openItemUrl(
|
||||
allItems: ArrayList<SelfossModel.Item>,
|
||||
currentItem: Int,
|
||||
linkDecoded: String,
|
||||
articleViewer: Boolean,
|
||||
@ -33,7 +32,6 @@ fun Context.openItemUrl(
|
||||
).show()
|
||||
} else {
|
||||
if (articleViewer) {
|
||||
ReaderActivity.allItems = allItems
|
||||
val intent = Intent(this, ReaderActivity::class.java)
|
||||
intent.putExtra("currentItem", currentItem)
|
||||
app.startActivity(intent)
|
||||
|
@ -1,7 +0,0 @@
|
||||
<vector android:height="24dp" android:tint="#000000"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M21,8c-1.45,0 -2.26,1.44 -1.93,2.51l-3.55,3.56c-0.3,-0.09 -0.74,-0.09 -1.04,0l-2.55,-2.55C12.27,10.45 11.46,9 10,9c-1.45,0 -2.27,1.44 -1.93,2.52l-4.56,4.55C2.44,15.74 1,16.55 1,18c0,1.1 0.9,2 2,2c1.45,0 2.26,-1.44 1.93,-2.51l4.55,-4.56c0.3,0.09 0.74,0.09 1.04,0l2.55,2.55C12.73,16.55 13.54,18 15,18c1.45,0 2.27,-1.44 1.93,-2.52l3.56,-3.55C21.56,12.26 23,11.45 23,10C23,8.9 22.1,8 21,8z"/>
|
||||
<path android:fillColor="@android:color/white" android:pathData="M15,9l0.94,-2.07l2.06,-0.93l-2.06,-0.93l-0.94,-2.07l-0.92,2.07l-2.08,0.93l2.08,0.93z"/>
|
||||
<path android:fillColor="@android:color/white" android:pathData="M3.5,11l0.5,-2l2,-0.5l-2,-0.5l-0.5,-2l-0.5,2l-2,0.5l2,0.5z"/>
|
||||
</vector>
|
@ -120,10 +120,10 @@
|
||||
<string name="mode_dark">Dark mode</string>
|
||||
<string name="mode_system">Follow the system setting</string>
|
||||
<string name="mode_light">Light mode</string>
|
||||
<string name="pref_switch_enable_analytics">Enable analytics</string>
|
||||
<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>
|
||||
</resources>
|
||||
|
@ -120,10 +120,10 @@
|
||||
<string name="mode_dark">Dark mode</string>
|
||||
<string name="mode_system">Follow the system setting</string>
|
||||
<string name="mode_light">Light mode</string>
|
||||
<string name="pref_switch_enable_analytics">Enable analytics</string>
|
||||
<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>
|
||||
</resources>
|
||||
|
@ -120,10 +120,10 @@
|
||||
<string name="mode_dark">Dark mode</string>
|
||||
<string name="mode_system">Follow the system setting</string>
|
||||
<string name="mode_light">Light mode</string>
|
||||
<string name="pref_switch_enable_analytics">Enable analytics</string>
|
||||
<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>
|
||||
</resources>
|
||||
|
@ -120,10 +120,10 @@
|
||||
<string name="mode_dark">Dark mode</string>
|
||||
<string name="mode_system">Follow the system setting</string>
|
||||
<string name="mode_light">Light mode</string>
|
||||
<string name="pref_switch_enable_analytics">Enable analytics</string>
|
||||
<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>
|
||||
</resources>
|
||||
|
@ -120,10 +120,10 @@
|
||||
<string name="mode_dark">Thème sombre</string>
|
||||
<string name="mode_system">Utiliser les paramètres système</string>
|
||||
<string name="mode_light">Thème clair</string>
|
||||
<string name="pref_switch_enable_analytics">Enable analytics</string>
|
||||
<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>
|
||||
</resources>
|
||||
|
@ -120,10 +120,10 @@
|
||||
<string name="mode_dark">Dark mode</string>
|
||||
<string name="mode_system">Follow the system setting</string>
|
||||
<string name="mode_light">Light mode</string>
|
||||
<string name="pref_switch_enable_analytics">Enable analytics</string>
|
||||
<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>
|
||||
</resources>
|
||||
|
@ -120,10 +120,10 @@
|
||||
<string name="mode_dark">Dark mode</string>
|
||||
<string name="mode_system">Follow the system setting</string>
|
||||
<string name="mode_light">Light mode</string>
|
||||
<string name="pref_switch_enable_analytics">Enable analytics</string>
|
||||
<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>
|
||||
</resources>
|
||||
|
@ -120,10 +120,10 @@
|
||||
<string name="mode_dark">Dark mode</string>
|
||||
<string name="mode_system">Follow the system setting</string>
|
||||
<string name="mode_light">Light mode</string>
|
||||
<string name="pref_switch_enable_analytics">Enable analytics</string>
|
||||
<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>
|
||||
</resources>
|
||||
|
@ -120,10 +120,10 @@
|
||||
<string name="mode_dark">Dark mode</string>
|
||||
<string name="mode_system">Follow the system setting</string>
|
||||
<string name="mode_light">Light mode</string>
|
||||
<string name="pref_switch_enable_analytics">Enable analytics</string>
|
||||
<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>
|
||||
</resources>
|
||||
|
@ -1,9 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="pref_switch_enable_analytics">Enable analytics</string>
|
||||
<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>
|
||||
</resources>
|
@ -120,10 +120,10 @@
|
||||
<string name="mode_dark">Dark mode</string>
|
||||
<string name="mode_system">Follow the system setting</string>
|
||||
<string name="mode_light">Light mode</string>
|
||||
<string name="pref_switch_enable_analytics">Enable analytics</string>
|
||||
<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>
|
||||
</resources>
|
||||
|
@ -120,10 +120,10 @@
|
||||
<string name="mode_dark">Dark mode</string>
|
||||
<string name="mode_system">Follow the system setting</string>
|
||||
<string name="mode_light">Light mode</string>
|
||||
<string name="pref_switch_enable_analytics">Enable analytics</string>
|
||||
<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>
|
||||
</resources>
|
||||
|
@ -120,10 +120,10 @@
|
||||
<string name="mode_dark">Dark mode</string>
|
||||
<string name="mode_system">Follow the system setting</string>
|
||||
<string name="mode_light">Light mode</string>
|
||||
<string name="pref_switch_enable_analytics">Enable analytics</string>
|
||||
<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>
|
||||
</resources>
|
||||
|
@ -120,10 +120,10 @@
|
||||
<string name="mode_dark">Dark mode</string>
|
||||
<string name="mode_system">Follow the system setting</string>
|
||||
<string name="mode_light">Light mode</string>
|
||||
<string name="pref_switch_enable_analytics">Enable analytics</string>
|
||||
<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>
|
||||
</resources>
|
||||
|
@ -120,10 +120,10 @@
|
||||
<string name="mode_dark">Dark mode</string>
|
||||
<string name="mode_system">Follow the system setting</string>
|
||||
<string name="mode_light">Light mode</string>
|
||||
<string name="pref_switch_enable_analytics">Enable analytics</string>
|
||||
<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>
|
||||
</resources>
|
||||
|
@ -120,10 +120,10 @@
|
||||
<string name="mode_dark">深色模式</string>
|
||||
<string name="mode_system">遵循系统设置</string>
|
||||
<string name="mode_light">浅色模式</string>
|
||||
<string name="pref_switch_enable_analytics">启用分析</string>
|
||||
<string name="gdpr_dialog_title">该应用不分享任何关于您的个人数据。</string>
|
||||
<string name="gdpr_dialog_message"><![CDATA[崩溃报告发送现已启用。 可以从设置页面禁用它。 请记住,崩溃报告对于应用程序开发是必需的。]]></string>
|
||||
<string name="crash_toast_text">发生崩溃。请将细节发送给开发人员。</string>
|
||||
<string name="pref_switch_disable_acra">"禁用自动错误报告 "</string>
|
||||
<string name="menu_home_filter">筛选器</string>
|
||||
<string name="application_selfoss_only">This app only works with a Selfoss instance, and no other RSS feed.</string>
|
||||
</resources>
|
||||
|
@ -120,10 +120,10 @@
|
||||
<string name="mode_dark">Dark mode</string>
|
||||
<string name="mode_system">Follow the system setting</string>
|
||||
<string name="mode_light">Light mode</string>
|
||||
<string name="pref_switch_enable_analytics">Enable analytics</string>
|
||||
<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>
|
||||
</resources>
|
||||
|
@ -123,10 +123,10 @@
|
||||
<string name="mode_dark">Dark mode</string>
|
||||
<string name="mode_system">Follow the system setting</string>
|
||||
<string name="mode_light">Light mode</string>
|
||||
<string name="pref_switch_enable_analytics">Enable analytics</string>
|
||||
<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>
|
||||
</resources>
|
||||
|
@ -38,13 +38,6 @@
|
||||
android:icon="@drawable/ic_widgets_black_24dp" />
|
||||
|
||||
|
||||
<SwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:key="enable_analytics"
|
||||
android:title="@string/pref_switch_enable_analytics"
|
||||
android:icon="@drawable/ic_baseline_insights_24"/>
|
||||
|
||||
|
||||
<SwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:key="acra.disable"
|
||||
|
@ -11,11 +11,14 @@ 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"
|
||||
|
||||
@Test
|
||||
fun v3_date_should_be_parsed() {
|
||||
val date = DateUtils.parseDate(v3Date)
|
||||
val expected = LocalDateTime(2013, 4, 7, 13, 43, 0, 0).toInstant(TimeZone.of("UTC+1")) .toEpochMilliseconds()
|
||||
val expected =
|
||||
LocalDateTime(2013, 4, 7, 14, 43, 0, 0).toInstant(TimeZone.currentSystemDefault())
|
||||
.toEpochMilliseconds()
|
||||
|
||||
assertEquals(date, expected)
|
||||
}
|
||||
@ -30,4 +33,14 @@ class DatesTest {
|
||||
assertEquals(date, expected)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun bug1_date_should_be_parsed() {
|
||||
val date = DateUtils.parseDate(bug1Date)
|
||||
val expected =
|
||||
LocalDateTime(2022, 12, 24, 18, 0, 8, 0).toInstant(TimeZone.currentSystemDefault())
|
||||
.toEpochMilliseconds()
|
||||
|
||||
assertEquals(date, expected)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -17,10 +17,12 @@ plugins {
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
jcenter()
|
||||
maven { url = uri("https://www.jitpack.io") }
|
||||
maven { url = uri("https://nexus.amine-louveau.fr/repository/maven-public/")}
|
||||
// IMPORTANT : Add back when new library added
|
||||
// google()
|
||||
// mavenCentral()
|
||||
// jcenter()
|
||||
// maven { url = uri("https://www.jitpack.io") }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,16 +2,20 @@ val pushCache: String by settings
|
||||
|
||||
pluginManagement {
|
||||
repositories {
|
||||
google()
|
||||
gradlePluginPortal()
|
||||
mavenCentral()
|
||||
maven { url = uri("https://nexus.amine-louveau.fr/repository/maven-public/")}
|
||||
// IMPORTANT : Add back when new plugin added
|
||||
// google()
|
||||
// gradlePluginPortal()
|
||||
// mavenCentral()
|
||||
}
|
||||
}
|
||||
|
||||
dependencyResolutionManagement {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
maven { url = uri("https://nexus.amine-louveau.fr/repository/maven-public/")}
|
||||
// IMPORTANT : Add back when new library added
|
||||
// google()
|
||||
// mavenCentral()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,11 @@ actual class DateUtils {
|
||||
return try {
|
||||
Instant.parse(dateString).toEpochMilliseconds()
|
||||
} catch (e: Exception) {
|
||||
LocalDateTime.parse(dateString.replace(" ", "T")).toInstant(TimeZone.currentSystemDefault()).toEpochMilliseconds()
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,5 @@
|
||||
package bou.amine.apps.readerforselfossv2.model
|
||||
|
||||
import io.ktor.client.call.*
|
||||
import io.ktor.client.statement.*
|
||||
import io.ktor.http.*
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
@ -21,28 +18,4 @@ class StatusAndData<T>(val success: Boolean, val data: T? = null) {
|
||||
return StatusAndData(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun responseOrSuccessIf404(r: HttpResponse): SuccessResponse {
|
||||
return if (r.status === HttpStatusCode.NotFound) {
|
||||
SuccessResponse(true)
|
||||
} else {
|
||||
maybeResponse(r)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun maybeResponse(r: HttpResponse): SuccessResponse {
|
||||
return if (r.status.isSuccess()) {
|
||||
r.body()
|
||||
} else {
|
||||
SuccessResponse(false)
|
||||
}
|
||||
}
|
||||
|
||||
suspend inline fun <reified T> bodyOrFailure(r: HttpResponse): StatusAndData<T> {
|
||||
return if (r.status.isSuccess()) {
|
||||
StatusAndData.succes(r.body())
|
||||
} else {
|
||||
StatusAndData.error()
|
||||
}
|
||||
}
|
@ -8,13 +8,19 @@ import bou.amine.apps.readerforselfossv2.rest.SelfossApi
|
||||
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
||||
import bou.amine.apps.readerforselfossv2.utils.*
|
||||
import io.github.aakira.napier.Napier
|
||||
import io.ktor.client.call.*
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class Repository(private val api: SelfossApi, private val appSettingsService: AppSettingsService, val isConnectionAvailable: MutableStateFlow<Boolean>, private val db: ReaderForSelfossDB) {
|
||||
class Repository(
|
||||
private val api: SelfossApi,
|
||||
private val appSettingsService: AppSettingsService,
|
||||
val isConnectionAvailable: MutableStateFlow<Boolean>,
|
||||
private val db: ReaderForSelfossDB
|
||||
) {
|
||||
|
||||
var items = ArrayList<SelfossModel.Item>()
|
||||
var connectionMonitored = false
|
||||
@ -41,6 +47,8 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
|
||||
private var fetchedSources = false
|
||||
private var fetchedTags = false
|
||||
|
||||
private var _readerItems = ArrayList<SelfossModel.Item>()
|
||||
|
||||
suspend fun getNewerItems(): ArrayList<SelfossModel.Item> {
|
||||
// TODO: Use the updatedSince parameter
|
||||
var fetchedItems: StatusAndData<List<SelfossModel.Item>> = StatusAndData.error()
|
||||
@ -146,7 +154,8 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
|
||||
}
|
||||
|
||||
suspend fun getTags(): List<SelfossModel.Tag> {
|
||||
val isDatabaseEnabled = appSettingsService.isItemCachingEnabled() || !appSettingsService.isUpdateSourcesEnabled()
|
||||
val isDatabaseEnabled =
|
||||
appSettingsService.isItemCachingEnabled() || !appSettingsService.isUpdateSourcesEnabled()
|
||||
return if (isNetworkAvailable() && !fetchedTags) {
|
||||
val apiTags = api.tags()
|
||||
if (apiTags.success && apiTags.data != null && isDatabaseEnabled) {
|
||||
@ -178,7 +187,8 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
|
||||
}
|
||||
|
||||
suspend fun getSources(): ArrayList<SelfossModel.Source> {
|
||||
val isDatabaseEnabled = appSettingsService.isItemCachingEnabled() || !appSettingsService.isUpdateSourcesEnabled()
|
||||
val isDatabaseEnabled =
|
||||
appSettingsService.isItemCachingEnabled() || !appSettingsService.isUpdateSourcesEnabled()
|
||||
return if (isNetworkAvailable() && !fetchedSources) {
|
||||
val apiSources = api.sources()
|
||||
if (apiSources.success && apiSources.data != null && isDatabaseEnabled) {
|
||||
@ -380,18 +390,35 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
|
||||
return result
|
||||
}
|
||||
|
||||
suspend fun shouldBeSelfossInstance(): Pair<Boolean, Boolean> {
|
||||
var fetchFailed = true
|
||||
var showSelfossOnlyModal = false
|
||||
if (isNetworkAvailable()) {
|
||||
try {
|
||||
// Trying to fetch one item, and check someone is trying to use the app with
|
||||
// a random rss feed, that would throw a NoTransformationFoundException
|
||||
fetchFailed = !api.getItemsWithoutCatch().success
|
||||
} catch (e: NoTransformationFoundException) {
|
||||
showSelfossOnlyModal = true
|
||||
} catch (e: Throwable) {
|
||||
Napier.e(e.stackTraceToString(), tag = "RepositoryImpl.shouldBeSelfossInstance")
|
||||
}
|
||||
}
|
||||
|
||||
return Pair(fetchFailed, showSelfossOnlyModal)
|
||||
}
|
||||
|
||||
suspend fun logout() {
|
||||
if (isNetworkAvailable()) {
|
||||
try {
|
||||
val response = api.logout()
|
||||
if (response.isSuccess) {
|
||||
if (!response.isSuccess) {
|
||||
Napier.e("Couldn't logout.", tag = "RepositoryImpl.logout")
|
||||
}
|
||||
} catch (cause: Throwable) {
|
||||
Napier.e(cause.stackTraceToString(), tag = "RepositoryImpl.logout")
|
||||
} finally {
|
||||
appSettingsService.clearAll()
|
||||
}
|
||||
appSettingsService.clearAll()
|
||||
} else {
|
||||
appSettingsService.clearAll()
|
||||
}
|
||||
@ -456,11 +483,29 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
|
||||
|
||||
private fun getDBItems(): List<ITEM> = db.itemsQueries.items().executeAsList()
|
||||
|
||||
private fun insertDBAction(articleid: String, read: Boolean = false, unread: Boolean = false, starred: Boolean = false, unstarred: Boolean = false) =
|
||||
private fun insertDBAction(
|
||||
articleid: String,
|
||||
read: Boolean = false,
|
||||
unread: Boolean = false,
|
||||
starred: Boolean = false,
|
||||
unstarred: Boolean = false
|
||||
) =
|
||||
db.actionsQueries.insertAction(articleid, read, unread, starred, unstarred)
|
||||
|
||||
private fun updateDBItem(item: SelfossModel.Item) =
|
||||
db.itemsQueries.updateItem(item.datetime, item.title.getHtmlDecoded(), item.content, item.unread, item.starred, item.thumbnail, item.icon, item.link, item.sourcetitle, item.tags.joinToString(","), item.id.toString())
|
||||
db.itemsQueries.updateItem(
|
||||
item.datetime,
|
||||
item.title.getHtmlDecoded(),
|
||||
item.content,
|
||||
item.unread,
|
||||
item.starred,
|
||||
item.thumbnail,
|
||||
item.icon,
|
||||
item.link,
|
||||
item.sourcetitle,
|
||||
item.tags.joinToString(","),
|
||||
item.id.toString()
|
||||
)
|
||||
|
||||
suspend fun tryToCacheItemsAndGetNewOnes(): List<SelfossModel.Item> {
|
||||
try {
|
||||
@ -515,4 +560,12 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
|
||||
fun setSourceFilter(source: SelfossModel.Source?) {
|
||||
_sourceFilter.value = source
|
||||
}
|
||||
|
||||
fun setReaderItems(readerItems: ArrayList<SelfossModel.Item>) {
|
||||
_readerItems = readerItems
|
||||
}
|
||||
|
||||
fun getReaderItems(): ArrayList<SelfossModel.Item> {
|
||||
return _readerItems
|
||||
}
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
package bou.amine.apps.readerforselfossv2.rest
|
||||
|
||||
import bou.amine.apps.readerforselfossv2.model.StatusAndData
|
||||
import bou.amine.apps.readerforselfossv2.model.SuccessResponse
|
||||
import io.github.aakira.napier.Napier
|
||||
import io.ktor.client.*
|
||||
import io.ktor.client.call.*
|
||||
import io.ktor.client.request.*
|
||||
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)
|
||||
} else {
|
||||
maybeResponse(r)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun maybeResponse(r: HttpResponse?): SuccessResponse {
|
||||
return if (r != null && r.status.isSuccess()) {
|
||||
r.body()
|
||||
} else {
|
||||
SuccessResponse(false)
|
||||
}
|
||||
}
|
||||
|
||||
suspend inline fun <reified T> bodyOrFailure(r: HttpResponse?): StatusAndData<T> {
|
||||
return if (r != null && r.status.isSuccess()) {
|
||||
StatusAndData.succes(r.body())
|
||||
} else {
|
||||
StatusAndData.error()
|
||||
}
|
||||
}
|
||||
|
||||
inline fun tryToRequest(
|
||||
requestType: String,
|
||||
fn: () -> HttpResponse
|
||||
): HttpResponse? {
|
||||
var response: HttpResponse? = null
|
||||
try {
|
||||
response = fn()
|
||||
} catch (ex: Exception) {
|
||||
Napier.e("Couldn't execute $requestType request", ex, "tryTo$requestType")
|
||||
}
|
||||
return response
|
||||
}
|
||||
|
||||
suspend inline fun HttpClient.tryToGet(
|
||||
urlString: String,
|
||||
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() } }
|
||||
|
||||
suspend inline fun HttpClient.tryToDelete(
|
||||
urlString: String,
|
||||
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 = {}
|
||||
): HttpResponse? =
|
||||
tryToRequest("SubmitForm") {
|
||||
return this.submitForm(formParameters, encodeInQuery) {
|
||||
url(url)
|
||||
block()
|
||||
}
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
package bou.amine.apps.readerforselfossv2.rest
|
||||
|
||||
import bou.amine.apps.readerforselfossv2.model.*
|
||||
import bou.amine.apps.readerforselfossv2.model.SelfossModel
|
||||
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.*
|
||||
@ -10,7 +12,6 @@ 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.request.forms.*
|
||||
import io.ktor.client.statement.*
|
||||
import io.ktor.http.*
|
||||
import io.ktor.serialization.kotlinx.json.*
|
||||
@ -50,7 +51,7 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
|
||||
retryIf { _, response ->
|
||||
response.status == HttpStatusCode.Forbidden && shouldHavePostLogin() && hasLoginInfo()
|
||||
}
|
||||
modifyRequest { _ ->
|
||||
modifyRequest {
|
||||
Napier.i("Will modify", tag = "HttpSend")
|
||||
CoroutineScope(Dispatchers.Main).launch {
|
||||
Napier.i("Will login", tag = "HttpSend")
|
||||
@ -75,7 +76,7 @@ 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() != null && appSettingsService.getPassword() != null
|
||||
private fun hasLoginInfo() = appSettingsService.getUserName().isNotEmpty() && appSettingsService.getPassword().isNotEmpty()
|
||||
|
||||
suspend fun login(): SuccessResponse =
|
||||
if (appSettingsService.getUserName().isNotEmpty() && appSettingsService.getPassword().isNotEmpty()) {
|
||||
@ -88,12 +89,12 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
|
||||
SuccessResponse(true)
|
||||
}
|
||||
|
||||
private suspend fun getLogin() = maybeResponse(client.get(url("/login")) {
|
||||
private suspend fun getLogin() = maybeResponse(client.tryToGet(url("/login")) {
|
||||
parameter("username", appSettingsService.getUserName())
|
||||
parameter("password", appSettingsService.getPassword())
|
||||
})
|
||||
|
||||
private suspend fun postLogin() = maybeResponse(client.post(url("/login")) {
|
||||
private suspend fun postLogin() = maybeResponse(client.tryToPost(url("/login")) {
|
||||
parameter("username", appSettingsService.getUserName())
|
||||
parameter("password", appSettingsService.getPassword())
|
||||
})
|
||||
@ -106,9 +107,9 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
|
||||
maybeLogoutIfAvailable()
|
||||
}
|
||||
|
||||
private suspend fun maybeLogoutIfAvailable() = responseOrSuccessIf404(client.get(url("/logout")))
|
||||
private suspend fun maybeLogoutIfAvailable() = responseOrSuccessIf404(client.tryToGet(url("/logout")))
|
||||
|
||||
private suspend fun doLogout() = maybeResponse(client.delete(url("/api/session/current")))
|
||||
private suspend fun doLogout() = maybeResponse(client.tryToDelete(url("/api/session/current")))
|
||||
|
||||
suspend fun getItems(
|
||||
type: String,
|
||||
@ -119,7 +120,7 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
|
||||
updatedSince: String?,
|
||||
items: Int? = null
|
||||
): StatusAndData<List<SelfossModel.Item>> =
|
||||
bodyOrFailure(client.get(url("/items")) {
|
||||
bodyOrFailure(client.tryToGet(url("/items")) {
|
||||
if (!shouldHavePostLogin()) {
|
||||
parameter("username", appSettingsService.getUserName())
|
||||
parameter("password", appSettingsService.getPassword())
|
||||
@ -133,8 +134,18 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
|
||||
parameter("offset", offset)
|
||||
})
|
||||
|
||||
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)
|
||||
})
|
||||
|
||||
suspend fun stats(): StatusAndData<SelfossModel.Stats> =
|
||||
bodyOrFailure(client.get(url("/stats")) {
|
||||
bodyOrFailure(client.tryToGet(url("/stats")) {
|
||||
if (!shouldHavePostLogin()) {
|
||||
parameter("username", appSettingsService.getUserName())
|
||||
parameter("password", appSettingsService.getPassword())
|
||||
@ -142,7 +153,7 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
|
||||
})
|
||||
|
||||
suspend fun tags(): StatusAndData<List<SelfossModel.Tag>> =
|
||||
bodyOrFailure(client.get(url("/tags")) {
|
||||
bodyOrFailure(client.tryToGet(url("/tags")) {
|
||||
if (!shouldHavePostLogin()) {
|
||||
parameter("username", appSettingsService.getUserName())
|
||||
parameter("password", appSettingsService.getPassword())
|
||||
@ -150,7 +161,7 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
|
||||
})
|
||||
|
||||
suspend fun update(): StatusAndData<String> =
|
||||
bodyOrFailure(client.get(url("/update")) {
|
||||
bodyOrFailure(client.tryToGet(url("/update")) {
|
||||
if (!shouldHavePostLogin()) {
|
||||
parameter("username", appSettingsService.getUserName())
|
||||
parameter("password", appSettingsService.getPassword())
|
||||
@ -158,7 +169,7 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
|
||||
})
|
||||
|
||||
suspend fun spouts(): StatusAndData<Map<String, SelfossModel.Spout>> =
|
||||
bodyOrFailure(client.get(url("/sources/spouts")) {
|
||||
bodyOrFailure(client.tryToGet(url("/sources/spouts")) {
|
||||
if (!shouldHavePostLogin()) {
|
||||
parameter("username", appSettingsService.getUserName())
|
||||
parameter("password", appSettingsService.getPassword())
|
||||
@ -166,7 +177,7 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
|
||||
})
|
||||
|
||||
suspend fun sources(): StatusAndData<ArrayList<SelfossModel.Source>> =
|
||||
bodyOrFailure(client.get(url("/sources/list")) {
|
||||
bodyOrFailure(client.tryToGet(url("/sources/list")) {
|
||||
if (!shouldHavePostLogin()) {
|
||||
parameter("username", appSettingsService.getUserName())
|
||||
parameter("password", appSettingsService.getPassword())
|
||||
@ -174,10 +185,10 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
|
||||
})
|
||||
|
||||
suspend fun version(): StatusAndData<SelfossModel.ApiVersion> =
|
||||
bodyOrFailure(client.get(url("/api/about")))
|
||||
bodyOrFailure(client.tryToGet(url("/api/about")))
|
||||
|
||||
suspend fun markAsRead(id: String): SuccessResponse =
|
||||
maybeResponse(client.post(url("/mark/$id")) {
|
||||
maybeResponse(client.tryToPost(url("/mark/$id")) {
|
||||
if (!shouldHavePostLogin()) {
|
||||
parameter("username", appSettingsService.getUserName())
|
||||
parameter("password", appSettingsService.getPassword())
|
||||
@ -185,7 +196,7 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
|
||||
})
|
||||
|
||||
suspend fun unmarkAsRead(id: String): SuccessResponse =
|
||||
maybeResponse(client.post(url("/unmark/$id")) {
|
||||
maybeResponse(client.tryToPost(url("/unmark/$id")) {
|
||||
if (!shouldHavePostLogin()) {
|
||||
parameter("username", appSettingsService.getUserName())
|
||||
parameter("password", appSettingsService.getPassword())
|
||||
@ -193,7 +204,7 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
|
||||
})
|
||||
|
||||
suspend fun starr(id: String): SuccessResponse =
|
||||
maybeResponse(client.post(url("/starr/$id")) {
|
||||
maybeResponse(client.tryToPost(url("/starr/$id")) {
|
||||
if (!shouldHavePostLogin()) {
|
||||
parameter("username", appSettingsService.getUserName())
|
||||
parameter("password", appSettingsService.getPassword())
|
||||
@ -201,7 +212,7 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
|
||||
})
|
||||
|
||||
suspend fun unstarr(id: String): SuccessResponse =
|
||||
maybeResponse(client.post(url("/unstarr/$id")) {
|
||||
maybeResponse(client.tryToPost(url("/unstarr/$id")) {
|
||||
if (!shouldHavePostLogin()) {
|
||||
parameter("username", appSettingsService.getUserName())
|
||||
parameter("password", appSettingsService.getPassword())
|
||||
@ -209,7 +220,7 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
|
||||
})
|
||||
|
||||
suspend fun markAllAsRead(ids: List<String>): SuccessResponse =
|
||||
maybeResponse(client.submitForm(
|
||||
maybeResponse(client.tryToSubmitForm(
|
||||
url = url("/mark"),
|
||||
formParameters = Parameters.build {
|
||||
if (!shouldHavePostLogin()) {
|
||||
@ -242,8 +253,8 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
|
||||
spout: String,
|
||||
tags: String,
|
||||
filter: String
|
||||
): HttpResponse =
|
||||
client.submitForm(
|
||||
): HttpResponse? =
|
||||
client.tryToSubmitForm(
|
||||
url = url("/source"),
|
||||
formParameters = Parameters.build {
|
||||
if (!shouldHavePostLogin()) {
|
||||
@ -259,7 +270,7 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
|
||||
)
|
||||
|
||||
suspend fun deleteSource(id: Int): SuccessResponse =
|
||||
maybeResponse(client.delete(url("/source/$id")) {
|
||||
maybeResponse(client.tryToDelete(url("/source/$id")) {
|
||||
if (!shouldHavePostLogin()) {
|
||||
parameter("username", appSettingsService.getUserName())
|
||||
parameter("password", appSettingsService.getPassword())
|
||||
|
@ -35,7 +35,6 @@ class AppSettingsService {
|
||||
private var _staticBar: Boolean? = null
|
||||
private var _font: String = ""
|
||||
private var _theme: Int? = null
|
||||
private var _enableAnalytics: Boolean? = null
|
||||
|
||||
|
||||
init {
|
||||
@ -309,17 +308,6 @@ class AppSettingsService {
|
||||
return _staticBar == true
|
||||
}
|
||||
|
||||
private fun refreshAnalyticsEnabled() {
|
||||
_enableAnalytics = settings.getBoolean(ENABLE_ANALYTICS, true)
|
||||
}
|
||||
|
||||
fun isAnalyticsEnabled(): Boolean {
|
||||
if (_enableAnalytics != null) {
|
||||
refreshAnalyticsEnabled()
|
||||
}
|
||||
return _enableAnalytics == true
|
||||
}
|
||||
|
||||
private fun refreshFont() {
|
||||
_font = settings.getString(READER_FONT, "")
|
||||
}
|
||||
@ -370,7 +358,6 @@ class AppSettingsService {
|
||||
refreshFont()
|
||||
refreshStaticBarEnabled()
|
||||
refreshCurrentTheme()
|
||||
refreshAnalyticsEnabled()
|
||||
}
|
||||
|
||||
fun refreshLoginInformation(
|
||||
@ -471,6 +458,5 @@ class AppSettingsService {
|
||||
|
||||
const val CURRENT_THEME = "currentMode"
|
||||
|
||||
const val ENABLE_ANALYTICS = "enable_analytics"
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user