Compare commits
	
		
			14 Commits
		
	
	
		
			v171811325
			...
			v171811332
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					0b07f2a407 | ||
| 
						 | 
					9ba6feef0b | ||
| 
						 | 
					63a0638522 | ||
| 
						 | 
					f9a4e6e363 | ||
| 
						 | 
					6b40fd4bdc | ||
| 
						 | 
					04c7776466 | ||
| 
						 | 
					92c335b4e1 | ||
| 
						 | 
					17251e576b | ||
| 
						 | 
					62ea782429 | ||
| 
						 | 
					f99474e3c1 | ||
| 
						 | 
					57ac8f428f | ||
| 
						 | 
					9cc1adbf15 | ||
| 
						 | 
					1d9a440ae7 | ||
| 
						 | 
					511553806c | 
							
								
								
									
										6
									
								
								.github/CONTRIBUTING.md
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								.github/CONTRIBUTING.md
									
									
									
									
										vendored
									
									
								
							@@ -41,6 +41,12 @@ Always check if the web version of your instance is working.
 | 
			
		||||
* Remember that PR review can take time.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Install Selfoss (if you don't have an instance)
 | 
			
		||||
 | 
			
		||||
I won't provide any selfoss instance url. If you want to help, but to not have one, you'll have to install one, and use it.
 | 
			
		||||
 | 
			
		||||
All the details to need are [here](https://selfoss.aditu.de/).
 | 
			
		||||
 | 
			
		||||
# Build the project
 | 
			
		||||
 | 
			
		||||
You can directly import this project into IntellIJ/Android Studio.
 | 
			
		||||
 
 | 
			
		||||
@@ -18,7 +18,11 @@ Also, the last APK built from source is available [here](https://jenkins.amine-b
 | 
			
		||||
 | 
			
		||||
## Want to help ?
 | 
			
		||||
 | 
			
		||||
Check the [Contribution guide](https://github.com/aminecmi/ReaderforSelfoss/blob/master/.github/CONTRIBUTING.md)
 | 
			
		||||
1. **You'll have to have a Selfoss instance running.** You'll find everything you need to install it [here](https://selfoss.aditu.de/).
 | 
			
		||||
 | 
			
		||||
2. Check the [Contribution guide](https://github.com/aminecmi/ReaderforSelfoss/blob/master/.github/CONTRIBUTING.md).
 | 
			
		||||
 | 
			
		||||
3. Build the project by following [these steps](https://github.com/aminecmi/ReaderforSelfoss/blob/master/.github/CONTRIBUTING.md#build-the-project) (you should have read them after the contribution guide)
 | 
			
		||||
 | 
			
		||||
## Useful links
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@ buildscript {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
def gitVersion() {
 | 
			
		||||
    def process = "git for-each-ref refs/tags --sort=-taggerdate --format='%(refname:short)' --count=1".execute()
 | 
			
		||||
    def process = "git for-each-ref refs/tags --sort=-authordate --format='%(refname:short)' --count=1".execute()
 | 
			
		||||
    return process.text.replaceAll("'", "").substring(1).replaceAll("\\.", "").trim()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -170,4 +170,4 @@ def initAppLoginPropertiesIfNeeded() {
 | 
			
		||||
            entry(key: "appLoginPassword", value: System.getProperty("appLoginPassword"))
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -109,7 +109,7 @@ class AddSourceActivity : AppCompatActivity() {
 | 
			
		||||
        super.onResume()
 | 
			
		||||
        val config = Config(this)
 | 
			
		||||
 | 
			
		||||
        if (config.baseUrl.isEmpty() || !config.baseUrl.isBaseUrlValid(false)) {
 | 
			
		||||
        if (config.baseUrl.isEmpty() || !config.baseUrl.isBaseUrlValid(false, this@AddSourceActivity)) {
 | 
			
		||||
            mustLoginToAddSource()
 | 
			
		||||
        } else {
 | 
			
		||||
            handleSpoutsSpinner(spoutsSpinner, api, progress, formContainer)
 | 
			
		||||
 
 | 
			
		||||
@@ -54,7 +54,6 @@ class LoginActivity : AppCompatActivity() {
 | 
			
		||||
 | 
			
		||||
        handleBaseUrlFail()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        settings = getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE)
 | 
			
		||||
        userIdentifier = settings.getString("unique_id", "")
 | 
			
		||||
        logErrors = settings.getBoolean("login_debug", false)
 | 
			
		||||
@@ -145,7 +144,7 @@ class LoginActivity : AppCompatActivity() {
 | 
			
		||||
        var cancel = false
 | 
			
		||||
        var focusView: View? = null
 | 
			
		||||
 | 
			
		||||
        if (!url.isBaseUrlValid(logErrors)) {
 | 
			
		||||
        if (!url.isBaseUrlValid(logErrors, this@LoginActivity)) {
 | 
			
		||||
            urlView.error = getString(R.string.login_url_problem)
 | 
			
		||||
            focusView = urlView
 | 
			
		||||
            cancel = true
 | 
			
		||||
@@ -164,7 +163,7 @@ class LoginActivity : AppCompatActivity() {
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (isWithLogin || isWithHTTPLogin) {
 | 
			
		||||
        if (isWithLogin) {
 | 
			
		||||
            if (TextUtils.isEmpty(password)) {
 | 
			
		||||
                passwordView.error = getString(R.string.error_invalid_password)
 | 
			
		||||
                focusView = passwordView
 | 
			
		||||
@@ -178,6 +177,20 @@ class LoginActivity : AppCompatActivity() {
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (isWithHTTPLogin) {
 | 
			
		||||
            if (TextUtils.isEmpty(httpPassword)) {
 | 
			
		||||
                httpPasswordView.error = getString(R.string.error_invalid_password)
 | 
			
		||||
                focusView = httpPasswordView
 | 
			
		||||
                cancel = true
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (TextUtils.isEmpty(httpLogin)) {
 | 
			
		||||
                httpLoginView.error = getString(R.string.error_field_required)
 | 
			
		||||
                focusView = httpLoginView
 | 
			
		||||
                cancel = true
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (cancel) {
 | 
			
		||||
            focusView?.requestFocus()
 | 
			
		||||
        } else {
 | 
			
		||||
 
 | 
			
		||||
@@ -28,10 +28,8 @@ import java.io.IOException
 | 
			
		||||
import java.util.UUID.randomUUID
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@AcraHttpSender(uri = "http://amine-bou.fr:5984/acra-selfoss/_design/acra-storage/_update/report",
 | 
			
		||||
                basicAuthLogin = "selfoss",
 | 
			
		||||
                basicAuthPassword = "selfoss",
 | 
			
		||||
                httpMethod = HttpSender.Method.PUT)
 | 
			
		||||
@AcraHttpSender(uri = "http://37.187.110.167/amine/acra/simplest-acra.php",
 | 
			
		||||
                httpMethod = HttpSender.Method.POST)
 | 
			
		||||
@AcraDialog(resText = R.string.crash_dialog_text,
 | 
			
		||||
            resCommentPrompt = R.string.crash_dialog_comment,
 | 
			
		||||
            resTheme = android.R.style.Theme_DeviceDefault_Dialog)
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,7 @@ import android.graphics.drawable.ColorDrawable
 | 
			
		||||
import android.os.Build
 | 
			
		||||
import android.os.Bundle
 | 
			
		||||
import android.preference.PreferenceManager
 | 
			
		||||
import android.view.InflateException
 | 
			
		||||
import androidx.browser.customtabs.CustomTabsIntent
 | 
			
		||||
import com.google.android.material.floatingactionbutton.FloatingActionButton
 | 
			
		||||
import androidx.fragment.app.Fragment
 | 
			
		||||
@@ -17,6 +18,7 @@ import android.view.MenuItem
 | 
			
		||||
import android.view.View
 | 
			
		||||
import android.view.ViewGroup
 | 
			
		||||
import android.webkit.WebSettings
 | 
			
		||||
import androidx.appcompat.app.AlertDialog
 | 
			
		||||
import androidx.room.Room
 | 
			
		||||
import apps.amine.bou.readerforselfoss.R
 | 
			
		||||
import apps.amine.bou.readerforselfoss.api.mercury.MercuryApi
 | 
			
		||||
@@ -39,7 +41,6 @@ import apps.amine.bou.readerforselfoss.utils.openItemUrl
 | 
			
		||||
import apps.amine.bou.readerforselfoss.utils.shareLink
 | 
			
		||||
import apps.amine.bou.readerforselfoss.utils.sourceAndDateText
 | 
			
		||||
import apps.amine.bou.readerforselfoss.utils.succeeded
 | 
			
		||||
import apps.amine.bou.readerforselfoss.utils.toPx
 | 
			
		||||
import com.bumptech.glide.Glide
 | 
			
		||||
import com.bumptech.glide.request.RequestOptions
 | 
			
		||||
import com.github.rubensousa.floatingtoolbar.FloatingToolbar
 | 
			
		||||
@@ -54,9 +55,9 @@ import kotlin.concurrent.thread
 | 
			
		||||
 | 
			
		||||
class ArticleFragment : Fragment() {
 | 
			
		||||
    private lateinit var pageNumber: Number
 | 
			
		||||
    private var fontSize: Int = 14
 | 
			
		||||
    private var fontSize: Int = 16
 | 
			
		||||
    private lateinit var allItems: ArrayList<Item>
 | 
			
		||||
    private lateinit var mCustomTabActivityHelper: CustomTabActivityHelper
 | 
			
		||||
    private var mCustomTabActivityHelper: CustomTabActivityHelper? = null;
 | 
			
		||||
    private lateinit var url: String
 | 
			
		||||
    private lateinit var contentText: String
 | 
			
		||||
    private lateinit var contentSource: String
 | 
			
		||||
@@ -69,7 +70,9 @@ class ArticleFragment : Fragment() {
 | 
			
		||||
 | 
			
		||||
    override fun onStop() {
 | 
			
		||||
        super.onStop()
 | 
			
		||||
        mCustomTabActivityHelper.unbindCustomTabsService(activity)
 | 
			
		||||
        if (mCustomTabActivityHelper != null) {
 | 
			
		||||
            mCustomTabActivityHelper!!.unbindCustomTabsService(activity)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun onCreate(savedInstanceState: Bundle?) {
 | 
			
		||||
@@ -86,7 +89,7 @@ class ArticleFragment : Fragment() {
 | 
			
		||||
        ).addMigrations(MIGRATION_1_2).addMigrations(MIGRATION_2_3).build()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private lateinit var rootView: ViewGroup
 | 
			
		||||
    private var rootView: ViewGroup? = null
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    override fun onCreateView(
 | 
			
		||||
@@ -94,136 +97,153 @@ class ArticleFragment : Fragment() {
 | 
			
		||||
        container: ViewGroup?,
 | 
			
		||||
        savedInstanceState: Bundle?
 | 
			
		||||
    ): View? {
 | 
			
		||||
        rootView = inflater
 | 
			
		||||
            .inflate(R.layout.fragment_article, container, false) as ViewGroup
 | 
			
		||||
        try {
 | 
			
		||||
            rootView = inflater
 | 
			
		||||
                .inflate(R.layout.fragment_article, container, false) as ViewGroup
 | 
			
		||||
 | 
			
		||||
        url = allItems[pageNumber.toInt()].getLinkDecoded()
 | 
			
		||||
        contentText = allItems[pageNumber.toInt()].content
 | 
			
		||||
        contentTitle = allItems[pageNumber.toInt()].title
 | 
			
		||||
        contentImage = allItems[pageNumber.toInt()].getThumbnail(activity!!)
 | 
			
		||||
        contentSource = allItems[pageNumber.toInt()].sourceAndDateText()
 | 
			
		||||
            url = allItems[pageNumber.toInt()].getLinkDecoded()
 | 
			
		||||
            contentText = allItems[pageNumber.toInt()].content
 | 
			
		||||
            contentTitle = allItems[pageNumber.toInt()].title
 | 
			
		||||
            contentImage = allItems[pageNumber.toInt()].getThumbnail(activity!!)
 | 
			
		||||
            contentSource = allItems[pageNumber.toInt()].sourceAndDateText()
 | 
			
		||||
 | 
			
		||||
        val prefs = PreferenceManager.getDefaultSharedPreferences(activity)
 | 
			
		||||
        editor = prefs.edit()
 | 
			
		||||
        fontSize = prefs.getString("reader_font_size", "14").toInt()
 | 
			
		||||
            val prefs = PreferenceManager.getDefaultSharedPreferences(activity)
 | 
			
		||||
            editor = prefs.edit()
 | 
			
		||||
            fontSize = prefs.getString("reader_font_size", "16").toInt()
 | 
			
		||||
 | 
			
		||||
        val settings = activity!!.getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE)
 | 
			
		||||
        val debugReadingItems = prefs.getBoolean("read_debug", false)
 | 
			
		||||
            val settings = activity!!.getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE)
 | 
			
		||||
            val debugReadingItems = prefs.getBoolean("read_debug", false)
 | 
			
		||||
 | 
			
		||||
        val api = SelfossApi(
 | 
			
		||||
            context!!,
 | 
			
		||||
            activity!!,
 | 
			
		||||
            settings.getBoolean("isSelfSignedCert", false),
 | 
			
		||||
            prefs.getString("api_timeout", "-1").toLong(),
 | 
			
		||||
            prefs.getBoolean("should_log_everything", false)
 | 
			
		||||
        )
 | 
			
		||||
            val api = SelfossApi(
 | 
			
		||||
                context!!,
 | 
			
		||||
                activity!!,
 | 
			
		||||
                settings.getBoolean("isSelfSignedCert", false),
 | 
			
		||||
                prefs.getString("api_timeout", "-1").toLong(),
 | 
			
		||||
                prefs.getBoolean("should_log_everything", false)
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
        fab = rootView.fab
 | 
			
		||||
            fab = rootView!!.fab
 | 
			
		||||
 | 
			
		||||
        fab.backgroundTintList = ColorStateList.valueOf(appColors.colorAccent)
 | 
			
		||||
            fab.backgroundTintList = ColorStateList.valueOf(appColors.colorAccent)
 | 
			
		||||
 | 
			
		||||
        fab.rippleColor = appColors.colorAccentDark
 | 
			
		||||
            fab.rippleColor = appColors.colorAccentDark
 | 
			
		||||
 | 
			
		||||
        val floatingToolbar: FloatingToolbar = rootView.floatingToolbar
 | 
			
		||||
        floatingToolbar.attachFab(fab)
 | 
			
		||||
            val floatingToolbar: FloatingToolbar = rootView!!.floatingToolbar
 | 
			
		||||
            floatingToolbar.attachFab(fab)
 | 
			
		||||
 | 
			
		||||
        floatingToolbar.background = ColorDrawable(appColors.colorAccent)
 | 
			
		||||
            floatingToolbar.background = ColorDrawable(appColors.colorAccent)
 | 
			
		||||
 | 
			
		||||
        val customTabsIntent = activity!!.buildCustomTabsIntent()
 | 
			
		||||
        mCustomTabActivityHelper = CustomTabActivityHelper()
 | 
			
		||||
        mCustomTabActivityHelper.bindCustomTabsService(activity)
 | 
			
		||||
            val customTabsIntent = activity!!.buildCustomTabsIntent()
 | 
			
		||||
            mCustomTabActivityHelper = CustomTabActivityHelper()
 | 
			
		||||
            mCustomTabActivityHelper!!.bindCustomTabsService(activity)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        floatingToolbar.setClickListener(
 | 
			
		||||
            object : FloatingToolbar.ItemClickListener {
 | 
			
		||||
                override fun onItemClick(item: MenuItem) {
 | 
			
		||||
                    when (item.itemId) {
 | 
			
		||||
                        R.id.more_action -> getContentFromMercury(customTabsIntent, prefs)
 | 
			
		||||
                        R.id.share_action -> activity!!.shareLink(url, contentTitle)
 | 
			
		||||
                        R.id.open_action -> activity!!.openItemUrl(
 | 
			
		||||
                            allItems,
 | 
			
		||||
                            pageNumber.toInt(),
 | 
			
		||||
                            url,
 | 
			
		||||
                            customTabsIntent,
 | 
			
		||||
                            false,
 | 
			
		||||
                            false,
 | 
			
		||||
                            activity!!
 | 
			
		||||
                        )
 | 
			
		||||
                        R.id.unread_action -> if ((context != null && context!!.isNetworkAccessible(null)) || context == null) {
 | 
			
		||||
                            api.unmarkItem(allItems[pageNumber.toInt()].id).enqueue(
 | 
			
		||||
                                object : Callback<SuccessResponse> {
 | 
			
		||||
                                    override fun onResponse(
 | 
			
		||||
                                        call: Call<SuccessResponse>,
 | 
			
		||||
                                        response: Response<SuccessResponse>
 | 
			
		||||
                                    ) {
 | 
			
		||||
                                        if (!response.succeeded() && debugReadingItems) {
 | 
			
		||||
                                            val message =
 | 
			
		||||
                                                "message: ${response.message()} " +
 | 
			
		||||
                                                        "response isSuccess: ${response.isSuccessful} " +
 | 
			
		||||
                                                        "response code: ${response.code()} " +
 | 
			
		||||
                                                        "response message: ${response.message()} " +
 | 
			
		||||
                                                        "response errorBody: ${response.errorBody()?.string()} " +
 | 
			
		||||
                                                        "body success: ${response.body()?.success} " +
 | 
			
		||||
                                                        "body isSuccess: ${response.body()?.isSuccess}"
 | 
			
		||||
                                            ACRA.getErrorReporter().maybeHandleSilentException(Exception(message), activity!!)
 | 
			
		||||
                                        }
 | 
			
		||||
                                    }
 | 
			
		||||
 | 
			
		||||
                                    override fun onFailure(
 | 
			
		||||
                                        call: Call<SuccessResponse>,
 | 
			
		||||
                                        t: Throwable
 | 
			
		||||
                                    ) {
 | 
			
		||||
                                        if (debugReadingItems) {
 | 
			
		||||
                                            ACRA.getErrorReporter().maybeHandleSilentException(t, activity!!)
 | 
			
		||||
                                        }
 | 
			
		||||
                                    }
 | 
			
		||||
                                }
 | 
			
		||||
            floatingToolbar.setClickListener(
 | 
			
		||||
                object : FloatingToolbar.ItemClickListener {
 | 
			
		||||
                    override fun onItemClick(item: MenuItem) {
 | 
			
		||||
                        when (item.itemId) {
 | 
			
		||||
                            R.id.more_action -> getContentFromMercury(customTabsIntent, prefs)
 | 
			
		||||
                            R.id.share_action -> activity!!.shareLink(url, contentTitle)
 | 
			
		||||
                            R.id.open_action -> activity!!.openItemUrl(
 | 
			
		||||
                                allItems,
 | 
			
		||||
                                pageNumber.toInt(),
 | 
			
		||||
                                url,
 | 
			
		||||
                                customTabsIntent,
 | 
			
		||||
                                false,
 | 
			
		||||
                                false,
 | 
			
		||||
                                activity!!
 | 
			
		||||
                            )
 | 
			
		||||
                        } else {
 | 
			
		||||
                            thread {
 | 
			
		||||
                                db.actionsDao().insertAllActions(ActionEntity(allItems[pageNumber.toInt()].id, false, true, false, false))
 | 
			
		||||
                            R.id.unread_action -> if ((context != null && context!!.isNetworkAccessible(null)) || context == null) {
 | 
			
		||||
                                api.unmarkItem(allItems[pageNumber.toInt()].id).enqueue(
 | 
			
		||||
                                    object : Callback<SuccessResponse> {
 | 
			
		||||
                                        override fun onResponse(
 | 
			
		||||
                                            call: Call<SuccessResponse>,
 | 
			
		||||
                                            response: Response<SuccessResponse>
 | 
			
		||||
                                        ) {
 | 
			
		||||
                                            if (!response.succeeded() && debugReadingItems) {
 | 
			
		||||
                                                val message =
 | 
			
		||||
                                                    "message: ${response.message()} " +
 | 
			
		||||
                                                            "response isSuccess: ${response.isSuccessful} " +
 | 
			
		||||
                                                            "response code: ${response.code()} " +
 | 
			
		||||
                                                            "response message: ${response.message()} " +
 | 
			
		||||
                                                            "response errorBody: ${response.errorBody()?.string()} " +
 | 
			
		||||
                                                            "body success: ${response.body()?.success} " +
 | 
			
		||||
                                                            "body isSuccess: ${response.body()?.isSuccess}"
 | 
			
		||||
                                                ACRA.getErrorReporter().maybeHandleSilentException(Exception(message), activity!!)
 | 
			
		||||
                                            }
 | 
			
		||||
                                        }
 | 
			
		||||
 | 
			
		||||
                                        override fun onFailure(
 | 
			
		||||
                                            call: Call<SuccessResponse>,
 | 
			
		||||
                                            t: Throwable
 | 
			
		||||
                                        ) {
 | 
			
		||||
                                            if (debugReadingItems) {
 | 
			
		||||
                                                ACRA.getErrorReporter().maybeHandleSilentException(t, activity!!)
 | 
			
		||||
                                            }
 | 
			
		||||
                                        }
 | 
			
		||||
                                    }
 | 
			
		||||
                                )
 | 
			
		||||
                            } else {
 | 
			
		||||
                                thread {
 | 
			
		||||
                                    db.actionsDao().insertAllActions(ActionEntity(allItems[pageNumber.toInt()].id, false, true, false, false))
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                            else -> Unit
 | 
			
		||||
                        }
 | 
			
		||||
                        else -> Unit
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    override fun onItemLongClick(item: MenuItem?) {
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
                override fun onItemLongClick(item: MenuItem?) {
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        )
 | 
			
		||||
            rootView!!.source.text = contentSource
 | 
			
		||||
 | 
			
		||||
        rootView.source.text = contentSource
 | 
			
		||||
 | 
			
		||||
        if (contentText.isEmptyOrNullOrNullString()) {
 | 
			
		||||
            getContentFromMercury(customTabsIntent, prefs)
 | 
			
		||||
        } else {
 | 
			
		||||
            rootView.titleView.text = contentTitle
 | 
			
		||||
 | 
			
		||||
            htmlToWebview(contentText, prefs)
 | 
			
		||||
 | 
			
		||||
            if (!contentImage.isEmptyOrNullOrNullString() && context != null) {
 | 
			
		||||
                rootView.imageView.visibility = View.VISIBLE
 | 
			
		||||
                Glide
 | 
			
		||||
                    .with(context!!)
 | 
			
		||||
                    .asBitmap()
 | 
			
		||||
                    .load(contentImage)
 | 
			
		||||
                    .apply(RequestOptions.fitCenterTransform())
 | 
			
		||||
                    .into(rootView.imageView)
 | 
			
		||||
            if (contentText.isEmptyOrNullOrNullString()) {
 | 
			
		||||
                getContentFromMercury(customTabsIntent, prefs)
 | 
			
		||||
            } else {
 | 
			
		||||
                rootView.imageView.visibility = View.GONE
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
                rootView!!.titleView.text = contentTitle
 | 
			
		||||
 | 
			
		||||
        rootView.nestedScrollView.setOnScrollChangeListener(
 | 
			
		||||
            NestedScrollView.OnScrollChangeListener { _, _, scrollY, _, oldScrollY ->
 | 
			
		||||
                if (scrollY > oldScrollY) {
 | 
			
		||||
                    fab.hide()
 | 
			
		||||
                htmlToWebview(contentText, prefs)
 | 
			
		||||
 | 
			
		||||
                if (!contentImage.isEmptyOrNullOrNullString() && context != null) {
 | 
			
		||||
                    rootView!!.imageView.visibility = View.VISIBLE
 | 
			
		||||
                    Glide
 | 
			
		||||
                        .with(context!!)
 | 
			
		||||
                        .asBitmap()
 | 
			
		||||
                        .load(contentImage)
 | 
			
		||||
                        .apply(RequestOptions.fitCenterTransform())
 | 
			
		||||
                        .into(rootView!!.imageView)
 | 
			
		||||
                } else {
 | 
			
		||||
                    if (floatingToolbar.isShowing) floatingToolbar.hide() else fab.show()
 | 
			
		||||
                    rootView!!.imageView.visibility = View.GONE
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
            rootView!!.nestedScrollView.setOnScrollChangeListener(
 | 
			
		||||
                NestedScrollView.OnScrollChangeListener { _, _, scrollY, _, oldScrollY ->
 | 
			
		||||
                    if (scrollY > oldScrollY) {
 | 
			
		||||
                        fab.hide()
 | 
			
		||||
                    } else {
 | 
			
		||||
                        if (floatingToolbar.isShowing) floatingToolbar.hide() else fab.show()
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
        } catch (e: InflateException) {
 | 
			
		||||
            AlertDialog.Builder(context!!)
 | 
			
		||||
                .setMessage(context!!.getString(R.string.webview_dialog_issue_message))
 | 
			
		||||
                .setTitle(context!!.getString(R.string.webview_dialog_issue_title))
 | 
			
		||||
                .setPositiveButton(android.R.string.ok
 | 
			
		||||
                ) { dialog, which ->
 | 
			
		||||
                    val sharedPref = PreferenceManager.getDefaultSharedPreferences(context!!)
 | 
			
		||||
                    val editor = sharedPref.edit()
 | 
			
		||||
                    editor.putBoolean("prefer_article_viewer", false)
 | 
			
		||||
                    editor.commit()
 | 
			
		||||
                    activity!!.finish()
 | 
			
		||||
                }
 | 
			
		||||
                .create()
 | 
			
		||||
                .show()
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return rootView
 | 
			
		||||
    }
 | 
			
		||||
@@ -233,7 +253,7 @@ class ArticleFragment : Fragment() {
 | 
			
		||||
        prefs: SharedPreferences
 | 
			
		||||
    ) {
 | 
			
		||||
        if ((context != null && context!!.isNetworkAccessible(null)) || context == null) {
 | 
			
		||||
            rootView.progressBar.visibility = View.VISIBLE
 | 
			
		||||
            rootView!!.progressBar.visibility = View.VISIBLE
 | 
			
		||||
            val parser = MercuryApi(
 | 
			
		||||
                prefs.getBoolean("should_log_everything", false)
 | 
			
		||||
            )
 | 
			
		||||
@@ -248,7 +268,7 @@ class ArticleFragment : Fragment() {
 | 
			
		||||
                        try {
 | 
			
		||||
                            if (response.body() != null && response.body()!!.content != null && !response.body()!!.content.isNullOrEmpty()) {
 | 
			
		||||
                                try {
 | 
			
		||||
                                    rootView.titleView.text = response.body()!!.title
 | 
			
		||||
                                    rootView!!.titleView.text = response.body()!!.title
 | 
			
		||||
                                    try {
 | 
			
		||||
                                        // Note: Mercury may return relative urls... If it does the url val will not be changed.
 | 
			
		||||
                                        URL(response.body()!!.url)
 | 
			
		||||
@@ -272,19 +292,19 @@ class ArticleFragment : Fragment() {
 | 
			
		||||
 | 
			
		||||
                                try {
 | 
			
		||||
                                    if (response.body()!!.lead_image_url != null && !response.body()!!.lead_image_url.isNullOrEmpty() && context != null) {
 | 
			
		||||
                                        rootView.imageView.visibility = View.VISIBLE
 | 
			
		||||
                                        rootView!!.imageView.visibility = View.VISIBLE
 | 
			
		||||
                                        try {
 | 
			
		||||
                                            Glide
 | 
			
		||||
                                                .with(context!!)
 | 
			
		||||
                                                .asBitmap()
 | 
			
		||||
                                                .load(response.body()!!.lead_image_url)
 | 
			
		||||
                                                .apply(RequestOptions.fitCenterTransform())
 | 
			
		||||
                                                .into(rootView.imageView)
 | 
			
		||||
                                                .into(rootView!!.imageView)
 | 
			
		||||
                                        } catch (e: Exception) {
 | 
			
		||||
                                            ACRA.getErrorReporter().maybeHandleSilentException(e, context!!)
 | 
			
		||||
                                        }
 | 
			
		||||
                                    } else {
 | 
			
		||||
                                        rootView.imageView.visibility = View.GONE
 | 
			
		||||
                                        rootView!!.imageView.visibility = View.GONE
 | 
			
		||||
                                    }
 | 
			
		||||
                                } catch (e: Exception) {
 | 
			
		||||
                                    if (context != null) {
 | 
			
		||||
@@ -293,9 +313,9 @@ class ArticleFragment : Fragment() {
 | 
			
		||||
                                }
 | 
			
		||||
 | 
			
		||||
                                try {
 | 
			
		||||
                                    rootView.nestedScrollView.scrollTo(0, 0)
 | 
			
		||||
                                    rootView!!.nestedScrollView.scrollTo(0, 0)
 | 
			
		||||
 | 
			
		||||
                                    rootView.progressBar.visibility = View.GONE
 | 
			
		||||
                                    rootView!!.progressBar.visibility = View.GONE
 | 
			
		||||
                                } catch (e: Exception) {
 | 
			
		||||
                                    if (context != null) {
 | 
			
		||||
                                        ACRA.getErrorReporter().maybeHandleSilentException(e, context!!)
 | 
			
		||||
@@ -329,10 +349,10 @@ class ArticleFragment : Fragment() {
 | 
			
		||||
    private fun htmlToWebview(c: String, prefs: SharedPreferences) {
 | 
			
		||||
        val stringColor = String.format("#%06X", 0xFFFFFF and appColors.colorAccent)
 | 
			
		||||
 | 
			
		||||
        rootView.webcontent.visibility = View.VISIBLE
 | 
			
		||||
        rootView!!.webcontent.visibility = View.VISIBLE
 | 
			
		||||
        val (textColor, backgroundColor) = if (appColors.isDarkTheme) {
 | 
			
		||||
            if (context != null) {
 | 
			
		||||
                rootView.webcontent.setBackgroundColor(
 | 
			
		||||
                rootView!!.webcontent.setBackgroundColor(
 | 
			
		||||
                    ContextCompat.getColor(
 | 
			
		||||
                        context!!,
 | 
			
		||||
                        R.color.dark_webview
 | 
			
		||||
@@ -344,7 +364,7 @@ class ArticleFragment : Fragment() {
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            if (context != null) {
 | 
			
		||||
                rootView.webcontent.setBackgroundColor(
 | 
			
		||||
                rootView!!.webcontent.setBackgroundColor(
 | 
			
		||||
                    ContextCompat.getColor(
 | 
			
		||||
                        context!!,
 | 
			
		||||
                        R.color.light_webview
 | 
			
		||||
@@ -368,15 +388,15 @@ class ArticleFragment : Fragment() {
 | 
			
		||||
            "#FFFFFF"
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        rootView.webcontent.settings.useWideViewPort = true
 | 
			
		||||
        rootView.webcontent.settings.loadWithOverviewMode = true
 | 
			
		||||
        rootView.webcontent.settings.javaScriptEnabled = false
 | 
			
		||||
        rootView!!.webcontent.settings.useWideViewPort = true
 | 
			
		||||
        rootView!!.webcontent.settings.loadWithOverviewMode = true
 | 
			
		||||
        rootView!!.webcontent.settings.javaScriptEnabled = false
 | 
			
		||||
 | 
			
		||||
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
 | 
			
		||||
            rootView.webcontent.settings.layoutAlgorithm =
 | 
			
		||||
            rootView!!.webcontent.settings.layoutAlgorithm =
 | 
			
		||||
                    WebSettings.LayoutAlgorithm.TEXT_AUTOSIZING
 | 
			
		||||
        } else {
 | 
			
		||||
            rootView.webcontent.settings.layoutAlgorithm = WebSettings.LayoutAlgorithm.SINGLE_COLUMN
 | 
			
		||||
            rootView!!.webcontent.settings.layoutAlgorithm = WebSettings.LayoutAlgorithm.SINGLE_COLUMN
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        var baseUrl: String? = null
 | 
			
		||||
@@ -388,10 +408,11 @@ class ArticleFragment : Fragment() {
 | 
			
		||||
            ACRA.getErrorReporter().maybeHandleSilentException(e, activity!!)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        rootView.webcontent.loadDataWithBaseURL(
 | 
			
		||||
        rootView!!.webcontent.loadDataWithBaseURL(
 | 
			
		||||
            baseUrl,
 | 
			
		||||
            """<html>
 | 
			
		||||
                |<head>
 | 
			
		||||
                |   <meta name="viewport" content="width=device-width, initial-scale=1">
 | 
			
		||||
                |   <style>
 | 
			
		||||
                |      img {
 | 
			
		||||
                |        display: inline-block;
 | 
			
		||||
@@ -406,7 +427,7 @@ class ArticleFragment : Fragment() {
 | 
			
		||||
                |        color: $stringTextColor;
 | 
			
		||||
                |      }
 | 
			
		||||
                |      * {
 | 
			
		||||
                |        font-size: ${fontSize.toPx}px;
 | 
			
		||||
                |        font-size: ${fontSize}px;
 | 
			
		||||
                |        text-align: justify;
 | 
			
		||||
                |        word-break: break-word;
 | 
			
		||||
                |        overflow:hidden;
 | 
			
		||||
@@ -431,7 +452,7 @@ class ArticleFragment : Fragment() {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun openInBrowserAfterFailing(customTabsIntent: CustomTabsIntent) {
 | 
			
		||||
        rootView.progressBar.visibility = View.GONE
 | 
			
		||||
        rootView!!.progressBar.visibility = View.GONE
 | 
			
		||||
        activity!!.openItemUrl(
 | 
			
		||||
            allItems,
 | 
			
		||||
            pageNumber.toInt(),
 | 
			
		||||
 
 | 
			
		||||
@@ -2,15 +2,21 @@ package apps.amine.bou.readerforselfoss.utils
 | 
			
		||||
 | 
			
		||||
import android.content.Context
 | 
			
		||||
import android.preference.PreferenceManager
 | 
			
		||||
import android.provider.Settings
 | 
			
		||||
import org.acra.ErrorReporter
 | 
			
		||||
 | 
			
		||||
fun ErrorReporter.maybeHandleSilentException(throwable: Throwable, ctx: Context) {
 | 
			
		||||
    val sharedPref = PreferenceManager.getDefaultSharedPreferences(ctx)
 | 
			
		||||
    if (sharedPref.getBoolean("acra_should_log", false)) {
 | 
			
		||||
    val isTestLab = Settings.System.getString(ctx.contentResolver, "firebase.test.lab") ==  "true"
 | 
			
		||||
 | 
			
		||||
    if (sharedPref.getBoolean("acra_should_log", false) && !isTestLab) {
 | 
			
		||||
        this.handleSilentException(throwable)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fun ErrorReporter.doHandleSilentException(throwable: Throwable) {
 | 
			
		||||
    this.handleSilentException(throwable)
 | 
			
		||||
fun ErrorReporter.doHandleSilentException(throwable: Throwable, ctx: Context) {
 | 
			
		||||
    val isTestLab = Settings.System.getString(ctx.contentResolver, "firebase.test.lab") ==  "true"
 | 
			
		||||
    if (!isTestLab) {
 | 
			
		||||
        this.handleSilentException(throwable)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -2,6 +2,7 @@ package apps.amine.bou.readerforselfoss.utils
 | 
			
		||||
 | 
			
		||||
import android.app.Activity
 | 
			
		||||
import android.app.PendingIntent
 | 
			
		||||
import android.content.ActivityNotFoundException
 | 
			
		||||
import android.content.Context
 | 
			
		||||
import android.content.Intent
 | 
			
		||||
import android.graphics.BitmapFactory
 | 
			
		||||
@@ -129,13 +130,17 @@ fun Context.openItemUrl(
 | 
			
		||||
private fun openInBrowser(linkDecoded: String, app: Activity) {
 | 
			
		||||
    val intent = Intent(Intent.ACTION_VIEW)
 | 
			
		||||
    intent.data = Uri.parse(linkDecoded)
 | 
			
		||||
    app.startActivity(intent)
 | 
			
		||||
    try {
 | 
			
		||||
        app.startActivity(intent)
 | 
			
		||||
    } catch (e: ActivityNotFoundException) {
 | 
			
		||||
        Toast.makeText(app.baseContext, e.message, Toast.LENGTH_LONG).show()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fun String.isUrlValid(): Boolean =
 | 
			
		||||
    HttpUrl.parse(this) != null && Patterns.WEB_URL.matcher(this).matches()
 | 
			
		||||
 | 
			
		||||
fun String.isBaseUrlValid(logErrors: Boolean): Boolean {
 | 
			
		||||
fun String.isBaseUrlValid(logErrors: Boolean, ctx: Context): Boolean {
 | 
			
		||||
    val baseUrl = HttpUrl.parse(this)
 | 
			
		||||
    var existsAndEndsWithSlash = false
 | 
			
		||||
    if (baseUrl != null) {
 | 
			
		||||
@@ -145,7 +150,7 @@ fun String.isBaseUrlValid(logErrors: Boolean): Boolean {
 | 
			
		||||
 | 
			
		||||
    val isValid = Patterns.WEB_URL.matcher(this).matches() && existsAndEndsWithSlash
 | 
			
		||||
    if (!isValid && logErrors) {
 | 
			
		||||
        ACRA.getErrorReporter().doHandleSilentException(java.lang.Exception("Patterns.WEB_URL.matcher(this).matches() == ${Patterns.WEB_URL.matcher(this).matches()} && existsAndEndsWithSlash == $existsAndEndsWithSlash && baseUrl.pathSegments() == ${baseUrl?.pathSegments()}"))
 | 
			
		||||
        ACRA.getErrorReporter().doHandleSilentException(java.lang.Exception("Patterns.WEB_URL.matcher(this).matches() == ${Patterns.WEB_URL.matcher(this).matches()} && existsAndEndsWithSlash == $existsAndEndsWithSlash && baseUrl.pathSegments() == ${baseUrl?.pathSegments()}"), ctx)
 | 
			
		||||
    }
 | 
			
		||||
    return isValid
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -168,4 +168,6 @@
 | 
			
		||||
    <string name="shortcut_offline">Offline</string>
 | 
			
		||||
    <string name="pref_api_timeout">Api Timeout</string>
 | 
			
		||||
    <string name="pref_header_experimental">Experimental</string>
 | 
			
		||||
    <string name="webview_dialog_issue_message">Webview not available. Disabling the article viewer to avoid any future crashes. Will load articles inside of your browser from now on.</string>
 | 
			
		||||
    <string name="webview_dialog_issue_title">Webview issue</string>
 | 
			
		||||
</resources>
 | 
			
		||||
 
 | 
			
		||||
@@ -168,4 +168,6 @@
 | 
			
		||||
    <string name="shortcut_offline">Offline</string>
 | 
			
		||||
    <string name="pref_api_timeout">Api Timeout</string>
 | 
			
		||||
    <string name="pref_header_experimental">Experimental</string>
 | 
			
		||||
    <string name="webview_dialog_issue_message">Webview not available. Disabling the article viewer to avoid any future crashes. Will load articles inside of your browser from now on.</string>
 | 
			
		||||
    <string name="webview_dialog_issue_title">Webview issue</string>
 | 
			
		||||
</resources>
 | 
			
		||||
 
 | 
			
		||||
@@ -108,7 +108,7 @@
 | 
			
		||||
    <string name="self_signed_cert_warning">Per raons de seguretat, els certificats autosignats no seran compatibles per defecte. En activar aquesta opció, sereu responsable de qualsevol problema de seguretat que es pugui produir.</string>
 | 
			
		||||
    <string name="pref_selfoss_category">API de Selfoss</string>
 | 
			
		||||
    <string name="pref_api_items_number_title">Nombre d\'elements carregats</string>
 | 
			
		||||
    <string name="pref_hidden_tags">Hidden Tags</string>
 | 
			
		||||
    <string name="pref_hidden_tags">Etiquetes ocultes</string>
 | 
			
		||||
    <string name="read_debug_title">Voleu llegir els articles que apareixen com a no llegits?</string>
 | 
			
		||||
    <string name="read_debug_off">No es registraran quan es marquen elements com a llegits</string>
 | 
			
		||||
    <string name="read_debug_on">Les crides de l\'API es registraran en marcar un article com a llegit</string>
 | 
			
		||||
@@ -146,26 +146,28 @@
 | 
			
		||||
    <string name="pref_debug_crash_reports">Informes d\'error</string>
 | 
			
		||||
    <string name="pref_debug_debug_logs">Registre de depuració (s\'enviarà automàticament)</string>
 | 
			
		||||
    <string name="acra_login">Habilita el registre</string>
 | 
			
		||||
    <string name="drawer_item_hidden_tags">Hidden Tags</string>
 | 
			
		||||
    <string name="unmark">Mark item as unread</string>
 | 
			
		||||
    <string name="pref_header_offline">Offline and cache</string>
 | 
			
		||||
    <string name="pref_switch_items_caching_off">Articles won\'t be saved to the device memory, and the app won\'t be usable offline.</string>
 | 
			
		||||
    <string name="pref_switch_items_caching_on">Articles will be saved to the device memory and will be used for offline use.</string>
 | 
			
		||||
    <string name="pref_switch_items_caching">Save items for offline use</string>
 | 
			
		||||
    <string name="no_network_connectivity">Not connected !</string>
 | 
			
		||||
    <string name="pref_switch_periodic_refresh">Sync articles</string>
 | 
			
		||||
    <string name="pref_switch_periodic_refresh_off">Articles will not be synced in the background</string>
 | 
			
		||||
    <string name="pref_switch_periodic_refresh_on">Articles will periodically be synced</string>
 | 
			
		||||
    <string name="pref_periodic_refresh_minutes_title"><![CDATA[Sync interval ( >= 15 minutes)]]></string>
 | 
			
		||||
    <string name="pref_switch_refresh_when_charging">Only refresh when phone is charging</string>
 | 
			
		||||
    <string name="loading_notification_title">Loading ...</string>
 | 
			
		||||
    <string name="loading_notification_text">Selfoss is syncing your articles</string>
 | 
			
		||||
    <string name="notification_channel_sync">Sync notification</string>
 | 
			
		||||
    <string name="new_items_channel_sync">New items notification</string>
 | 
			
		||||
    <string name="new_items_notification_title">New items !</string>
 | 
			
		||||
    <string name="new_items_notification_text">%1$d new items loaded.</string>
 | 
			
		||||
    <string name="pref_switch_notify_new_items">Notify on new items synced.</string>
 | 
			
		||||
    <string name="shortcut_offline">Offline</string>
 | 
			
		||||
    <string name="pref_api_timeout">Api Timeout</string>
 | 
			
		||||
    <string name="drawer_item_hidden_tags">Etiquetes ocultes</string>
 | 
			
		||||
    <string name="unmark">Marca com no llegit</string>
 | 
			
		||||
    <string name="pref_header_offline">Sense connexió i memòria clau</string>
 | 
			
		||||
    <string name="pref_switch_items_caching_off">Els articles no es guardaran a la memòria del dispositiu i l\'aplicació no es podrà utilitzar sense connexió.</string>
 | 
			
		||||
    <string name="pref_switch_items_caching_on">Els articles es guardaran a la memòria del dispositiu i es podran utilitzar sense connexió.</string>
 | 
			
		||||
    <string name="pref_switch_items_caching">Guarda els elements per utilitzar-los sense connexió</string>
 | 
			
		||||
    <string name="no_network_connectivity">Sense connexió!</string>
 | 
			
		||||
    <string name="pref_switch_periodic_refresh">Sincronitza els articles</string>
 | 
			
		||||
    <string name="pref_switch_periodic_refresh_off">Els articles no se sincronitzaran en segon pla</string>
 | 
			
		||||
    <string name="pref_switch_periodic_refresh_on">Els articles se sincronitzaran periòdicament</string>
 | 
			
		||||
    <string name="pref_periodic_refresh_minutes_title"><![CDATA[Interval de sincronització ( >= 15 minuts)]]></string>
 | 
			
		||||
    <string name="pref_switch_refresh_when_charging">Sincronitza només quan el telèfon s\'està carregant</string>
 | 
			
		||||
    <string name="loading_notification_title">S\'està carregant...</string>
 | 
			
		||||
    <string name="loading_notification_text">Selfoss està sincronitzant els articles</string>
 | 
			
		||||
    <string name="notification_channel_sync">Notificació de sincronització</string>
 | 
			
		||||
    <string name="new_items_channel_sync">Notificació d\'elements nous</string>
 | 
			
		||||
    <string name="new_items_notification_title">Nous articles!</string>
 | 
			
		||||
    <string name="new_items_notification_text">S\'han carregat %1$d articles nous.</string>
 | 
			
		||||
    <string name="pref_switch_notify_new_items">Avisa\'m quan se sincronitzin articles nous.</string>
 | 
			
		||||
    <string name="shortcut_offline">Sense connexió</string>
 | 
			
		||||
    <string name="pref_api_timeout">S\'ha acabat el temps d\'espera de l\'API</string>
 | 
			
		||||
    <string name="pref_header_experimental">Experimental</string>
 | 
			
		||||
    <string name="webview_dialog_issue_message">Webview not available. Disabling the article viewer to avoid any future crashes. Will load articles inside of your browser from now on.</string>
 | 
			
		||||
    <string name="webview_dialog_issue_title">Webview issue</string>
 | 
			
		||||
</resources>
 | 
			
		||||
 
 | 
			
		||||
@@ -168,4 +168,6 @@
 | 
			
		||||
    <string name="shortcut_offline">Offline</string>
 | 
			
		||||
    <string name="pref_api_timeout">Api Timeout</string>
 | 
			
		||||
    <string name="pref_header_experimental">Experimental</string>
 | 
			
		||||
    <string name="webview_dialog_issue_message">Webview not available. Disabling the article viewer to avoid any future crashes. Will load articles inside of your browser from now on.</string>
 | 
			
		||||
    <string name="webview_dialog_issue_title">Webview issue</string>
 | 
			
		||||
</resources>
 | 
			
		||||
 
 | 
			
		||||
@@ -168,4 +168,6 @@
 | 
			
		||||
    <string name="shortcut_offline">Offline</string>
 | 
			
		||||
    <string name="pref_api_timeout">Api Timeout</string>
 | 
			
		||||
    <string name="pref_header_experimental">Experimental</string>
 | 
			
		||||
    <string name="webview_dialog_issue_message">Webview not available. Disabling the article viewer to avoid any future crashes. Will load articles inside of your browser from now on.</string>
 | 
			
		||||
    <string name="webview_dialog_issue_title">Webview issue</string>
 | 
			
		||||
</resources>
 | 
			
		||||
 
 | 
			
		||||
@@ -168,4 +168,6 @@
 | 
			
		||||
    <string name="shortcut_offline">Offline</string>
 | 
			
		||||
    <string name="pref_api_timeout">API-Zeitüberschreitung</string>
 | 
			
		||||
    <string name="pref_header_experimental">Experimentell</string>
 | 
			
		||||
    <string name="webview_dialog_issue_message">Webview not available. Disabling the article viewer to avoid any future crashes. Will load articles inside of your browser from now on.</string>
 | 
			
		||||
    <string name="webview_dialog_issue_title">Webview issue</string>
 | 
			
		||||
</resources>
 | 
			
		||||
 
 | 
			
		||||
@@ -168,4 +168,6 @@
 | 
			
		||||
    <string name="shortcut_offline">Offline</string>
 | 
			
		||||
    <string name="pref_api_timeout">Api Timeout</string>
 | 
			
		||||
    <string name="pref_header_experimental">Experimental</string>
 | 
			
		||||
    <string name="webview_dialog_issue_message">Webview not available. Disabling the article viewer to avoid any future crashes. Will load articles inside of your browser from now on.</string>
 | 
			
		||||
    <string name="webview_dialog_issue_title">Webview issue</string>
 | 
			
		||||
</resources>
 | 
			
		||||
 
 | 
			
		||||
@@ -168,4 +168,6 @@
 | 
			
		||||
    <string name="shortcut_offline">Sin conexión</string>
 | 
			
		||||
    <string name="pref_api_timeout">Se acabó el tiempo de espera de la API</string>
 | 
			
		||||
    <string name="pref_header_experimental">Experimental</string>
 | 
			
		||||
    <string name="webview_dialog_issue_message">Webview not available. Disabling the article viewer to avoid any future crashes. Will load articles inside of your browser from now on.</string>
 | 
			
		||||
    <string name="webview_dialog_issue_title">Webview issue</string>
 | 
			
		||||
</resources>
 | 
			
		||||
 
 | 
			
		||||
@@ -168,4 +168,6 @@
 | 
			
		||||
    <string name="shortcut_offline">Offline</string>
 | 
			
		||||
    <string name="pref_api_timeout">Api Timeout</string>
 | 
			
		||||
    <string name="pref_header_experimental">Experimental</string>
 | 
			
		||||
    <string name="webview_dialog_issue_message">Webview not available. Disabling the article viewer to avoid any future crashes. Will load articles inside of your browser from now on.</string>
 | 
			
		||||
    <string name="webview_dialog_issue_title">Webview issue</string>
 | 
			
		||||
</resources>
 | 
			
		||||
 
 | 
			
		||||
@@ -166,6 +166,8 @@
 | 
			
		||||
    <string name="new_items_notification_text">%1$d nouveaux articles synchronisés.</string>
 | 
			
		||||
    <string name="pref_switch_notify_new_items">Notification quand des nouveaux articles sont synchronisés.</string>
 | 
			
		||||
    <string name="shortcut_offline">Hors ligne</string>
 | 
			
		||||
    <string name="pref_api_timeout">Api Timeout</string>
 | 
			
		||||
    <string name="pref_header_experimental">Experimental</string>
 | 
			
		||||
    <string name="pref_api_timeout">Timeout de l\'api</string>
 | 
			
		||||
    <string name="pref_header_experimental">Expérimental</string>
 | 
			
		||||
    <string name="webview_dialog_issue_message">Pas de Webview disponible. Désactivation du lecteur d\'article pour éviter les futures erreurs. Les articles seront lu via votre navigateur à l\'avenir.</string>
 | 
			
		||||
    <string name="webview_dialog_issue_title">Problème de Webview</string>
 | 
			
		||||
</resources>
 | 
			
		||||
 
 | 
			
		||||
@@ -168,4 +168,6 @@
 | 
			
		||||
    <string name="shortcut_offline">Sen conexión</string>
 | 
			
		||||
    <string name="pref_api_timeout">Acabouse o tempo de espera da API</string>
 | 
			
		||||
    <string name="pref_header_experimental">Experimental</string>
 | 
			
		||||
    <string name="webview_dialog_issue_message">Webview not available. Disabling the article viewer to avoid any future crashes. Will load articles inside of your browser from now on.</string>
 | 
			
		||||
    <string name="webview_dialog_issue_title">Webview issue</string>
 | 
			
		||||
</resources>
 | 
			
		||||
 
 | 
			
		||||
@@ -168,4 +168,6 @@
 | 
			
		||||
    <string name="shortcut_offline">Offline</string>
 | 
			
		||||
    <string name="pref_api_timeout">Api Timeout</string>
 | 
			
		||||
    <string name="pref_header_experimental">Experimental</string>
 | 
			
		||||
    <string name="webview_dialog_issue_message">Webview not available. Disabling the article viewer to avoid any future crashes. Will load articles inside of your browser from now on.</string>
 | 
			
		||||
    <string name="webview_dialog_issue_title">Webview issue</string>
 | 
			
		||||
</resources>
 | 
			
		||||
 
 | 
			
		||||
@@ -168,4 +168,6 @@
 | 
			
		||||
    <string name="shortcut_offline">Offline</string>
 | 
			
		||||
    <string name="pref_api_timeout">Api Timeout</string>
 | 
			
		||||
    <string name="pref_header_experimental">Experimental</string>
 | 
			
		||||
    <string name="webview_dialog_issue_message">Webview not available. Disabling the article viewer to avoid any future crashes. Will load articles inside of your browser from now on.</string>
 | 
			
		||||
    <string name="webview_dialog_issue_title">Webview issue</string>
 | 
			
		||||
</resources>
 | 
			
		||||
 
 | 
			
		||||
@@ -168,4 +168,6 @@
 | 
			
		||||
    <string name="shortcut_offline">Offline</string>
 | 
			
		||||
    <string name="pref_api_timeout">Api Timeout</string>
 | 
			
		||||
    <string name="pref_header_experimental">Experimental</string>
 | 
			
		||||
    <string name="webview_dialog_issue_message">Webview not available. Disabling the article viewer to avoid any future crashes. Will load articles inside of your browser from now on.</string>
 | 
			
		||||
    <string name="webview_dialog_issue_title">Webview issue</string>
 | 
			
		||||
</resources>
 | 
			
		||||
 
 | 
			
		||||
@@ -168,4 +168,6 @@
 | 
			
		||||
    <string name="shortcut_offline">Offline</string>
 | 
			
		||||
    <string name="pref_api_timeout">Api Timeout</string>
 | 
			
		||||
    <string name="pref_header_experimental">Experimental</string>
 | 
			
		||||
    <string name="webview_dialog_issue_message">Webview not available. Disabling the article viewer to avoid any future crashes. Will load articles inside of your browser from now on.</string>
 | 
			
		||||
    <string name="webview_dialog_issue_title">Webview issue</string>
 | 
			
		||||
</resources>
 | 
			
		||||
 
 | 
			
		||||
@@ -168,4 +168,6 @@
 | 
			
		||||
    <string name="shortcut_offline">Offline</string>
 | 
			
		||||
    <string name="pref_api_timeout">Api Timeout</string>
 | 
			
		||||
    <string name="pref_header_experimental">Experimental</string>
 | 
			
		||||
    <string name="webview_dialog_issue_message">Webview not available. Disabling the article viewer to avoid any future crashes. Will load articles inside of your browser from now on.</string>
 | 
			
		||||
    <string name="webview_dialog_issue_title">Webview issue</string>
 | 
			
		||||
</resources>
 | 
			
		||||
 
 | 
			
		||||
@@ -168,4 +168,6 @@
 | 
			
		||||
    <string name="shortcut_offline">Offline</string>
 | 
			
		||||
    <string name="pref_api_timeout">Api Timeout</string>
 | 
			
		||||
    <string name="pref_header_experimental">Experimental</string>
 | 
			
		||||
    <string name="webview_dialog_issue_message">Webview not available. Disabling the article viewer to avoid any future crashes. Will load articles inside of your browser from now on.</string>
 | 
			
		||||
    <string name="webview_dialog_issue_title">Webview issue</string>
 | 
			
		||||
</resources>
 | 
			
		||||
 
 | 
			
		||||
@@ -168,4 +168,6 @@
 | 
			
		||||
    <string name="shortcut_offline">Offline</string>
 | 
			
		||||
    <string name="pref_api_timeout">Api Timeout</string>
 | 
			
		||||
    <string name="pref_header_experimental">Experimental</string>
 | 
			
		||||
    <string name="webview_dialog_issue_message">Webview not available. Disabling the article viewer to avoid any future crashes. Will load articles inside of your browser from now on.</string>
 | 
			
		||||
    <string name="webview_dialog_issue_title">Webview issue</string>
 | 
			
		||||
</resources>
 | 
			
		||||
 
 | 
			
		||||
@@ -168,4 +168,6 @@
 | 
			
		||||
    <string name="shortcut_offline">Offline</string>
 | 
			
		||||
    <string name="pref_api_timeout">Api Timeout</string>
 | 
			
		||||
    <string name="pref_header_experimental">Experimental</string>
 | 
			
		||||
    <string name="webview_dialog_issue_message">Webview not available. Disabling the article viewer to avoid any future crashes. Will load articles inside of your browser from now on.</string>
 | 
			
		||||
    <string name="webview_dialog_issue_title">Webview issue</string>
 | 
			
		||||
</resources>
 | 
			
		||||
 
 | 
			
		||||
@@ -168,4 +168,6 @@
 | 
			
		||||
    <string name="shortcut_offline">Offline</string>
 | 
			
		||||
    <string name="pref_api_timeout">Api Timeout</string>
 | 
			
		||||
    <string name="pref_header_experimental">Experimental</string>
 | 
			
		||||
    <string name="webview_dialog_issue_message">Webview not available. Disabling the article viewer to avoid any future crashes. Will load articles inside of your browser from now on.</string>
 | 
			
		||||
    <string name="webview_dialog_issue_title">Webview issue</string>
 | 
			
		||||
</resources>
 | 
			
		||||
 
 | 
			
		||||
@@ -168,4 +168,6 @@
 | 
			
		||||
    <string name="shortcut_offline">Offline</string>
 | 
			
		||||
    <string name="pref_api_timeout">Api Timeout</string>
 | 
			
		||||
    <string name="pref_header_experimental">Experimental</string>
 | 
			
		||||
    <string name="webview_dialog_issue_message">Webview not available. Disabling the article viewer to avoid any future crashes. Will load articles inside of your browser from now on.</string>
 | 
			
		||||
    <string name="webview_dialog_issue_title">Webview issue</string>
 | 
			
		||||
</resources>
 | 
			
		||||
 
 | 
			
		||||
@@ -168,4 +168,6 @@
 | 
			
		||||
    <string name="shortcut_offline">Offline</string>
 | 
			
		||||
    <string name="pref_api_timeout">Api Timeout</string>
 | 
			
		||||
    <string name="pref_header_experimental">Experimental</string>
 | 
			
		||||
    <string name="webview_dialog_issue_message">Webview not available. Disabling the article viewer to avoid any future crashes. Will load articles inside of your browser from now on.</string>
 | 
			
		||||
    <string name="webview_dialog_issue_title">Webview issue</string>
 | 
			
		||||
</resources>
 | 
			
		||||
 
 | 
			
		||||
@@ -168,4 +168,6 @@
 | 
			
		||||
    <string name="shortcut_offline">Offline</string>
 | 
			
		||||
    <string name="pref_api_timeout">Api Timeout</string>
 | 
			
		||||
    <string name="pref_header_experimental">Experimental</string>
 | 
			
		||||
    <string name="webview_dialog_issue_message">Webview not available. Disabling the article viewer to avoid any future crashes. Will load articles inside of your browser from now on.</string>
 | 
			
		||||
    <string name="webview_dialog_issue_title">Webview issue</string>
 | 
			
		||||
</resources>
 | 
			
		||||
 
 | 
			
		||||
@@ -168,4 +168,6 @@
 | 
			
		||||
    <string name="shortcut_offline">Offline</string>
 | 
			
		||||
    <string name="pref_api_timeout">Api Timeout</string>
 | 
			
		||||
    <string name="pref_header_experimental">Experimental</string>
 | 
			
		||||
    <string name="webview_dialog_issue_message">Webview not available. Disabling the article viewer to avoid any future crashes. Will load articles inside of your browser from now on.</string>
 | 
			
		||||
    <string name="webview_dialog_issue_title">Webview issue</string>
 | 
			
		||||
</resources>
 | 
			
		||||
 
 | 
			
		||||
@@ -168,4 +168,6 @@
 | 
			
		||||
    <string name="shortcut_offline">Offline</string>
 | 
			
		||||
    <string name="pref_api_timeout">Api Timeout</string>
 | 
			
		||||
    <string name="pref_header_experimental">Experimental</string>
 | 
			
		||||
    <string name="webview_dialog_issue_message">Webview not available. Disabling the article viewer to avoid any future crashes. Will load articles inside of your browser from now on.</string>
 | 
			
		||||
    <string name="webview_dialog_issue_title">Webview issue</string>
 | 
			
		||||
</resources>
 | 
			
		||||
 
 | 
			
		||||
@@ -168,4 +168,6 @@
 | 
			
		||||
    <string name="shortcut_offline">Offline</string>
 | 
			
		||||
    <string name="pref_api_timeout">Api Timeout</string>
 | 
			
		||||
    <string name="pref_header_experimental">Experimental</string>
 | 
			
		||||
    <string name="webview_dialog_issue_message">Webview not available. Disabling the article viewer to avoid any future crashes. Will load articles inside of your browser from now on.</string>
 | 
			
		||||
    <string name="webview_dialog_issue_title">Webview issue</string>
 | 
			
		||||
</resources>
 | 
			
		||||
 
 | 
			
		||||
@@ -168,4 +168,6 @@
 | 
			
		||||
    <string name="shortcut_offline">Offline</string>
 | 
			
		||||
    <string name="pref_api_timeout">Api Timeout</string>
 | 
			
		||||
    <string name="pref_header_experimental">Experimental</string>
 | 
			
		||||
    <string name="webview_dialog_issue_message">Webview not available. Disabling the article viewer to avoid any future crashes. Will load articles inside of your browser from now on.</string>
 | 
			
		||||
    <string name="webview_dialog_issue_title">Webview issue</string>
 | 
			
		||||
</resources>
 | 
			
		||||
 
 | 
			
		||||
@@ -168,4 +168,6 @@
 | 
			
		||||
    <string name="shortcut_offline">Offline</string>
 | 
			
		||||
    <string name="pref_api_timeout">Api Timeout</string>
 | 
			
		||||
    <string name="pref_header_experimental">Experimental</string>
 | 
			
		||||
    <string name="webview_dialog_issue_message">Webview not available. Disabling the article viewer to avoid any future crashes. Will load articles inside of your browser from now on.</string>
 | 
			
		||||
    <string name="webview_dialog_issue_title">Webview issue</string>
 | 
			
		||||
</resources>
 | 
			
		||||
 
 | 
			
		||||
@@ -168,4 +168,6 @@
 | 
			
		||||
    <string name="shortcut_offline">Offline</string>
 | 
			
		||||
    <string name="pref_api_timeout">Api Timeout</string>
 | 
			
		||||
    <string name="pref_header_experimental">Experimental</string>
 | 
			
		||||
    <string name="webview_dialog_issue_message">Webview not available. Disabling the article viewer to avoid any future crashes. Will load articles inside of your browser from now on.</string>
 | 
			
		||||
    <string name="webview_dialog_issue_title">Webview issue</string>
 | 
			
		||||
</resources>
 | 
			
		||||
 
 | 
			
		||||
@@ -168,4 +168,6 @@
 | 
			
		||||
    <string name="shortcut_offline">Offline</string>
 | 
			
		||||
    <string name="pref_api_timeout">Api Timeout</string>
 | 
			
		||||
    <string name="pref_header_experimental">Experimental</string>
 | 
			
		||||
    <string name="webview_dialog_issue_message">Webview not available. Disabling the article viewer to avoid any future crashes. Will load articles inside of your browser from now on.</string>
 | 
			
		||||
    <string name="webview_dialog_issue_title">Webview issue</string>
 | 
			
		||||
</resources>
 | 
			
		||||
 
 | 
			
		||||
@@ -168,4 +168,6 @@
 | 
			
		||||
    <string name="shortcut_offline">Offline</string>
 | 
			
		||||
    <string name="pref_api_timeout">Api Timeout</string>
 | 
			
		||||
    <string name="pref_header_experimental">Experimental</string>
 | 
			
		||||
    <string name="webview_dialog_issue_message">Webview not available. Disabling the article viewer to avoid any future crashes. Will load articles inside of your browser from now on.</string>
 | 
			
		||||
    <string name="webview_dialog_issue_title">Webview issue</string>
 | 
			
		||||
</resources>
 | 
			
		||||
 
 | 
			
		||||
@@ -168,4 +168,6 @@
 | 
			
		||||
    <string name="shortcut_offline">Offline</string>
 | 
			
		||||
    <string name="pref_api_timeout">Api Timeout</string>
 | 
			
		||||
    <string name="pref_header_experimental">Experimental</string>
 | 
			
		||||
    <string name="webview_dialog_issue_message">Webview not available. Disabling the article viewer to avoid any future crashes. Will load articles inside of your browser from now on.</string>
 | 
			
		||||
    <string name="webview_dialog_issue_title">Webview issue</string>
 | 
			
		||||
</resources>
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
        android:title="@string/pref_switch_actions_pager_scroll" />
 | 
			
		||||
 | 
			
		||||
    <EditTextPreference
 | 
			
		||||
        android:defaultValue="14"
 | 
			
		||||
        android:defaultValue="16"
 | 
			
		||||
        android:inputType="number"
 | 
			
		||||
        android:key="reader_font_size"
 | 
			
		||||
        android:selectAllOnFocus="true"
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user