Compare commits

..

34 Commits

Author SHA1 Message Date
3bdfef9f8b Added changelog and changed fab size. 2017-11-12 07:55:01 +01:00
6f7f475a6b Enhancements. Three first items of #108. 2017-11-12 07:51:11 +01:00
8fc5fab67b Merge branch 'master' of github.com:aminecmi/ReaderforSelfoss 2017-11-11 21:01:48 +01:00
6927e92396 New Crowdin translations (#105)
* New translations strings.xml (French)

* New translations strings.xml (Afrikaans)

* New translations strings.xml (Japanese)

* New translations strings.xml (Ukrainian)

* New translations strings.xml (Turkish)

* New translations strings.xml (Swedish)

* New translations strings.xml (Spanish)

* New translations strings.xml (Serbian (Cyrillic))

* New translations strings.xml (Russian)

* New translations strings.xml (Romanian)

* New translations strings.xml (Portuguese, Brazilian)

* New translations strings.xml (Polish)

* New translations strings.xml (Norwegian)

* New translations strings.xml (Korean)

* New translations strings.xml (Italian)

* New translations strings.xml (Arabic)

* New translations strings.xml (Hungarian)

* New translations strings.xml (Hebrew)

* New translations strings.xml (Greek)

* New translations strings.xml (German)

* New translations strings.xml (French)

* New translations strings.xml (Finnish)

* New translations strings.xml (Dutch)

* New translations strings.xml (Danish)

* New translations strings.xml (Czech)

* New translations strings.xml (Chinese Traditional)

* New translations strings.xml (Catalan)

* New translations strings.xml (Vietnamese)

* New translations strings.xml (Portuguese, Brazilian)

* New translations strings.xml (Portuguese, Brazilian)

* New translations strings.xml (Portuguese)

* New translations strings.xml (Portuguese, Brazilian)

* New translations strings.xml (Afrikaans)

* New translations strings.xml (Japanese)

* New translations strings.xml (Ukrainian)

* New translations strings.xml (Turkish)

* New translations strings.xml (Swedish)

* New translations strings.xml (Spanish)

* New translations strings.xml (Serbian (Cyrillic))

* New translations strings.xml (Russian)

* New translations strings.xml (Romanian)

* New translations strings.xml (Portuguese, Brazilian)

* New translations strings.xml (Arabic)

* New translations strings.xml (Greek)

* New translations strings.xml (Portuguese)

* New translations strings.xml (Polish)

* New translations strings.xml (Norwegian)

* New translations strings.xml (Korean)

* New translations strings.xml (Italian)

* New translations strings.xml (Hungarian)

* New translations strings.xml (Hebrew)

* New translations strings.xml (German)

* New translations strings.xml (Catalan)

* New translations strings.xml (French)

* New translations strings.xml (Finnish)

* New translations strings.xml (Dutch)

* New translations strings.xml (Danish)

* New translations strings.xml (Czech)

* New translations strings.xml (Chinese Traditional)

* New translations strings.xml (Portuguese, Brazilian)

* New translations strings.xml (Vietnamese)
2017-11-11 21:01:25 +01:00
c7470396d7 Changelog. 2017-11-11 20:55:31 +01:00
f21570e2e4 New Crowdin translations (#104)
* New translations strings.xml (French)

* New translations strings.xml (Afrikaans)

* New translations strings.xml (Japanese)

* New translations strings.xml (Ukrainian)

* New translations strings.xml (Turkish)

* New translations strings.xml (Swedish)

* New translations strings.xml (Spanish)

* New translations strings.xml (Serbian (Cyrillic))

* New translations strings.xml (Russian)

* New translations strings.xml (Romanian)

* New translations strings.xml (Portuguese, Brazilian)

* New translations strings.xml (Polish)

* New translations strings.xml (Norwegian)

* New translations strings.xml (Korean)

* New translations strings.xml (Italian)

* New translations strings.xml (Arabic)

* New translations strings.xml (Hungarian)

* New translations strings.xml (Hebrew)

* New translations strings.xml (Greek)

* New translations strings.xml (German)

* New translations strings.xml (French)

* New translations strings.xml (Finnish)

* New translations strings.xml (Dutch)

* New translations strings.xml (Danish)

* New translations strings.xml (Czech)

* New translations strings.xml (Chinese Traditional)

* New translations strings.xml (Catalan)

* New translations strings.xml (Vietnamese)

* New translations strings.xml (Portuguese, Brazilian)

* New translations strings.xml (Portuguese, Brazilian)

* New translations strings.xml (Portuguese)

* New translations strings.xml (Portuguese, Brazilian)

* New translations strings.xml (Afrikaans)

* New translations strings.xml (Japanese)

* New translations strings.xml (Ukrainian)

* New translations strings.xml (Turkish)

* New translations strings.xml (Swedish)

* New translations strings.xml (Spanish)

* New translations strings.xml (Serbian (Cyrillic))

* New translations strings.xml (Russian)

* New translations strings.xml (Romanian)

* New translations strings.xml (Portuguese, Brazilian)

* New translations strings.xml (Arabic)

* New translations strings.xml (Greek)

* New translations strings.xml (Portuguese)

* New translations strings.xml (Polish)

* New translations strings.xml (Norwegian)

* New translations strings.xml (Korean)

* New translations strings.xml (Italian)

* New translations strings.xml (Hungarian)

* New translations strings.xml (Hebrew)

* New translations strings.xml (German)

* New translations strings.xml (Catalan)

* New translations strings.xml (French)

* New translations strings.xml (Finnish)

* New translations strings.xml (Dutch)

* New translations strings.xml (Danish)

* New translations strings.xml (Czech)

* New translations strings.xml (Chinese Traditional)
2017-11-11 20:53:15 +01:00
51f406e20c New action bar. Closes #103. 2017-11-11 20:39:56 +01:00
9e3fde744e Changed to Textview to disaply the simple content from the API. 2017-11-11 16:50:17 +01:00
ccf406ae68 Update CONTRIBUTING.md 2017-11-11 14:47:40 +01:00
bc78d1e079 Changelog and updated target sdk. 2017-11-11 14:35:13 +01:00
d151eb261e Updates to make the build work. 2017-11-11 14:28:06 +01:00
0856598cd9 Changelog. 2017-11-11 08:44:18 +01:00
f0563efc62 Fixed #98. Using kotlin implementation for the drawer. Using the new style code. 2017-11-11 07:58:29 +01:00
84dfa9a8a5 New Crowdin translations (#100)
* New translations strings.xml (French)

* New translations strings.xml (Afrikaans)

* New translations strings.xml (Japanese)

* New translations strings.xml (Ukrainian)

* New translations strings.xml (Turkish)

* New translations strings.xml (Swedish)

* New translations strings.xml (Spanish)

* New translations strings.xml (Serbian (Cyrillic))

* New translations strings.xml (Russian)

* New translations strings.xml (Romanian)

* New translations strings.xml (Portuguese, Brazilian)

* New translations strings.xml (Polish)

* New translations strings.xml (Norwegian)

* New translations strings.xml (Korean)

* New translations strings.xml (Italian)

* New translations strings.xml (Arabic)

* New translations strings.xml (Hungarian)

* New translations strings.xml (Hebrew)

* New translations strings.xml (Greek)

* New translations strings.xml (German)

* New translations strings.xml (French)

* New translations strings.xml (Finnish)

* New translations strings.xml (Dutch)

* New translations strings.xml (Danish)

* New translations strings.xml (Czech)

* New translations strings.xml (Chinese Traditional)

* New translations strings.xml (Catalan)

* New translations strings.xml (Vietnamese)

* New translations strings.xml (Portuguese, Brazilian)

* New translations strings.xml (Portuguese, Brazilian)

* New translations strings.xml (Portuguese)

* New translations strings.xml (Portuguese, Brazilian)
2017-11-08 11:36:41 +01:00
8e25489cca Update CHANGELOG.md 2017-11-08 11:24:48 +01:00
198f95e1ca Update CHANGELOG.md 2017-11-08 11:24:40 +01:00
7e02fe89ea New Crowdin translations (#97)
* New translations strings.xml (French)

* New translations strings.xml (Afrikaans)

* New translations strings.xml (Japanese)

* New translations strings.xml (Ukrainian)

* New translations strings.xml (Turkish)

* New translations strings.xml (Swedish)

* New translations strings.xml (Spanish)

* New translations strings.xml (Serbian (Cyrillic))

* New translations strings.xml (Russian)

* New translations strings.xml (Romanian)

* New translations strings.xml (Portuguese, Brazilian)

* New translations strings.xml (Polish)

* New translations strings.xml (Norwegian)

* New translations strings.xml (Korean)

* New translations strings.xml (Italian)

* New translations strings.xml (Arabic)

* New translations strings.xml (Hungarian)

* New translations strings.xml (Hebrew)

* New translations strings.xml (Greek)

* New translations strings.xml (German)

* New translations strings.xml (French)

* New translations strings.xml (Finnish)

* New translations strings.xml (Dutch)

* New translations strings.xml (Danish)

* New translations strings.xml (Czech)

* New translations strings.xml (Chinese Traditional)

* New translations strings.xml (Catalan)

* New translations strings.xml (Vietnamese)
2017-11-04 11:57:30 +01:00
819356412c Optimizing imports. 2017-11-04 11:43:09 +01:00
deb789bc1b Some code cleaning. 2017-11-04 11:33:22 +01:00
133ba74548 Fixed changelog. 2017-11-04 10:59:13 +01:00
1461e32643 Update README.md 2017-11-02 10:11:19 +01:00
f400c3d9ac New translations strings.xml (French) (#96) 2017-11-02 09:42:22 +01:00
7e595a4f74 Reverted last commit 2017-11-02 09:39:46 +01:00
18c9c499b2 Delete crowdin.yml 2017-11-02 09:36:25 +01:00
24ae115ed4 New translations strings.xml (French) (#95) 2017-11-01 19:54:56 +01:00
7f345558cd Changelog. 2017-11-01 19:48:06 +01:00
57177cc910 Loading more on swipe. 2017-11-01 19:46:13 +01:00
cea258bc21 Fixes #45. User may need to reselect the theme. 2017-11-01 19:06:36 +01:00
ed9b1c8ba7 Only reporting the issue if there is an issue. 2017-11-01 18:13:54 +01:00
5a79fd89e9 Realy fixed the api call this time. 2017-10-29 21:11:03 +01:00
42a130db08 Changelog. 2017-10-29 20:18:35 +01:00
320a8d19de New translations strings.xml (French) (#94) 2017-10-29 20:14:52 +01:00
5721506007 Maybe fixed issue with marking items. 2017-10-29 20:10:02 +01:00
803e8cb2f4 Revert "This is causing bugs for Xperia XZ Premium device on pre-launch report."
This reverts commit 98492fd0c0.
2017-10-29 13:52:43 +01:00
84 changed files with 1198 additions and 805 deletions

View File

@ -10,7 +10,7 @@ Please read the guidelines before contributing, and follow them (or try to) when
There are many ways to contribute to this project, you could report bugs, request missing features, suggest enhancements and changes to existing ones. You also can improve the README with useful tips that could help the other users.
You can fork the repository, and [help me solve some issues](https://github.com/aminecmi/ReaderforSelfoss/labels/help%20wanted) or [develop new things](https://github.com/aminecmi/ReaderforSelfoss/issues)
You can fork the repository, and [help me solve some issues](https://github.com/aminecmi/ReaderforSelfoss/issues?q=is%3Aissue+is%3Aopen+label%3A%22Up+For+Grabs%22) or [develop new things](https://github.com/aminecmi/ReaderforSelfoss/issues)
### What I can't help you with.
@ -31,7 +31,7 @@ Always check if the web version of your instance is working.
* Please ask before starting to work on an issue. I may be working on it, or someone else could be doing so.
* Each pull request should implement **ONE** feature or bugfix. Keep in mind that you can submit as many PR as you want.
* Your code must be simple and clear enough to avoid using comments to explain what it does.
* Follow the used coding style [the official one](https://kotlinlang.org/docs/reference/coding-conventions.html) ([some idoms for reference](http://kotlinlang.org/docs/reference/idioms.html)) with more to come.
* Follow the used coding style [the android koding style](https://android.github.io/kotlin-guides/style.html) ([some idoms for reference](http://kotlinlang.org/docs/reference/idioms.html)) with more to come.
* Try as much as possible to write a test for your feature, and if you do so, run it, and make it work.
* Always check your changes and discard the ones that are irrelevant to your feature or bugfix.
* Have meaningful commit messages.

View File

@ -1,3 +1,49 @@
**1.5.4.10**
- Displaying a loader when "reading more" in the article viewer.
- Displaying the thumbnail instead of icon on the article viewer.
- Scrolling to top when loading content with the "read more" button.
**1.5.4.09**
- Using the kotlin wrapper for the material drawer (see #98 for more details).
- Updated support libraries
- Changed the Floating Action Button to the support library version.
- New reader activity action bar #103.
**1.5.4.08**
- Thanks @jrafaelsantana for translating the whole app in Brazilian Portuguese.
**1.5.4.07**
- Loading more items on swipe too.
- Fixed popup menu style. User may need to reselect the theme.
- Disabled reporting marking items as read if there isn't an issue.
**1.5.4.05/06**
- Translation fix.
**1.5.4.04**
- Fixing an issue with marking items as read (something related to an old version of selfoss).
**1.5.4.03**
- Trying to fix some issue with pre-launch reports. Reverted because it seems to be related to the dev console side.
**1.5.4.02**
- Fixing full height cards issue.
**1.5.4.01**
- Removed the "apk downloaded from outside of playstore" message.
@ -327,4 +373,4 @@ _Updates_
**1.3.3.4**
...
...

View File

@ -22,3 +22,5 @@ Check the [Contribution guide](https://github.com/aminecmi/ReaderforSelfoss/blob
- [Check what changed](https://github.com/aminecmi/ReaderforSelfoss/blob/master/CHANGELOG.md)
- [See what I'm doing](https://github.com/aminecmi/ReaderforSelfoss/projects/1)
- [Create an issue, or request a new feature](https://github.com/aminecmi/ReaderforSelfoss/issues)
- [Help translation the app](https://crowdin.com/project/readerforselfoss)
- [Ask for help](https://gitter.im/amine-bou/ReaderForSelfoss)

View File

@ -38,12 +38,12 @@ repositories {
}
android {
compileSdkVersion 26
buildToolsVersion '26.0.2'
compileSdkVersion 27
buildToolsVersion '27.0.0'
defaultConfig {
applicationId "apps.amine.bou.readerforselfoss"
minSdkVersion 16
targetSdkVersion 26
targetSdkVersion 27
versionCode versionCodeFromGit()
versionName versionNameFromGit()
@ -107,13 +107,13 @@ dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
// Android Support
compile 'com.android.support:appcompat-v7:26.1.0'
compile 'com.android.support:design:26.1.0'
compile 'com.android.support:recyclerview-v7:26.1.0'
compile 'com.android.support:support-v4:26.1.0'
compile 'com.android.support:support-vector-drawable:26.1.0'
compile 'com.android.support:customtabs:26.1.0'
compile 'com.android.support:cardview-v7:26.1.0'
compile 'com.android.support:appcompat-v7:27.0.0'
compile 'com.android.support:design:27.0.0'
compile 'com.android.support:recyclerview-v7:27.0.0'
compile 'com.android.support:support-v4:27.0.0'
compile 'com.android.support:support-vector-drawable:27.0.0'
compile 'com.android.support:customtabs:27.0.0'
compile 'com.android.support:cardview-v7:27.0.0'
compile 'com.android.support.constraint:constraint-layout:1.0.2'
// Firebase + crashlytics
@ -131,7 +131,7 @@ dependencies {
compile 'agency.tango.android:material-intro-screen:0.0.5'
// About
compile('com.mikepenz:aboutlibraries:5.9.7@aar') {
compile('com.mikepenz:aboutlibraries:6.0.0@aar') {
transitive = true
}
@ -143,7 +143,6 @@ dependencies {
// Material-ish things
compile 'com.ashokvarma.android:bottom-navigation-bar:2.0.3'
compile 'com.melnykov:floatingactionbutton:1.3.0'
compile 'com.github.jd-alexander:LikeButton:0.2.1'
compile 'com.amulyakhare:com.amulyakhare.textdrawable:1.0.1'
compile 'org.sufficientlysecure:html-textview:3.5'
@ -159,9 +158,7 @@ dependencies {
compile 'com.klinkerapps:drag-dismiss-activity:1.5.0'
// Drawer
compile('com.mikepenz:materialdrawer:5.9.5@aar') {
transitive = true
}
implementation 'co.zsmb:materialdrawer-kt:1.2.1'
compile 'com.anupcowkur:reservoir:3.1.0'
// Themes
@ -169,6 +166,8 @@ dependencies {
// Github issues reporter
compile 'com.heinrichreimersoftware:android-issue-reporter:1.3.1'
compile 'com.github.rubensousa:floatingtoolbar:1.5.1'
}
apply plugin: 'com.google.gms.google-services'

View File

@ -65,8 +65,7 @@
</intent-filter>
</activity>
<activity
android:name=".ReaderActivity"
android:theme="@style/DragDismissTheme">
android:name=".ReaderActivity">
</activity>
<meta-data

View File

@ -7,18 +7,23 @@ import android.support.constraint.ConstraintLayout
import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.Toolbar
import android.view.View
import android.widget.*
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import android.widget.AdapterView
import android.widget.ArrayAdapter
import android.widget.Button
import android.widget.EditText
import android.widget.ProgressBar
import android.widget.Spinner
import android.widget.TextView
import android.widget.Toast
import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi
import apps.amine.bou.readerforselfoss.api.selfoss.Spout
import apps.amine.bou.readerforselfoss.api.selfoss.SuccessResponse
import apps.amine.bou.readerforselfoss.utils.Config
import apps.amine.bou.readerforselfoss.utils.isBaseUrlValid
import com.ftinc.scoop.Scoop
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
class AddSourceActivity : AppCompatActivity() {
@ -50,17 +55,22 @@ class AddSourceActivity : AppCompatActivity() {
mustLoginToAddSource()
}
val intent = intent
if (Intent.ACTION_SEND == intent.action && "text/plain" == intent.type) {
mSourceUri.setText(intent.getStringExtra(Intent.EXTRA_TEXT))
mNameInput.setText(intent.getStringExtra(Intent.EXTRA_TITLE))
}
maybeGetDetailsFromIntentSharing(intent, mSourceUri, mNameInput)
mSaveBtn.setOnClickListener {
handleSaveSource(mTags, mNameInput.text.toString(), mSourceUri.text.toString(), api!!)
}
val config = Config(this)
if (config.baseUrl.isEmpty() || !config.baseUrl.isBaseUrlValid()) {
mustLoginToAddSource()
} else {
handleSpoutsSpinner(mSpoutsSpinner, api, mProgress, mForm)
}
}
private fun handleSpoutsSpinner(mSpoutsSpinner: Spinner, api: SelfossApi?, mProgress: ProgressBar, mForm: ConstraintLayout) {
val spoutsKV = HashMap<String, String>()
mSpoutsSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(adapterView: AdapterView<*>, view: View, i: Int, l: Long) {
@ -73,48 +83,48 @@ class AddSourceActivity : AppCompatActivity() {
}
}
val config = Config(this)
var items: Map<String, Spout>
api!!.spouts().enqueue(object : Callback<Map<String, Spout>> {
override fun onResponse(call: Call<Map<String, Spout>>, response: Response<Map<String, Spout>>) {
if (response.body() != null) {
items = response.body()!!
if (config.baseUrl.isEmpty() || !config.baseUrl.isBaseUrlValid()) {
mustLoginToAddSource()
} else {
var items: Map<String, Spout>
api!!.spouts().enqueue(object : Callback<Map<String, Spout>> {
override fun onResponse(call: Call<Map<String, Spout>>, response: Response<Map<String, Spout>>) {
if (response.body() != null) {
items = response.body()!!
val itemsStrings = items.map { it.value.name }
for ((key, value) in items) {
spoutsKV.put(value.name, key)
}
mProgress.visibility = View.GONE
mForm.visibility = View.VISIBLE
val spinnerArrayAdapter =
ArrayAdapter(
this@AddSourceActivity,
android.R.layout.simple_spinner_item,
itemsStrings)
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
mSpoutsSpinner.adapter = spinnerArrayAdapter
} else {
handleProblemWithSpouts()
val itemsStrings = items.map { it.value.name }
for ((key, value) in items) {
spoutsKV.put(value.name, key)
}
}
override fun onFailure(call: Call<Map<String, Spout>>, t: Throwable) {
mProgress.visibility = View.GONE
mForm.visibility = View.VISIBLE
val spinnerArrayAdapter =
ArrayAdapter(
this@AddSourceActivity,
android.R.layout.simple_spinner_item,
itemsStrings)
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
mSpoutsSpinner.adapter = spinnerArrayAdapter
} else {
handleProblemWithSpouts()
}
}
private fun handleProblemWithSpouts() {
Toast.makeText(this@AddSourceActivity, R.string.cant_get_spouts, Toast.LENGTH_SHORT).show()
mProgress.visibility = View.GONE
}
})
override fun onFailure(call: Call<Map<String, Spout>>, t: Throwable) {
handleProblemWithSpouts()
}
private fun handleProblemWithSpouts() {
Toast.makeText(this@AddSourceActivity, R.string.cant_get_spouts, Toast.LENGTH_SHORT).show()
mProgress.visibility = View.GONE
}
})
}
private fun maybeGetDetailsFromIntentSharing(intent: Intent, mSourceUri: EditText, mNameInput: EditText) {
if (Intent.ACTION_SEND == intent.action && "text/plain" == intent.type) {
mSourceUri.setText(intent.getStringExtra(Intent.EXTRA_TEXT))
mNameInput.setText(intent.getStringExtra(Intent.EXTRA_TITLE))
}
}
@ -127,7 +137,9 @@ class AddSourceActivity : AppCompatActivity() {
private fun handleSaveSource(mTags: EditText, title: String, url: String, api: SelfossApi) {
if (title.isEmpty() || url.isEmpty() || mSpoutsValue == null || mSpoutsValue!!.isEmpty()) {
val sourceDetailsAvailable = title.isEmpty() || url.isEmpty() || mSpoutsValue == null || mSpoutsValue!!.isEmpty()
if (sourceDetailsAvailable) {
Toast.makeText(this, R.string.form_not_complete, Toast.LENGTH_SHORT).show()
} else {
api.createSource(

View File

@ -1,7 +1,5 @@
package apps.amine.bou.readerforselfoss
import java.lang.Exception
import android.app.Activity
import android.content.Context
import android.content.Intent
@ -15,41 +13,25 @@ import android.support.design.widget.CoordinatorLayout
import android.support.v4.view.MenuItemCompat
import android.support.v4.widget.SwipeRefreshLayout
import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.*
import android.support.v7.widget.GridLayoutManager
import android.support.v7.widget.RecyclerView
import android.support.v7.widget.SearchView
import android.support.v7.widget.StaggeredGridLayoutManager
import android.support.v7.widget.Toolbar
import android.support.v7.widget.helper.ItemTouchHelper
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.widget.TextView
import android.widget.Toast
import com.anupcowkur.reservoir.Reservoir
import com.anupcowkur.reservoir.ReservoirGetCallback
import com.anupcowkur.reservoir.ReservoirPutCallback
import com.crashlytics.android.answers.Answers
import com.crashlytics.android.answers.InviteEvent
import com.github.stkent.amplify.prompt.DefaultLayoutPromptView
import com.github.stkent.amplify.tracking.Amplify
import com.google.android.gms.appinvite.AppInviteInvitation
import com.google.android.gms.common.ConnectionResult
import com.google.android.gms.common.GoogleApiAvailability
import com.google.firebase.remoteconfig.FirebaseRemoteConfig
import com.google.gson.reflect.TypeToken
import com.mikepenz.aboutlibraries.Libs
import com.mikepenz.aboutlibraries.LibsBuilder
import com.mikepenz.materialdrawer.Drawer
import com.mikepenz.materialdrawer.DrawerBuilder
import com.mikepenz.materialdrawer.holder.BadgeStyle
import com.mikepenz.materialdrawer.model.DividerDrawerItem
import com.mikepenz.materialdrawer.model.PrimaryDrawerItem
import com.mikepenz.materialdrawer.model.SecondaryDrawerItem
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import apps.amine.bou.readerforselfoss.adapters.ItemCardAdapter
import apps.amine.bou.readerforselfoss.adapters.ItemListAdapter
import apps.amine.bou.readerforselfoss.api.selfoss.*
import apps.amine.bou.readerforselfoss.api.selfoss.Item
import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi
import apps.amine.bou.readerforselfoss.api.selfoss.Sources
import apps.amine.bou.readerforselfoss.api.selfoss.Stats
import apps.amine.bou.readerforselfoss.api.selfoss.SuccessResponse
import apps.amine.bou.readerforselfoss.api.selfoss.Tag
import apps.amine.bou.readerforselfoss.settings.SettingsActivity
import apps.amine.bou.readerforselfoss.themes.AppColors
import apps.amine.bou.readerforselfoss.utils.Config
@ -59,15 +41,39 @@ import apps.amine.bou.readerforselfoss.utils.checkApkVersion
import apps.amine.bou.readerforselfoss.utils.customtabs.CustomTabActivityHelper
import apps.amine.bou.readerforselfoss.utils.drawer.CustomUrlPrimaryDrawerItem
import apps.amine.bou.readerforselfoss.utils.longHash
import co.zsmb.materialdrawerkt.builders.accountHeader
import co.zsmb.materialdrawerkt.builders.drawer
import co.zsmb.materialdrawerkt.builders.footer
import co.zsmb.materialdrawerkt.draweritems.badgeable.primaryItem
import co.zsmb.materialdrawerkt.draweritems.profile.profile
import com.anupcowkur.reservoir.Reservoir
import com.anupcowkur.reservoir.ReservoirGetCallback
import com.anupcowkur.reservoir.ReservoirPutCallback
import com.ashokvarma.bottomnavigation.BottomNavigationBar
import com.ashokvarma.bottomnavigation.BottomNavigationItem
import com.ashokvarma.bottomnavigation.TextBadgeItem
import com.crashlytics.android.Crashlytics
import com.crashlytics.android.answers.Answers
import com.crashlytics.android.answers.InviteEvent
import com.ftinc.scoop.Scoop
import com.github.stkent.amplify.prompt.DefaultLayoutPromptView
import com.github.stkent.amplify.tracking.Amplify
import com.google.android.gms.appinvite.AppInviteInvitation
import com.google.android.gms.common.ConnectionResult
import com.google.android.gms.common.GoogleApiAvailability
import com.google.firebase.remoteconfig.FirebaseRemoteConfig
import com.google.gson.reflect.TypeToken
import com.heinrichreimersoftware.androidissuereporter.IssueReporterLauncher
import com.mikepenz.materialdrawer.AccountHeader
import com.mikepenz.materialdrawer.AccountHeaderBuilder
import com.mikepenz.materialdrawer.model.ProfileDrawerItem
import com.mikepenz.aboutlibraries.Libs
import com.mikepenz.aboutlibraries.LibsBuilder
import com.mikepenz.materialdrawer.Drawer
import com.mikepenz.materialdrawer.holder.BadgeStyle
import com.mikepenz.materialdrawer.model.DividerDrawerItem
import com.mikepenz.materialdrawer.model.PrimaryDrawerItem
import com.mikepenz.materialdrawer.model.SecondaryDrawerItem
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
@ -107,7 +113,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
private lateinit var tabNewBadge: TextBadgeItem
private lateinit var tabArchiveBadge: TextBadgeItem
private lateinit var tabStarredBadge: TextBadgeItem
private lateinit var toolbar: Toolbar
private lateinit var toolBar: Toolbar
private lateinit var drawer: Drawer
private lateinit var api: SelfossApi
private lateinit var customTabActivityHelper: CustomTabActivityHelper
@ -139,8 +145,8 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
setContentView(R.layout.activity_home)
toolbar = findViewById(R.id.toolbar)
setSupportActionBar(toolbar)
toolBar = findViewById(R.id.toolbar)
setSupportActionBar(toolBar)
if (savedInstanceState == null) {
val promptView: DefaultLayoutPromptView = findViewById(R.id.prompt_view)
@ -172,6 +178,10 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
reloadLayoutManager()
handleSwipeRefreshLayout()
}
private fun handleSwipeRefreshLayout() {
swipeRefreshLayout.setColorSchemeResources(
R.color.refresh_progress_1,
R.color.refresh_progress_2,
@ -189,7 +199,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
override fun onMove(recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder): Boolean = false
target: RecyclerView.ViewHolder): Boolean = false
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, swipeDir: Int) {
try {
@ -207,7 +217,23 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
else
tabNewBadge.hide()
} catch (e: IndexOutOfBoundsException) {}
val manager = recyclerView.layoutManager
val lastVisibleItem: Int = when (manager) {
is StaggeredGridLayoutManager -> manager.findLastCompletelyVisibleItemPositions(null).last()
is GridLayoutManager -> manager.findLastCompletelyVisibleItemPosition()
else -> 0
}
if (lastVisibleItem == (items.size - 1)) {
getElementsAccordingToTab(appendResults = true)
}
} catch (e: IndexOutOfBoundsException) {
Crashlytics.setUserIdentifier(userIdentifier)
Crashlytics.log(100, "SWIPE_INDEX_OUT_OF_BOUND", "IndexOutOfBoundsException when swiping")
Crashlytics.logException(e)
}
}
}
@ -304,86 +330,68 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
private fun handleDrawer() {
displayAccountHeader =
PreferenceManager.getDefaultSharedPreferences(this)
.getBoolean("account_header_displaying", false)
val headerResult: AccountHeader? = if (displayAccountHeader) {
AccountHeaderBuilder()
.withActivity(this)
.withHeaderBackground(R.drawable.bg)
.addProfiles(
ProfileDrawerItem()
.withName(
settings.getString("url", "")
PreferenceManager.getDefaultSharedPreferences(this)
.getBoolean("account_header_displaying", false)
drawer = drawer {
rootViewRes = R.id.drawer_layout
toolbar = toolBar
actionBarDrawerToggleEnabled = true
actionBarDrawerToggleAnimated = true
showOnFirstLaunch = true
onSlide { _, p1 ->
bottomBar.alpha = (1 - p1)
}
onClosed {
bottomBar.show()
}
onOpened {
bottomBar.hide()
}
if (displayAccountHeader)
accountHeader {
background = R.drawable.bg
profile(settings.getString("url", "")) {
iconDrawable = resources.getDrawable(R.mipmap.ic_launcher)
}
selectionListEnabledForSingleProfile = false
}
footer {
primaryItem(R.string.drawer_report_bug) {
icon = R.drawable.ic_bug_report
iconTintingEnabled = true
onClick { _ ->
IssueReporterLauncher.forTarget(getString(R.string.report_github_user), getString(R.string.report_github_repo))
.theme(R.style.Theme_App_Light)
.guestToken(BuildConfig.GITHUB_TOKEN)
.guestEmailRequired(true)
.minDescriptionLength(20)
.putExtraInfo("Unique ID", settings.getString("unique_id", ""))
.putExtraInfo("From github", BuildConfig.GITHUB_VERSION)
.homeAsUpEnabled(true)
.launch(this@HomeActivity)
false
}
}
primaryItem(R.string.title_activity_settings) {
icon = R.drawable.ic_settings
iconTintingEnabled = true
onClick { _ ->
startActivityForResult(
Intent(
this@HomeActivity,
SettingsActivity::class.java
),
MENU_PREFERENCES
)
.withIcon(resources.getDrawable(R.mipmap.ic_launcher))
)
.withSelectionListEnabledForSingleProfile(false)
.build()
} else null
val drawerBuilder =
DrawerBuilder()
.withActivity(this)
.withRootView(R.id.drawer_layout)
.withToolbar(toolbar)
.withActionBarDrawerToggle(true)
.withActionBarDrawerToggleAnimated(true)
.withShowDrawerOnFirstLaunch(true)
.withOnDrawerListener(object: Drawer.OnDrawerListener {
override fun onDrawerSlide(v: View?, p1: Float) {
bottomBar.alpha = (1 - p1)
false
}
override fun onDrawerClosed(v: View?) {
bottomBar.show()
}
override fun onDrawerOpened(v: View?) {
bottomBar.hide()
}
})
if (displayAccountHeader && headerResult != null)
drawerBuilder.withAccountHeader(headerResult)
drawer = drawerBuilder.build()
drawer.addStickyFooterItem(
PrimaryDrawerItem()
.withName(R.string.drawer_report_bug)
.withIcon(R.drawable.ic_bug_report)
.withIconTintingEnabled(true)
.withOnDrawerItemClickListener { _, _, _ ->
IssueReporterLauncher.forTarget(getString(R.string.report_github_user), getString(R.string.report_github_repo))
.theme(R.style.Theme_App_Light)
.guestToken(BuildConfig.GITHUB_TOKEN)
.guestEmailRequired(true)
.minDescriptionLength(20)
.putExtraInfo("Unique ID", settings.getString("unique_id", ""))
.putExtraInfo("From github", BuildConfig.GITHUB_VERSION)
.homeAsUpEnabled(true)
.launch(this)
false
}
)
drawer.addStickyFooterItem(
PrimaryDrawerItem()
.withName(R.string.title_activity_settings)
.withIcon(R.drawable.ic_settings)
.withIconTintingEnabled(true)
.withOnDrawerItemClickListener { _, _, _ ->
startActivityForResult(
Intent(
this@HomeActivity,
SettingsActivity::class.java
),
MENU_PREFERENCES
)
false
}
)
}
}
}
@ -392,10 +400,11 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
fun handleTags(maybeTags: List<Tag>?) {
if (maybeTags == null) {
if (loadedFromCache)
drawer.addItem(
SecondaryDrawerItem()
.withName(getString(R.string.drawer_error_loading_tags))
.withSelectable(false))
SecondaryDrawerItem()
.withName(getString(R.string.drawer_error_loading_tags))
.withSelectable(false))
}
else {
for (tag in maybeTags) {
@ -405,20 +414,20 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
gd.setSize(30, 30)
gd.cornerRadius = 30F
drawer.addItem(
PrimaryDrawerItem()
.withName(tag.tag)
.withIdentifier(tag.tag.longHash())
.withIcon(gd)
.withBadge("${tag.unread}")
.withBadgeStyle(
BadgeStyle().withTextColor(Color.WHITE)
.withColor(appColors.accent)
)
.withOnDrawerItemClickListener { _, _, _ ->
maybeTagFilter = tag
getElementsAccordingToTab()
false
}
PrimaryDrawerItem()
.withName(tag.tag)
.withIdentifier(tag.tag.longHash())
.withIcon(gd)
.withBadge("${tag.unread}")
.withBadgeStyle(
BadgeStyle().withTextColor(Color.WHITE)
.withColor(appColors.accent)
)
.withOnDrawerItemClickListener { _, _, _ ->
maybeTagFilter = tag
getElementsAccordingToTab()
false
}
)
}
}
@ -429,22 +438,22 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
if (maybeSources == null) {
if (loadedFromCache)
drawer.addItem(
SecondaryDrawerItem()
.withName(getString(R.string.drawer_error_loading_sources))
.withSelectable(false))
SecondaryDrawerItem()
.withName(getString(R.string.drawer_error_loading_sources))
.withSelectable(false))
}
else
for (tag in maybeSources)
drawer.addItem(
CustomUrlPrimaryDrawerItem()
.withName(tag.title)
.withIdentifier(tag.id.toLong())
.withIcon(tag.getIcon(this@HomeActivity))
.withOnDrawerItemClickListener { _, _, _ ->
maybeSourceFilter = tag
getElementsAccordingToTab()
false
}
CustomUrlPrimaryDrawerItem()
.withName(tag.title)
.withIdentifier(tag.id.toLong())
.withIcon(tag.getIcon(this@HomeActivity))
.withOnDrawerItemClickListener { _, _, _ ->
maybeSourceFilter = tag
getElementsAccordingToTab()
false
}
)
}
@ -452,58 +461,58 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
drawer.removeAllItems()
if (maybeDrawerData != null) {
drawer.addItem(
SecondaryDrawerItem()
.withName(getString(R.string.drawer_item_filters))
.withSelectable(false)
.withIdentifier(DRAWER_ID_FILTERS)
.withBadge(getString(R.string.drawer_action_clear))
.withOnDrawerItemClickListener { _, _, _ ->
maybeSourceFilter = null
maybeTagFilter = null
getElementsAccordingToTab()
false
}
SecondaryDrawerItem()
.withName(getString(R.string.drawer_item_filters))
.withSelectable(false)
.withIdentifier(DRAWER_ID_FILTERS)
.withBadge(getString(R.string.drawer_action_clear))
.withOnDrawerItemClickListener { _, _, _ ->
maybeSourceFilter = null
maybeTagFilter = null
getElementsAccordingToTab()
false
}
)
drawer.addItem(DividerDrawerItem())
drawer.addItem(
SecondaryDrawerItem()
.withName(getString(R.string.drawer_item_tags))
.withIdentifier(DRAWER_ID_TAGS)
.withSelectable(false))
SecondaryDrawerItem()
.withName(getString(R.string.drawer_item_tags))
.withIdentifier(DRAWER_ID_TAGS)
.withSelectable(false))
handleTags(maybeDrawerData.tags)
drawer.addItem(DividerDrawerItem())
drawer.addItem(
SecondaryDrawerItem()
.withName(getString(R.string.drawer_item_sources))
.withIdentifier(DRAWER_ID_TAGS)
.withBadge(getString(R.string.drawer_action_edit))
.withSelectable(false)
.withOnDrawerItemClickListener { _, _, _ ->
startActivity(Intent(this, SourcesActivity::class.java))
false
}
SecondaryDrawerItem()
.withName(getString(R.string.drawer_item_sources))
.withIdentifier(DRAWER_ID_TAGS)
.withBadge(getString(R.string.drawer_action_edit))
.withSelectable(false)
.withOnDrawerItemClickListener { _, _, _ ->
startActivity(Intent(this, SourcesActivity::class.java))
false
}
)
handleSources(maybeDrawerData.sources)
drawer.addItem(DividerDrawerItem())
drawer.addItem(
PrimaryDrawerItem()
.withName(R.string.action_about)
.withSelectable(false)
.withIcon(R.drawable.ic_info_outline)
.withIconTintingEnabled(true)
.withOnDrawerItemClickListener { _, _, _ ->
LibsBuilder()
.withActivityStyle(
if (appColors.isDarkTheme)
Libs.ActivityStyle.LIGHT_DARK_TOOLBAR
else
Libs.ActivityStyle.DARK
)
.withAboutIconShown(true)
.withAboutVersionShown(true)
.start(this@HomeActivity)
false
})
PrimaryDrawerItem()
.withName(R.string.action_about)
.withSelectable(false)
.withIcon(R.drawable.ic_info_outline)
.withIconTintingEnabled(true)
.withOnDrawerItemClickListener { _, _, _ ->
LibsBuilder()
.withActivityStyle(
if (appColors.isDarkTheme)
Libs.ActivityStyle.LIGHT_DARK_TOOLBAR
else
Libs.ActivityStyle.DARK
)
.withAboutIconShown(true)
.withAboutVersionShown(true)
.start(this@HomeActivity)
false
})
if (!loadedFromCache)
@ -517,15 +526,15 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
} else {
if (!loadedFromCache) {
drawer.addItem(
PrimaryDrawerItem()
.withName(getString(R.string.no_tags_loaded))
.withIdentifier(DRAWER_ID_TAGS)
.withSelectable(false))
PrimaryDrawerItem()
.withName(getString(R.string.no_tags_loaded))
.withIdentifier(DRAWER_ID_TAGS)
.withSelectable(false))
drawer.addItem(
PrimaryDrawerItem()
.withName(getString(R.string.no_sources_loaded))
.withIdentifier(DRAWER_ID_SOURCES)
.withSelectable(false))
PrimaryDrawerItem()
.withName(getString(R.string.no_sources_loaded))
.withIdentifier(DRAWER_ID_SOURCES)
.withSelectable(false))
}
}
@ -566,7 +575,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
drawer.addItem(PrimaryDrawerItem().withName(getString(R.string.drawer_loading)).withSelectable(false))
val resultType = object : TypeToken<DrawerData>() {}.type
val resultType = object : TypeToken<DrawerData>() {}.type //NOSONAR
Reservoir.getAsync("drawerData", resultType, object: ReservoirGetCallback<DrawerData> {
override fun onSuccess(maybeDrawerData: DrawerData?) {
handleDrawerData(maybeDrawerData, loadedFromCache = true)
@ -593,31 +602,14 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
recyclerView.setHasFixedSize(true)
if (infiniteScroll) {
if (recyclerViewScrollListener == null)
recyclerViewScrollListener = object: RecyclerView.OnScrollListener() {
override fun onScrolled(localRecycler: RecyclerView?, dx: Int, dy: Int) {
if (dy > 0) {
if (localRecycler != null) {
val manager = recyclerView.layoutManager
val lastVisibleItem: Int = when (manager) {
is StaggeredGridLayoutManager -> manager.findLastCompletelyVisibleItemPositions(null).last()
is GridLayoutManager -> manager.findLastCompletelyVisibleItemPosition()
else -> 0
}
if (lastVisibleItem == (items.size - 1)) {
getElementsAccordingToTab(appendResults = true)
}
}
}
}
}
recyclerView.clearOnScrollListeners()
recyclerView.addOnScrollListener(recyclerViewScrollListener)
handleInfiniteScroll()
}
bottomBar.setTabSelectedListener(object: BottomNavigationBar.OnTabSelectedListener {
handleBottomBarActions(mLayoutManager)
}
private fun handleBottomBarActions(mLayoutManager: RecyclerView.LayoutManager) {
bottomBar.setTabSelectedListener(object : BottomNavigationBar.OnTabSelectedListener {
override fun onTabUnselected(position: Int) = Unit
override fun onTabReselected(position: Int) =
@ -638,7 +630,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
}
override fun onTabSelected(position: Int) =
when(position) {
when (position) {
0 -> getUnRead()
1 -> getRead()
2 -> getStarred()
@ -648,6 +640,29 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
})
}
private fun handleInfiniteScroll() {
if (recyclerViewScrollListener == null)
recyclerViewScrollListener = object : RecyclerView.OnScrollListener() {
override fun onScrolled(localRecycler: RecyclerView?, dx: Int, dy: Int) {
if (localRecycler != null && dy > 0) {
val manager = recyclerView.layoutManager
val lastVisibleItem: Int = when (manager) {
is StaggeredGridLayoutManager -> manager.findLastCompletelyVisibleItemPositions(null).last()
is GridLayoutManager -> manager.findLastCompletelyVisibleItemPosition()
else -> 0
}
if (lastVisibleItem == (items.size - 1)) {
getElementsAccordingToTab(appendResults = true)
}
}
}
}
recyclerView.clearOnScrollListeners()
recyclerView.addOnScrollListener(recyclerViewScrollListener)
}
fun mayBeEmpty() =
if (items.isEmpty()) {
emptyText.visibility = View.VISIBLE

View File

@ -1,15 +1,14 @@
package apps.amine.bou.readerforselfoss
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.preference.PreferenceManager
import android.view.View
import agency.tango.materialintroscreen.MaterialIntroActivity
import agency.tango.materialintroscreen.MessageButtonBehaviour
import agency.tango.materialintroscreen.SlideFragmentBuilder
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.preference.PreferenceManager
import android.support.v7.app.AppCompatDelegate
import android.view.View
class IntroActivity : MaterialIntroActivity() {

View File

@ -2,7 +2,6 @@ package apps.amine.bou.readerforselfoss
import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.app.ActivityManager
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
@ -16,7 +15,11 @@ import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.view.inputmethod.EditorInfo
import android.widget.*
import android.widget.Button
import android.widget.EditText
import android.widget.Switch
import android.widget.TextView
import android.widget.Toast
import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi
import apps.amine.bou.readerforselfoss.api.selfoss.SuccessResponse
import apps.amine.bou.readerforselfoss.utils.Config
@ -61,16 +64,7 @@ class LoginActivity : AppCompatActivity() {
val toolbar: Toolbar = findViewById(R.id.toolbar)
setSupportActionBar(toolbar)
if (intent.getBooleanExtra("baseUrlFail", false)) {
val alertDialog = AlertDialog.Builder(this).create()
alertDialog.setTitle(getString(R.string.warning_wrong_url))
alertDialog.setMessage(getString(R.string.base_url_error))
alertDialog.setButton(
AlertDialog.BUTTON_NEUTRAL,
"OK",
{ dialog, _ -> dialog.dismiss() })
alertDialog.show()
}
handleBaseUrlFail()
settings = getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE)
@ -92,6 +86,10 @@ class LoginActivity : AppCompatActivity() {
mLoginFormView = findViewById(R.id.login_form)
mProgressView = findViewById(R.id.login_progress)
handleActions()
}
private fun handleActions() {
val mSwitch: Switch = findViewById(R.id.withLogin)
val mHTTPSwitch: Switch = findViewById(R.id.withHttpLogin)
val mLoginLayout: TextInputLayout = findViewById(R.id.loginLayout)
@ -102,7 +100,7 @@ class LoginActivity : AppCompatActivity() {
val selfHostedSwitch: Switch = findViewById(R.id.withSelfhostedCert)
val warningTextview: TextView = findViewById(R.id.warningText)
selfHostedSwitch.setOnCheckedChangeListener {_, b ->
selfHostedSwitch.setOnCheckedChangeListener { _, b ->
isWithSelfSignedCert = !isWithSelfSignedCert
val visi: Int = if (b) View.VISIBLE else View.GONE
@ -136,6 +134,19 @@ class LoginActivity : AppCompatActivity() {
}
}
private fun handleBaseUrlFail() {
if (intent.getBooleanExtra("baseUrlFail", false)) {
val alertDialog = AlertDialog.Builder(this).create()
alertDialog.setTitle(getString(R.string.warning_wrong_url))
alertDialog.setMessage(getString(R.string.base_url_error))
alertDialog.setButton(
AlertDialog.BUTTON_NEUTRAL,
"OK",
{ dialog, _ -> dialog.dismiss() })
alertDialog.show()
}
}
private fun goToMain() {
val intent = Intent(this, HomeActivity::class.java)
startActivity(intent)
@ -245,9 +256,7 @@ class LoginActivity : AppCompatActivity() {
}
}
/**
* Shows the progress UI and hides the login form.
*/
private fun showProgress(show: Boolean) {
val shortAnimTime = resources.getInteger(android.R.integer.config_shortAnimTime)
@ -285,15 +294,11 @@ class LoginActivity : AppCompatActivity() {
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.about -> {
if (!ActivityManager.isUserAMonkey()){
LibsBuilder()
.withActivityStyle(Libs.ActivityStyle.LIGHT_DARK_TOOLBAR)
.withAboutIconShown(true)
.withAboutVersionShown(true)
.start(this)
} else {
Toast.makeText(this@LoginActivity, "You may be a bot", Toast.LENGTH_SHORT).show()
}
LibsBuilder()
.withActivityStyle(Libs.ActivityStyle.LIGHT_DARK_TOOLBAR)
.withAboutIconShown(true)
.withAboutVersionShown(true)
.start(this)
return true
}
R.id.loging_debug -> {

View File

@ -1,114 +1,194 @@
package apps.amine.bou.readerforselfoss
import android.content.SharedPreferences
import android.os.Bundle
import android.preference.PreferenceManager
import android.view.LayoutInflater
import android.support.customtabs.CustomTabsIntent
import android.support.design.widget.FloatingActionButton
import android.support.v4.widget.NestedScrollView
import android.support.v7.app.AppCompatActivity
import android.text.Html
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import android.widget.ImageButton
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.ProgressBar
import android.widget.TextView
import apps.amine.bou.readerforselfoss.api.mercury.MercuryApi
import apps.amine.bou.readerforselfoss.api.mercury.ParsedContent
import apps.amine.bou.readerforselfoss.utils.buildCustomTabsIntent
import apps.amine.bou.readerforselfoss.utils.customtabs.CustomTabActivityHelper
import apps.amine.bou.readerforselfoss.utils.isEmptyOrNullOrNullString
import apps.amine.bou.readerforselfoss.utils.openItemUrl
import apps.amine.bou.readerforselfoss.utils.shareLink
import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions
import com.crashlytics.android.Crashlytics
import com.ftinc.scoop.Scoop
import com.github.rubensousa.floatingtoolbar.FloatingToolbar
import org.sufficientlysecure.htmltextview.HtmlHttpImageGetter
import org.sufficientlysecure.htmltextview.HtmlTextView
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import xyz.klinker.android.drag_dismiss.activity.DragDismissActivity
class ReaderActivity : DragDismissActivity() {
class ReaderActivity : AppCompatActivity() {
private lateinit var mCustomTabActivityHelper: CustomTabActivityHelper
private lateinit var image: ImageView
private lateinit var source: TextView
private lateinit var title: TextView
private lateinit var content: TextView
private lateinit var progress: FrameLayout
private lateinit var nestedScrollView: NestedScrollView
//private lateinit var content: HtmlTextView
private lateinit var url: String
private lateinit var contentText: String
private lateinit var contentSource: String
private lateinit var contentImage: String
private lateinit var contentTitle: String
private lateinit var fab: FloatingActionButton
override fun onStart() {
super.onStart()
mCustomTabActivityHelper.bindCustomTabsService(this)
}
override fun onStop() {
super.onStop()
mCustomTabActivityHelper.unbindCustomTabsService(this)
}
override fun onCreateContent(inflater: LayoutInflater, parent: ViewGroup, savedInstanceState: Bundle?): View {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Scoop.getInstance().apply(this)
val v = inflater.inflate(R.layout.activity_reader, parent, false)
showProgressBar()
val prefs = PreferenceManager.getDefaultSharedPreferences(this)
setContentView(R.layout.activity_reader)
val image: ImageView = v.findViewById(R.id.imageView)
val source: TextView = v.findViewById(R.id.source)
val title: TextView = v.findViewById(R.id.title)
val content: HtmlTextView = v.findViewById(R.id.content)
val url = intent.getStringExtra("url")
val parser = MercuryApi(BuildConfig.MERCURY_KEY, prefs.getBoolean("should_log_everything", false))
val browserBtn: ImageButton = v.findViewById(R.id.browserBtn)
val shareBtn: ImageButton = v.findViewById(R.id.shareBtn)
image = findViewById(R.id.imageView)
source = findViewById(R.id.source)
title = findViewById(R.id.title)
content = findViewById(R.id.content)
progress = findViewById(R.id.progressBar)
nestedScrollView = findViewById(R.id.nestedScrollView)
url = intent.getStringExtra("url")
contentText = intent.getStringExtra("content")
contentTitle = intent.getStringExtra("title")
contentImage = intent.getStringExtra("image")
contentSource = intent.getStringExtra("source")
fab = findViewById(R.id.fab)
val mFloatingToolbar: FloatingToolbar = findViewById(R.id.floatingToolbar)
mFloatingToolbar.attachFab(fab)
val customTabsIntent = this@ReaderActivity.buildCustomTabsIntent()
mCustomTabActivityHelper = CustomTabActivityHelper()
mCustomTabActivityHelper.bindCustomTabsService(this)
val prefs = PreferenceManager.getDefaultSharedPreferences(this)
mFloatingToolbar.setClickListener(object : FloatingToolbar.ItemClickListener {
override fun onItemClick(item: MenuItem) {
when (item.itemId) {
R.id.more_action -> getContentFromMercury(customTabsIntent, prefs)
R.id.share_action -> this@ReaderActivity.shareLink(url)
R.id.open_action -> this@ReaderActivity.openItemUrl(
url,
contentText,
contentImage,
contentTitle,
contentSource,
customTabsIntent,
false,
false,
this@ReaderActivity)
else -> Unit
}
}
override fun onItemLongClick(item: MenuItem?) {
}
})
if (contentText.isEmptyOrNullOrNullString()) {
getContentFromMercury(customTabsIntent, prefs)
} else {
source.text = contentSource
title.text = contentTitle
tryToHandleHtml(contentText, customTabsIntent, prefs)
if (!contentImage.isEmptyOrNullOrNullString()) {
image.visibility = View.VISIBLE
Glide
.with(baseContext)
.asBitmap()
.load(contentImage)
.apply(RequestOptions.fitCenterTransform())
.into(image)
} else {
image.visibility = View.GONE
}
}
}
private fun getContentFromMercury(customTabsIntent: CustomTabsIntent, prefs: SharedPreferences) {
progress.visibility = View.VISIBLE
val parser = MercuryApi(BuildConfig.MERCURY_KEY, prefs.getBoolean("should_log_everything", false))
parser.parseUrl(url).enqueue(object : Callback<ParsedContent> {
override fun onResponse(call: Call<ParsedContent>, response: Response<ParsedContent>) {
if (response.body() != null && response.body()!!.content != null && response.body()!!.content.isNotEmpty()) {
source.text = response.body()!!.domain
title.text = response.body()!!.title
this@ReaderActivity.url = response.body()!!.url
if (response.body()!!.content != null && !response.body()!!.content.isEmpty()) {
try {
content.setHtml(response.body()!!.content, HtmlHttpImageGetter(content, null, true))
} catch (e: IndexOutOfBoundsException) {
openInBrowserAfterFailing()
}
tryToHandleHtml(response.body()!!.content, customTabsIntent, prefs)
}
if (response.body()!!.lead_image_url != null && !response.body()!!.lead_image_url.isEmpty())
if (response.body()!!.lead_image_url != null && !response.body()!!.lead_image_url.isEmpty()) {
image.visibility = View.VISIBLE
Glide
.with(baseContext)
.asBitmap()
.load(response.body()!!.lead_image_url)
.apply(RequestOptions.fitCenterTransform())
.into(image)
shareBtn.setOnClickListener {
this@ReaderActivity.shareLink(response.body()!!.url)
.with(baseContext)
.asBitmap()
.load(response.body()!!.lead_image_url)
.apply(RequestOptions.fitCenterTransform())
.into(image)
} else {
image.visibility = View.GONE
}
browserBtn.setOnClickListener {
this@ReaderActivity.openItemUrl(
response.body()!!.url,
customTabsIntent,
false,
false,
this@ReaderActivity)
}
nestedScrollView.scrollTo(0, 0)
hideProgressBar()
} else openInBrowserAfterFailing()
progress.visibility = View.GONE
} else openInBrowserAfterFailing(customTabsIntent)
}
override fun onFailure(call: Call<ParsedContent>, t: Throwable) = openInBrowserAfterFailing()
private fun openInBrowserAfterFailing() {
this@ReaderActivity.openItemUrl(
url,
customTabsIntent,
true,
false,
this@ReaderActivity
)
finish()
}
override fun onFailure(call: Call<ParsedContent>, t: Throwable) = openInBrowserAfterFailing(customTabsIntent)
})
return v
}
private fun tryToHandleHtml(c: String, customTabsIntent: CustomTabsIntent, prefs: SharedPreferences) {
try {
content.text = Html.fromHtml(c, HtmlHttpImageGetter(content, null, true), null)
//content.setHtml(response.body()!!.content, HtmlHttpImageGetter(content, null, true))
} catch (e: Exception) {
Crashlytics.setUserIdentifier(prefs.getString("unique_id", ""))
Crashlytics.log(100, "CANT_TRANSFORM_TO_HTML", e.message)
Crashlytics.logException(e)
openInBrowserAfterFailing(customTabsIntent)
}
}
private fun openInBrowserAfterFailing(customTabsIntent: CustomTabsIntent) {
progress.visibility = View.GONE
this@ReaderActivity.openItemUrl(
url,
contentText,
contentImage,
contentTitle,
contentSource,
customTabsIntent,
true,
false,
this@ReaderActivity
)
finish()
}
}

View File

@ -3,21 +3,19 @@ package apps.amine.bou.readerforselfoss
import android.content.Intent
import android.os.Bundle
import android.preference.PreferenceManager
import android.support.design.widget.FloatingActionButton
import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView
import android.support.v7.widget.Toolbar
import android.widget.Toast
import com.melnykov.fab.FloatingActionButton
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import apps.amine.bou.readerforselfoss.adapters.SourcesListAdapter
import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi
import apps.amine.bou.readerforselfoss.api.selfoss.Sources
import com.ftinc.scoop.Scoop
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
class SourcesActivity : AppCompatActivity() {
@ -43,7 +41,6 @@ class SourcesActivity : AppCompatActivity() {
val api = SelfossApi(this, this@SourcesActivity, prefs.getBoolean("isSelfSignedCert", false), prefs.getBoolean("should_log_everything", false))
var items: ArrayList<Sources> = ArrayList()
mFab.attachToRecyclerView(mRecyclerView)
mRecyclerView.setHasFixedSize(true)
mRecyclerView.layoutManager = mLayoutManager

View File

@ -3,7 +3,6 @@ package apps.amine.bou.readerforselfoss.adapters
import android.app.Activity
import android.content.Context
import android.graphics.Color
import android.support.constraint.ConstraintLayout
import android.support.design.widget.Snackbar
import android.support.v7.widget.CardView
import android.support.v7.widget.RecyclerView
@ -15,28 +14,30 @@ import android.widget.ImageView
import android.widget.ImageView.ScaleType
import android.widget.TextView
import android.widget.Toast
import com.amulyakhare.textdrawable.TextDrawable
import com.amulyakhare.textdrawable.util.ColorGenerator
import com.bumptech.glide.Glide
import com.like.LikeButton
import com.like.OnLikeListener
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import apps.amine.bou.readerforselfoss.R
import apps.amine.bou.readerforselfoss.api.selfoss.Item
import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi
import apps.amine.bou.readerforselfoss.api.selfoss.SuccessResponse
import apps.amine.bou.readerforselfoss.themes.AppColors
import apps.amine.bou.readerforselfoss.utils.*
import apps.amine.bou.readerforselfoss.utils.buildCustomTabsIntent
import apps.amine.bou.readerforselfoss.utils.customtabs.CustomTabActivityHelper
import apps.amine.bou.readerforselfoss.utils.glide.bitmapCenterCrop
import apps.amine.bou.readerforselfoss.utils.glide.bitmapFitCenter
import apps.amine.bou.readerforselfoss.utils.glide.circularBitmapDrawable
import apps.amine.bou.readerforselfoss.utils.openInBrowserAsNewTask
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.toTextDrawableString
import com.amulyakhare.textdrawable.TextDrawable
import com.amulyakhare.textdrawable.util.ColorGenerator
import com.bumptech.glide.Glide
import com.crashlytics.android.Crashlytics
import kotlin.collections.ArrayList
import com.like.LikeButton
import com.like.OnLikeListener
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
class ItemCardAdapter(private val app: Activity,
private val items: ArrayList<Item>,
@ -76,10 +77,10 @@ class ItemCardAdapter(private val app: Activity,
val color = generator.getColor(itm.sourcetitle)
val drawable =
TextDrawable
.builder()
.round()
.build(itm.sourcetitle.toTextDrawableString(), color)
TextDrawable
.builder()
.round()
.build(itm.sourcetitle.toTextDrawableString(), color)
holder.sourceImage.setImageDrawable(drawable)
} else {
c.circularBitmapDrawable(itm.getIcon(c), holder.sourceImage)
@ -125,15 +126,15 @@ class ItemCardAdapter(private val app: Activity,
api.markItem(i.id).enqueue(object : Callback<SuccessResponse> {
override fun onResponse(call: Call<SuccessResponse>, response: Response<SuccessResponse>) {
if (debugReadingItems) {
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}"
"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}"
Crashlytics.setUserIdentifier(userIdentifier)
Crashlytics.log(100, "READ_DEBUG_SUCCESS", message)
Crashlytics.logException(Exception("Was success, but did it work ?"))
@ -228,10 +229,14 @@ class ItemCardAdapter(private val app: Activity,
mView.setOnClickListener {
c.openItemUrl(items[adapterPosition].getLinkDecoded(),
customTabsIntent,
internalBrowser,
articleViewer,
app)
items[adapterPosition].content,
items[adapterPosition].getThumbnail(c),
items[adapterPosition].title,
items[adapterPosition].sourceAndDateText(),
customTabsIntent,
internalBrowser,
articleViewer,
app)
}
}
}

View File

@ -12,26 +12,33 @@ import android.util.TypedValue
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.*
import android.widget.ImageButton
import android.widget.ImageView
import android.widget.RelativeLayout
import android.widget.TextView
import android.widget.Toast
import apps.amine.bou.readerforselfoss.R
import apps.amine.bou.readerforselfoss.api.selfoss.Item
import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi
import apps.amine.bou.readerforselfoss.api.selfoss.SuccessResponse
import apps.amine.bou.readerforselfoss.utils.buildCustomTabsIntent
import apps.amine.bou.readerforselfoss.utils.customtabs.CustomTabActivityHelper
import apps.amine.bou.readerforselfoss.utils.glide.bitmapCenterCrop
import apps.amine.bou.readerforselfoss.utils.glide.circularBitmapDrawable
import apps.amine.bou.readerforselfoss.utils.openInBrowserAsNewTask
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 com.amulyakhare.textdrawable.TextDrawable
import com.amulyakhare.textdrawable.util.ColorGenerator
import com.crashlytics.android.Crashlytics
import com.like.LikeButton
import com.like.OnLikeListener
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import java.util.*
import apps.amine.bou.readerforselfoss.R
import apps.amine.bou.readerforselfoss.api.selfoss.Item
import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi
import apps.amine.bou.readerforselfoss.api.selfoss.SuccessResponse
import apps.amine.bou.readerforselfoss.utils.*
import apps.amine.bou.readerforselfoss.utils.customtabs.CustomTabActivityHelper
import apps.amine.bou.readerforselfoss.utils.glide.bitmapCenterCrop
import apps.amine.bou.readerforselfoss.utils.glide.circularBitmapDrawable
import com.crashlytics.android.Crashlytics
import kotlin.collections.ArrayList
@ -65,8 +72,8 @@ class ItemListAdapter(private val app: Activity,
if (itm.getThumbnail(c).isEmpty()) {
val sizeInInt = 46
val sizeInDp = TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, sizeInInt.toFloat(), c.resources
.displayMetrics).toInt()
TypedValue.COMPLEX_UNIT_DIP, sizeInInt.toFloat(), c.resources
.displayMetrics).toInt()
val marginInInt = 16
val marginInDp = TypedValue.applyDimension(
@ -138,15 +145,15 @@ class ItemListAdapter(private val app: Activity,
api.markItem(i.id).enqueue(object : Callback<SuccessResponse> {
override fun onResponse(call: Call<SuccessResponse>, response: Response<SuccessResponse>) {
if (debugReadingItems) {
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}"
"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}"
Crashlytics.setUserIdentifier(userIdentifier)
Crashlytics.log(100, "READ_DEBUG_SUCCESS", message)
Crashlytics.logException(Exception("Was success, but did it work ?"))
@ -240,10 +247,14 @@ class ItemListAdapter(private val app: Activity,
if (!clickBehavior) {
mView.setOnClickListener {
c.openItemUrl(items[adapterPosition].getLinkDecoded(),
customTabsIntent,
internalBrowser,
articleViewer,
app)
items[adapterPosition].content,
items[adapterPosition].getThumbnail(c),
items[adapterPosition].title,
items[adapterPosition].sourceAndDateText(),
customTabsIntent,
internalBrowser,
articleViewer,
app)
}
mView.setOnLongClickListener {
actionBarShowHide()
@ -253,10 +264,14 @@ class ItemListAdapter(private val app: Activity,
mView.setOnClickListener { actionBarShowHide() }
mView.setOnLongClickListener {
c.openItemUrl(items[adapterPosition].getLinkDecoded(),
customTabsIntent,
internalBrowser,
articleViewer,
app)
items[adapterPosition].content,
items[adapterPosition].getThumbnail(c),
items[adapterPosition].title,
items[adapterPosition].sourceAndDateText(),
customTabsIntent,
internalBrowser,
articleViewer,
app)
true
}
}

View File

@ -10,19 +10,17 @@ import android.widget.Button
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import com.amulyakhare.textdrawable.TextDrawable
import com.amulyakhare.textdrawable.util.ColorGenerator
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import apps.amine.bou.readerforselfoss.R
import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi
import apps.amine.bou.readerforselfoss.api.selfoss.Sources
import apps.amine.bou.readerforselfoss.api.selfoss.SuccessResponse
import apps.amine.bou.readerforselfoss.utils.glide.circularBitmapDrawable
import apps.amine.bou.readerforselfoss.utils.toTextDrawableString
import com.amulyakhare.textdrawable.TextDrawable
import com.amulyakhare.textdrawable.util.ColorGenerator
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
class SourcesListAdapter(private val app: Activity,

View File

@ -1,12 +1,10 @@
package apps.amine.bou.readerforselfoss.api.selfoss
import java.lang.reflect.Type
import com.google.gson.JsonParseException
import com.google.gson.JsonDeserializationContext
import com.google.gson.JsonElement
import com.google.gson.JsonDeserializer
import com.google.gson.JsonElement
import com.google.gson.JsonParseException
import java.lang.reflect.Type
internal class BooleanTypeAdapter : JsonDeserializer<Boolean> {

View File

@ -2,8 +2,8 @@ package apps.amine.bou.readerforselfoss.api.selfoss
import android.app.Activity
import android.content.Context
import java.util.concurrent.ConcurrentHashMap
import apps.amine.bou.readerforselfoss.utils.Config
import apps.amine.bou.readerforselfoss.utils.getUnsafeHttpClient
import com.burgstaller.okhttp.AuthenticationCacheInterceptor
import com.burgstaller.okhttp.CachingAuthenticatorDecorator
import com.burgstaller.okhttp.DispatchingAuthenticator
@ -13,18 +13,13 @@ import com.burgstaller.okhttp.digest.Credentials
import com.burgstaller.okhttp.digest.DigestAuthenticator
import com.google.gson.GsonBuilder
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Call
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import apps.amine.bou.readerforselfoss.utils.Config
import apps.amine.bou.readerforselfoss.utils.getUnsafeHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import java.util.concurrent.ConcurrentHashMap
// codebeat:disable[ARITY,TOO_MANY_FUNCTIONS]
class SelfossApi(c: Context, callingActivity: Activity, isWithSelfSignedCert: Boolean, shouldLog: Boolean) {
private lateinit var service: SelfossService
@ -148,5 +143,3 @@ class SelfossApi(c: Context, callingActivity: Activity, isWithSelfSignedCert: Bo
service.createSource(title, url, spout, tags, filter, userName, password)
}
// codebeat:enable[ARITY,TOO_MANY_FUNCTIONS]

View File

@ -55,6 +55,7 @@ data class Sources(@SerializedName("id") val id: String,
data class Item(@SerializedName("id") val id: String,
@SerializedName("datetime") val datetime: String,
@SerializedName("title") val title: String,
@SerializedName("content") val content: String,
@SerializedName("unread") val unread: Boolean,
@SerializedName("starred") val starred: Boolean,
@SerializedName("thumbnail") val thumbnail: String,
@ -72,15 +73,16 @@ data class Item(@SerializedName("id") val id: String,
}
constructor(source: Parcel) : this(
id = source.readString(),
datetime = source.readString(),
title = source.readString(),
unread = 0.toByte() != source.readByte(),
starred = 0.toByte() != source.readByte(),
thumbnail = source.readString(),
icon = source.readString(),
link = source.readString(),
sourcetitle = source.readString()
id = source.readString(),
datetime = source.readString(),
title = source.readString(),
content = source.readString(),
unread = 0.toByte() != source.readByte(),
starred = 0.toByte() != source.readByte(),
thumbnail = source.readString(),
icon = source.readString(),
link = source.readString(),
sourcetitle = source.readString()
)
override fun describeContents() = 0
@ -89,6 +91,7 @@ data class Item(@SerializedName("id") val id: String,
dest.writeString(id)
dest.writeString(datetime)
dest.writeString(title)
dest.writeString(content)
dest.writeByte((if (unread) 1 else 0))
dest.writeByte((if (starred) 1 else 0))
dest.writeString(thumbnail)

View File

@ -5,17 +5,18 @@ import retrofit2.http.DELETE
import retrofit2.http.Field
import retrofit2.http.FormUrlEncoded
import retrofit2.http.GET
import retrofit2.http.Headers
import retrofit2.http.POST
import retrofit2.http.Path
import retrofit2.http.Query
// codebeat:disable[ARITY]
internal interface SelfossService {
@GET("login")
fun loginToSelfoss(@Query("username") username: String, @Query("password") password: String): Call<SuccessResponse>
@GET("items")
fun getItems(@Query("type") type: String,
@Query("tag") tag: String?,
@ -26,17 +27,21 @@ internal interface SelfossService {
@Query("items") items: Int,
@Query("offset") offset: Int): Call<List<Item>>
@Headers("Content-Type: application/x-www-form-urlencoded")
@POST("mark/{id}")
fun markAsRead(@Path("id") id: String,
@Query("username") username: String,
@Query("password") password: String): Call<SuccessResponse>
@Headers("Content-Type: application/x-www-form-urlencoded")
@POST("unmark/{id}")
fun unmarkAsRead(@Path("id") id: String,
@Query("username") username: String,
@Query("password") password: String): Call<SuccessResponse>
@FormUrlEncoded
@POST("mark")
fun markAllAsRead(@Field("ids[]") ids: List<String>,
@ -44,12 +49,14 @@ internal interface SelfossService {
@Query("password") password: String): Call<SuccessResponse>
@Headers("Content-Type: application/x-www-form-urlencoded")
@POST("starr/{id}")
fun starr(@Path("id") id: String,
@Query("username") username: String,
@Query("password") password: String): Call<SuccessResponse>
@Headers("Content-Type: application/x-www-form-urlencoded")
@POST("unstarr/{id}")
fun unstarr(@Path("id") id: String,
@Query("username") username: String,
@ -70,10 +77,12 @@ internal interface SelfossService {
fun update(@Query("username") username: String,
@Query("password") password: String): Call<String>
@GET("sources/spouts")
fun spouts(@Query("username") username: String,
@Query("password") password: String): Call<Map<String, Spout>>
@GET("sources/list")
fun sources(@Query("username") username: String,
@Query("password") password: String): Call<List<Sources>>
@ -84,6 +93,7 @@ internal interface SelfossService {
@Query("username") username: String,
@Query("password") password: String): Call<SuccessResponse>
@FormUrlEncoded
@POST("source")
fun createSource(@Field("title") title: String,
@ -94,4 +104,3 @@ internal interface SelfossService {
@Query("username") username: String,
@Query("password") password: String): Call<SuccessResponse>
}
// codebeat:disable[ARITY]

View File

@ -24,7 +24,7 @@ import com.ftinc.scoop.Scoop;
* A {@link PreferenceActivity} which implements and proxies the necessary calls
* to be used with AppCompat.
*/
public abstract class AppCompatPreferenceActivity extends PreferenceActivity {
public abstract class AppCompatPreferenceActivity extends PreferenceActivity { //NOSONAR
private AppCompatDelegate mDelegate;
@ -116,6 +116,7 @@ public abstract class AppCompatPreferenceActivity extends PreferenceActivity {
getDelegate().onDestroy();
}
@Override
public void invalidateOptionsMenu() {
getDelegate().invalidateOptionsMenu();
}

View File

@ -1,6 +1,8 @@
package apps.amine.bou.readerforselfoss.settings;
import java.util.List;
import android.annotation.TargetApi;
import android.content.ClipData;
import android.content.ClipboardManager;
@ -16,17 +18,15 @@ import android.preference.Preference;
import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceActivity;
import android.preference.SwitchPreference;
import android.support.v7.app.ActionBar;
import android.preference.PreferenceFragment;
import android.preference.PreferenceManager;
import android.preference.SwitchPreference;
import android.support.v7.app.ActionBar;
import android.text.InputFilter;
import android.text.Spanned;
import android.view.MenuItem;
import android.widget.Toast;
import java.util.List;
import apps.amine.bou.readerforselfoss.BuildConfig;
import apps.amine.bou.readerforselfoss.R;
import apps.amine.bou.readerforselfoss.utils.Config;
@ -44,7 +44,7 @@ import com.ftinc.scoop.ui.ScoopSettingsActivity;
* href="http://developer.android.com/guide/topics/ui/settings.html">Settings
* API Guide</a> for more information on developing a Settings UI.
*/
public class SettingsActivity extends AppCompatPreferenceActivity {
public class SettingsActivity extends AppCompatPreferenceActivity { //NOSONAR
/**
* A preference value change listener that updates the preference's summary
* to reflect its new value.
@ -126,6 +126,7 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
* This method stops fragment injection in malicious applications.
* Make sure to deny any unknown fragments here.
*/
@Override
protected boolean isValidFragment(String fragmentName) {
return PreferenceFragment.class.getName().equals(fragmentName)
|| GeneralPreferenceFragment.class.getName().equals(fragmentName)
@ -166,7 +167,9 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
int input = Integer.parseInt(dest.toString() + source.toString());
if (input <= 200 && input >0)
return null;
} catch (NumberFormatException nfe) { }
} catch (NumberFormatException nfe) {
Toast.makeText(getActivity(), R.string.items_number_should_be_number, Toast.LENGTH_LONG).show();
}
return "";
}
}

View File

@ -0,0 +1,7 @@
package apps.amine.bou.readerforselfoss.utils
import apps.amine.bou.readerforselfoss.api.selfoss.SuccessResponse
import retrofit2.Response
fun Response<SuccessResponse>.succeeded(): Boolean =
this.code() === 200 && this.body() != null && this.body()!!.isSuccess

View File

@ -5,11 +5,8 @@ import android.content.Intent
import android.content.SharedPreferences
import android.net.Uri
import android.support.v7.app.AlertDialog
import com.google.firebase.remoteconfig.FirebaseRemoteConfig
import apps.amine.bou.readerforselfoss.R
import apps.amine.bou.readerforselfoss.api.selfoss.Item
import com.google.firebase.remoteconfig.FirebaseRemoteConfig
fun String?.isEmptyOrNullOrNullString(): Boolean =

View File

@ -50,7 +50,49 @@ fun Context.buildCustomTabsIntent(): CustomTabsIntent {
return intentBuilder.build()
}
fun Context.openItemUrlInternally(linkDecoded: String,
content: String,
image: String,
title: String,
source: String,
customTabsIntent: CustomTabsIntent,
articleViewer: Boolean,
app: Activity) {
if (articleViewer) {
val intent = Intent(this, ReaderActivity::class.java)
/*DragDismissIntentBuilder(this)
.setFullscreenOnTablets(true) // defaults to false, tablets will have padding on each side
.setDragElasticity(DragDismissIntentBuilder.DragElasticity.NORMAL) // Larger elasticities will make it easier to dismiss.
.setDrawUnderStatusBar(true)
.build(intent)*/
intent.putExtra("url", linkDecoded)
intent.putExtra("content", content)
intent.putExtra("title", title)
intent.putExtra("image", image)
intent.putExtra("source", source)
app.startActivity(intent)
} else {
try {
CustomTabActivityHelper.openCustomTab(app, customTabsIntent, Uri.parse(linkDecoded)
) { _, uri ->
val intent = Intent(Intent.ACTION_VIEW, uri)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
startActivity(intent)
}
} catch (e: Exception) {
openInBrowser(linkDecoded, app)
}
}
}
fun Context.openItemUrl(linkDecoded: String,
content: String,
image: String,
title: String,
source: String,
customTabsIntent: CustomTabsIntent,
internalBrowser: Boolean,
articleViewer: Boolean,
@ -62,29 +104,7 @@ fun Context.openItemUrl(linkDecoded: String,
if (!internalBrowser) {
openInBrowser(linkDecoded, app)
} else {
if (articleViewer) {
val intent = Intent(this, ReaderActivity::class.java)
DragDismissIntentBuilder(this)
.setFullscreenOnTablets(true) // defaults to false, tablets will have padding on each side
.setDragElasticity(DragDismissIntentBuilder.DragElasticity.NORMAL) // Larger elasticities will make it easier to dismiss.
.setDrawUnderStatusBar(true)
.build(intent)
intent.putExtra("url", linkDecoded)
app.startActivity(intent)
} else {
try {
CustomTabActivityHelper.openCustomTab(app, customTabsIntent, Uri.parse(linkDecoded)
) { _, uri ->
val intent = Intent(Intent.ACTION_VIEW, uri)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
startActivity(intent)
}
} catch (e: Exception) {
openInBrowser(linkDecoded, app)
}
}
this.openItemUrlInternally(linkDecoded, content, image, title, source, customTabsIntent, articleViewer, app)
}
}
}
@ -96,7 +116,7 @@ private fun openInBrowser(linkDecoded: String, app: Activity) {
}
fun String.isUrlValid(): Boolean =
HttpUrl.parse(this) != null && Patterns.WEB_URL.matcher(this).matches()
HttpUrl.parse(this) != null && Patterns.WEB_URL.matcher(this).matches()
fun String.isBaseUrlValid(): Boolean {
val baseUrl = HttpUrl.parse(this)

View File

@ -1,5 +1,8 @@
package apps.amine.bou.readerforselfoss.utils.customtabs;
import java.util.List;
import android.app.Activity;
import android.net.Uri;
import android.os.Bundle;
@ -8,8 +11,6 @@ import android.support.customtabs.CustomTabsIntent;
import android.support.customtabs.CustomTabsServiceConnection;
import android.support.customtabs.CustomTabsSession;
import java.util.List;
/**
* This is a helper class to manage the connection to the Custom Tabs Service.
*/

View File

@ -1,5 +1,9 @@
package apps.amine.bou.readerforselfoss.utils.customtabs;
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@ -9,10 +13,8 @@ import android.net.Uri;
import android.support.customtabs.CustomTabsService;
import android.text.TextUtils;
import android.util.Log;
import apps.amine.bou.readerforselfoss.utils.customtabs.helpers.KeepAliveService;
import java.util.ArrayList;
import java.util.List;
import apps.amine.bou.readerforselfoss.utils.customtabs.helpers.KeepAliveService;
@SuppressWarnings("ALL")
class CustomTabsHelper {
@ -101,7 +103,7 @@ class CustomTabsHelper {
List<ResolveInfo> handlers = pm.queryIntentActivities(
intent,
PackageManager.GET_RESOLVED_FILTER);
if (handlers == null || handlers.size() == 0) {
if (handlers == null || handlers.isEmpty()) {
return false;
}
for (ResolveInfo resolveInfo : handlers) {

View File

@ -1,11 +1,12 @@
package apps.amine.bou.readerforselfoss.utils.customtabs;
import java.lang.ref.WeakReference;
import android.content.ComponentName;
import android.support.customtabs.CustomTabsClient;
import android.support.customtabs.CustomTabsServiceConnection;
import java.lang.ref.WeakReference;
/**
* Implementation for the CustomTabsServiceConnection that avoids leaking the
* ServiceConnectionCallback

View File

@ -5,14 +5,11 @@ import android.support.annotation.LayoutRes
import android.support.annotation.StringRes
import android.view.View
import android.widget.TextView
import apps.amine.bou.readerforselfoss.R
import com.mikepenz.materialdrawer.holder.BadgeStyle
import com.mikepenz.materialdrawer.holder.StringHolder
import com.mikepenz.materialdrawer.model.interfaces.ColorfulBadgeable
import apps.amine.bou.readerforselfoss.R
class CustomUrlPrimaryDrawerItem : CustomUrlBasePrimaryDrawerItem<CustomUrlPrimaryDrawerItem, CustomUrlPrimaryDrawerItem.ViewHolder>(), ColorfulBadgeable<CustomUrlPrimaryDrawerItem> {
protected var mBadge: StringHolder = StringHolder("")

View File

@ -6,8 +6,8 @@ import apps.amine.bou.readerforselfoss.utils.getUnsafeHttpClient
import com.bumptech.glide.Glide
import com.bumptech.glide.GlideBuilder
import com.bumptech.glide.Registry
import com.bumptech.glide.module.GlideModule
import com.bumptech.glide.load.model.GlideUrl
import com.bumptech.glide.module.GlideModule
import java.io.InputStream

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 124 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 216 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 108 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 242 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 114 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 263 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 500 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 119 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 296 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 408 B

View File

@ -15,7 +15,8 @@
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:theme="@style/ToolBarStyle" />
app:theme="@style/ToolBarStyle"
app:popupTheme="?attr/toolbarPopupTheme" />
</android.support.design.widget.AppBarLayout>

View File

@ -54,7 +54,8 @@
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:theme="@style/ToolBarStyle" />
app:theme="@style/ToolBarStyle"
app:popupTheme="?attr/toolbarPopupTheme" />
</android.support.design.widget.AppBarLayout>

View File

@ -14,7 +14,8 @@
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:theme="@style/ToolBarStyle" />
app:theme="@style/ToolBarStyle"
app:popupTheme="?attr/toolbarPopupTheme" />
</android.support.design.widget.AppBarLayout>
<LinearLayout

View File

@ -1,126 +1,148 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="apps.amine.bou.readerforselfoss.ReaderActivity"
android:background="?android:attr/windowBackground">
android:layout_height="match_parent">
<ImageView
android:id="@+id/imageView"
android:layout_width="0dp"
android:layout_height="200dp"
android:scaleType="centerCrop"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
<TextView
android:id="@+id/source"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
android:textSize="12sp"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/imageView" />
<TextView
android:id="@+id/title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginStart="16dp"
android:layout_marginTop="6dp"
android:textAppearance="@style/TextAppearance.AppCompat.Headline"
android:textStyle="bold"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/source" />
<org.sufficientlysecure.htmltextview.HtmlTextView
android:id="@+id/content"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginStart="16dp"
android:layout_marginTop="24dp"
android:paddingBottom="48dp"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/title"
tools:text="Some text @android:string/fingerprint_icon_content_description" />
<android.support.constraint.ConstraintLayout
<android.support.v4.widget.NestedScrollView
android:id="@+id/nestedScrollView"
android:layout_width="match_parent"
android:layout_height="35dp"
android:layout_marginBottom="0dp"
android:layout_marginEnd="0dp"
android:layout_marginRight="16dp"
android:layout_marginTop="16dp"
android:background="#BBBBBB"
android:layout_height="match_parent">
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/imageView"
android:layout_width="0dp"
android:layout_height="200dp"
android:scaleType="centerCrop"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
<TextView
android:id="@+id/source"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
android:textSize="12sp"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/imageView" />
<TextView
android:id="@+id/title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginStart="16dp"
android:layout_marginTop="6dp"
android:textAppearance="@style/TextAppearance.AppCompat.Headline"
android:textStyle="bold"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/source" />
<TextView
android:id="@+id/content"
android:autoLink="web"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginStart="16dp"
android:layout_marginTop="24dp"
android:paddingBottom="48dp"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/title" />
<!--<org.sufficientlysecure.htmltextview.HtmlTextView
android:id="@+id/content"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginStart="16dp"
android:layout_marginTop="24dp"
android:paddingBottom="48dp"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/title" />-->
</android.support.constraint.ConstraintLayout>
</android.support.v4.widget.NestedScrollView>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/content"
app:layout_constraintVertical_bias="1.0">
app:layout_constraintLeft_toLeftOf="parent"
android:layout_gravity="end|bottom|right">
<ImageButton
android:id="@+id/browserBtn"
android:layout_width="35dp"
android:layout_height="35dp"
android:layout_centerVertical="true"
<com.github.rubensousa.floatingtoolbar.FloatingToolbar
android:id="@+id/floatingToolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:layout_gravity="bottom"
app:floatingItemBackground="?attr/colorAccent"
app:floatingMenu="@menu/reader_toolbar" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_gravity="end|bottom|right"
android:layout_marginBottom="16dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:layout_toLeftOf="@+id/shareBtn"
android:layout_toStartOf="@+id/shareBtn"
android:adjustViewBounds="true"
android:background="@android:color/transparent"
android:elevation="5dp"
android:padding="4dp"
android:scaleType="centerCrop"
android:src="@drawable/ic_open_in_browser_black_24dp"
android:tint="@android:color/black"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/shareBtn"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:src="@drawable/ic_add"
app:backgroundTint="?attr/colorAccent"
app:fabSize="mini"
app:rippleColor="?attr/colorAccentDark" />
</FrameLayout>
<ImageButton
android:id="@+id/shareBtn"
android:layout_width="35dp"
android:layout_height="35dp"
android:adjustViewBounds="true"
android:background="@android:color/transparent"
android:elevation="5dp"
android:padding="4dp"
android:scaleType="centerCrop"
android:src="@drawable/ic_share_black_24dp"
android:tint="@android:color/black"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/browserBtn"
app:layout_constraintTop_toTopOf="parent" />
<FrameLayout
android:id="@+id/progressBar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone"
android:animateLayoutChanges="true"
android:alpha="0.8"
android:background="@color/black"
android:clickable="false">
</android.support.constraint.ConstraintLayout>
<ProgressBar
style="?android:attr/progressBarStyleLarge"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:progressTint="?attr/colorAccent" />
</FrameLayout>
</android.support.design.widget.CoordinatorLayout>
</android.support.constraint.ConstraintLayout>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
@ -16,7 +16,8 @@
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:theme="@style/ToolBarStyle" />
app:theme="@style/ToolBarStyle"
app:popupTheme="?attr/toolbarPopupTheme" />
</android.support.design.widget.AppBarLayout>
@ -28,16 +29,13 @@
app:layout_behavior="@string/appbar_scrolling_view_behavior">
</android.support.v7.widget.RecyclerView>
<com.melnykov.fab.FloatingActionButton
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom|right"
android:src="@drawable/ic_add_black_24dp"
android:src="@drawable/ic_add"
android:tint="?android:textColorPrimary"
fab:fab_colorNormal="?attr/colorAccent"
fab:fab_colorPressed="?attr/colorAccentDark"
fab:fab_colorRipple="@color/pink"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:layout_alignParentBottom="true"
@ -45,5 +43,5 @@
android:layout_alignParentEnd="true"
android:layout_marginBottom="16dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"/>
</RelativeLayout>
android:layout_marginRight="16dp" />
</android.support.design.widget.CoordinatorLayout>

View File

@ -9,6 +9,7 @@
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:theme="@style/ToolBarStyle" />
app:theme="@style/ToolBarStyle"
app:popupTheme="?attr/toolbarPopupTheme" />
</android.support.design.widget.AppBarLayout>

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/more_action"
android:icon="@drawable/ic_chrome_reader_mode"
android:title="@string/reader_action_more"
app:showAsAction="ifRoom" />
<item
android:id="@+id/open_action"
android:icon="@drawable/ic_open_in_browser"
android:iconTint="@color/white"
android:title="@string/reader_action_open"
app:showAsAction="ifRoom" />
<item
android:id="@+id/share_action"
android:icon="@drawable/ic_share_white_24dp"
android:title="@string/reader_action_share"
app:showAsAction="ifRoom" />
</menu>

View File

@ -154,4 +154,8 @@
<string name="translation">Translation</string>
<string name="cant_open_invalid_url">The item url is invalid. I\'m looking into solving this issue so the app won\'t crash.</string>
<string name="drawer_report_bug">Report a bug</string>
<string name="items_number_should_be_number">The items number should be an integer.</string>
<string name="reader_action_more">Read more</string>
<string name="reader_action_open">Open in browser</string>
<string name="reader_action_share">Share</string>
</resources>

View File

@ -154,4 +154,8 @@
<string name="translation">Translation</string>
<string name="cant_open_invalid_url">The item url is invalid. I\'m looking into solving this issue so the app won\'t crash.</string>
<string name="drawer_report_bug">Report a bug</string>
<string name="items_number_should_be_number">The items number should be an integer.</string>
<string name="reader_action_more">Read more</string>
<string name="reader_action_open">Open in browser</string>
<string name="reader_action_share">Share</string>
</resources>

View File

@ -154,4 +154,8 @@
<string name="translation">Translation</string>
<string name="cant_open_invalid_url">The item url is invalid. I\'m looking into solving this issue so the app won\'t crash.</string>
<string name="drawer_report_bug">Report a bug</string>
<string name="items_number_should_be_number">The items number should be an integer.</string>
<string name="reader_action_more">Read more</string>
<string name="reader_action_open">Open in browser</string>
<string name="reader_action_share">Share</string>
</resources>

View File

@ -154,4 +154,8 @@
<string name="translation">Translation</string>
<string name="cant_open_invalid_url">The item url is invalid. I\'m looking into solving this issue so the app won\'t crash.</string>
<string name="drawer_report_bug">Report a bug</string>
<string name="items_number_should_be_number">The items number should be an integer.</string>
<string name="reader_action_more">Read more</string>
<string name="reader_action_open">Open in browser</string>
<string name="reader_action_share">Share</string>
</resources>

View File

@ -154,4 +154,8 @@
<string name="translation">Translation</string>
<string name="cant_open_invalid_url">The item url is invalid. I\'m looking into solving this issue so the app won\'t crash.</string>
<string name="drawer_report_bug">Report a bug</string>
<string name="items_number_should_be_number">The items number should be an integer.</string>
<string name="reader_action_more">Read more</string>
<string name="reader_action_open">Open in browser</string>
<string name="reader_action_share">Share</string>
</resources>

View File

@ -154,4 +154,8 @@
<string name="translation">Übersetzung</string>
<string name="cant_open_invalid_url">The item url is invalid. I\'m looking into solving this issue so the app won\'t crash.</string>
<string name="drawer_report_bug">Report a bug</string>
<string name="items_number_should_be_number">The items number should be an integer.</string>
<string name="reader_action_more">Read more</string>
<string name="reader_action_open">Open in browser</string>
<string name="reader_action_share">Share</string>
</resources>

View File

@ -154,4 +154,8 @@
<string name="translation">Translation</string>
<string name="cant_open_invalid_url">The item url is invalid. I\'m looking into solving this issue so the app won\'t crash.</string>
<string name="drawer_report_bug">Report a bug</string>
<string name="items_number_should_be_number">The items number should be an integer.</string>
<string name="reader_action_more">Read more</string>
<string name="reader_action_open">Open in browser</string>
<string name="reader_action_share">Share</string>
</resources>

View File

@ -154,4 +154,8 @@
<string name="translation">Translation</string>
<string name="cant_open_invalid_url">The item url is invalid. I\'m looking into solving this issue so the app won\'t crash.</string>
<string name="drawer_report_bug">Report a bug</string>
<string name="items_number_should_be_number">The items number should be an integer.</string>
<string name="reader_action_more">Read more</string>
<string name="reader_action_open">Open in browser</string>
<string name="reader_action_share">Share</string>
</resources>

View File

@ -154,4 +154,8 @@
<string name="translation">Translation</string>
<string name="cant_open_invalid_url">The item url is invalid. I\'m looking into solving this issue so the app won\'t crash.</string>
<string name="drawer_report_bug">Report a bug</string>
<string name="items_number_should_be_number">The items number should be an integer.</string>
<string name="reader_action_more">Read more</string>
<string name="reader_action_open">Open in browser</string>
<string name="reader_action_share">Share</string>
</resources>

View File

@ -6,20 +6,20 @@
<string name="prompt_password">"Mot de passe"</string>
<string name="prompt_http_password">"Mot de passe HTTP"</string>
<string name="action_sign_in">"Valider"</string>
<string name="error_invalid_password">"Mot de passe pas assez lent"</string>
<string name="error_invalid_password">"Mot de passe trop court"</string>
<string name="error_field_required">"Champ requis"</string>
<string name="prompt_url">"Url Selfoss"</string>
<string name="withLoginSwitch">"Avec login ?"</string>
<string name="withHttpLoginSwitch">"Avec login HTTP ?"</string>
<string name="login_url_problem">"Petit soucis. Il manque peut être un / à la fin ?"</string>
<string name="login_url_problem">"Petit souci. Il manque peut être un / à la fin ?"</string>
<string name="prompt_login">"Utilisateur"</string>
<string name="prompt_http_login">"Utilisateur HTTP"</string>
<string name="label_share">"Partager"</string>
<string name="readAll">"Tout lire"</string>
<string name="action_disconnect">"Déconnecter"</string>
<string name="title_activity_settings">"Paramètres"</string>
<string name="pref_header_general">"General"</string>
<string name="pref_switch_actions_tap_title">"Action du clique sur un article"</string>
<string name="pref_header_general">"Général"</string>
<string name="pref_switch_actions_tap_title">"Action du clic sur un article"</string>
<string name="add_source_hint_tags">"Tag1, Tag2, Tag3"</string>
<string name="add_source_hint_url">"Lien"</string>
<string name="add_source_hint_name">"Nom"</string>
@ -101,20 +101,20 @@
<string name="card_height_on">La taille de la carte s\'adaptera au contenu</string>
<string name="card_height_off">La taille de la carte sera fixe</string>
<string name="source_code">Code source</string>
<string name="cant_mark_read">Kan het artikel niet als gelezen markeren</string>
<string name="cant_mark_read">Impossible de marquer l\'article comme lu</string>
<string name="drawer_error_loading_tags">Erreur lors du chargement des tags…</string>
<string name="drawer_error_loading_sources">Erreur lors du chargement des sources…</string>
<string name="drawer_item_filters">Filtres</string>
<string name="drawer_action_clear">raz</string>
<string name="drawer_item_tags">Tags</string>
<string name="drawer_item_sources">Sources</string>
<string name="drawer_action_edit">editer</string>
<string name="drawer_action_edit">éditer</string>
<string name="cache_drawer_error" tools:keep="@string/cache_drawer_error">Impossible de mettre en cache les filtres pour le drawer</string>
<string name="no_tags_loaded">Pas de tags chargés</string>
<string name="no_sources_loaded">Pas de sources chargés</string>
<string name="drawer_loading">Chargement …</string>
<string name="menu_home_search">Rechercher</string>
<string name="can_delete_source">Can\'t delete the source…</string>
<string name="can_delete_source">Impossible de supprimer la source…</string>
<string name="base_url_error">Il y a eu un souci lors de la communication avec votre instance Selfoss. Si le problèmes persiste, contactez-moi pour trouver une solution.</string>
<string name="pref_header_theme">Thèmes</string>
<string name="default_theme">Par défaut</string>
@ -132,7 +132,7 @@
<string name="indigo_pink_dark_theme">Indigo/Rose/Foncé</string>
<string name="red_teal_dark_theme">Rouge/Sarcelle/Foncé</string>
<string name="pref_header_debug">Debug</string>
<string name="login_debug_title">Activez pour loguer toutes les erreurs de conexion</string>
<string name="login_debug_title">Activez pour logguer toutes les erreurs de connexion</string>
<string name="login_debug_on">Toutes les erreurs de connexion vont être loguées</string>
<string name="login_debug_off">Aucune erreur de connexion ne sera loguée</string>
<string name="login_menu_debug">Debug</string>
@ -142,7 +142,7 @@
<string name="pref_api_items_number_title">Nombre d\'articles chargés</string>
<string name="read_debug_title">Des articles lus marqués comme non lus ?</string>
<string name="read_debug_off">Aucun log quand un article est marqué comme lu</string>
<string name="read_debug_on">Les appels API vont être logués lorsequ\'un article est marqué comme lu</string>
<string name="read_debug_on">Les appels API vont être logués lorsqu\'un article est marqué comme lu</string>
<string name="summary_debug_identifier">Identifiant de debug</string>
<string name="unique_id_to_clipboard">Texte copié</string>
<string name="display_header_drawer_summary">Afficher une entête avec l\'url de votre instance de Selfoss en haut du drawer lateral.</string>
@ -154,4 +154,8 @@
<string name="translation">Traduction</string>
<string name="cant_open_invalid_url">Lurl de lélément nest pas valide. En attendant la résolution du problème, le lien ne s\'ouvrira pas.</string>
<string name="drawer_report_bug">Signaler un bug</string>
<string name="items_number_should_be_number">Le nombre d\'articles doit être un entier.</string>
<string name="reader_action_more">Lire plus</string>
<string name="reader_action_open">Ouvrir</string>
<string name="reader_action_share">Partager</string>
</resources>

View File

@ -154,4 +154,8 @@
<string name="translation">Translation</string>
<string name="cant_open_invalid_url">The item url is invalid. I\'m looking into solving this issue so the app won\'t crash.</string>
<string name="drawer_report_bug">Report a bug</string>
<string name="items_number_should_be_number">The items number should be an integer.</string>
<string name="reader_action_more">Read more</string>
<string name="reader_action_open">Open in browser</string>
<string name="reader_action_share">Share</string>
</resources>

View File

@ -154,4 +154,8 @@
<string name="translation">Translation</string>
<string name="cant_open_invalid_url">The item url is invalid. I\'m looking into solving this issue so the app won\'t crash.</string>
<string name="drawer_report_bug">Report a bug</string>
<string name="items_number_should_be_number">The items number should be an integer.</string>
<string name="reader_action_more">Read more</string>
<string name="reader_action_open">Open in browser</string>
<string name="reader_action_share">Share</string>
</resources>

View File

@ -154,4 +154,8 @@
<string name="translation">Translation</string>
<string name="cant_open_invalid_url">The item url is invalid. I\'m looking into solving this issue so the app won\'t crash.</string>
<string name="drawer_report_bug">Report a bug</string>
<string name="items_number_should_be_number">The items number should be an integer.</string>
<string name="reader_action_more">Read more</string>
<string name="reader_action_open">Open in browser</string>
<string name="reader_action_share">Share</string>
</resources>

View File

@ -154,4 +154,8 @@
<string name="translation">Translation</string>
<string name="cant_open_invalid_url">The item url is invalid. I\'m looking into solving this issue so the app won\'t crash.</string>
<string name="drawer_report_bug">Report a bug</string>
<string name="items_number_should_be_number">The items number should be an integer.</string>
<string name="reader_action_more">Read more</string>
<string name="reader_action_open">Open in browser</string>
<string name="reader_action_share">Share</string>
</resources>

View File

@ -154,4 +154,8 @@
<string name="translation">Translation</string>
<string name="cant_open_invalid_url">The item url is invalid. I\'m looking into solving this issue so the app won\'t crash.</string>
<string name="drawer_report_bug">Report a bug</string>
<string name="items_number_should_be_number">The items number should be an integer.</string>
<string name="reader_action_more">Read more</string>
<string name="reader_action_open">Open in browser</string>
<string name="reader_action_share">Share</string>
</resources>

View File

@ -154,4 +154,8 @@
<string name="translation">Vertaling</string>
<string name="cant_open_invalid_url">The item url is invalid. I\'m looking into solving this issue so the app won\'t crash.</string>
<string name="drawer_report_bug">Report a bug</string>
<string name="items_number_should_be_number">The items number should be an integer.</string>
<string name="reader_action_more">Read more</string>
<string name="reader_action_open">Open in browser</string>
<string name="reader_action_share">Share</string>
</resources>

View File

@ -154,4 +154,8 @@
<string name="translation">Translation</string>
<string name="cant_open_invalid_url">The item url is invalid. I\'m looking into solving this issue so the app won\'t crash.</string>
<string name="drawer_report_bug">Report a bug</string>
<string name="items_number_should_be_number">The items number should be an integer.</string>
<string name="reader_action_more">Read more</string>
<string name="reader_action_open">Open in browser</string>
<string name="reader_action_share">Share</string>
</resources>

View File

@ -154,4 +154,8 @@
<string name="translation">Translation</string>
<string name="cant_open_invalid_url">The item url is invalid. I\'m looking into solving this issue so the app won\'t crash.</string>
<string name="drawer_report_bug">Report a bug</string>
<string name="items_number_should_be_number">The items number should be an integer.</string>
<string name="reader_action_more">Read more</string>
<string name="reader_action_open">Open in browser</string>
<string name="reader_action_share">Share</string>
</resources>

View File

@ -2,156 +2,160 @@
<!--Generated by crowdin.com-->
<resources xmlns:tools="http://schemas.android.com/tools">
<string name="app_name">"Reader for Selfoss"</string>
<string name="title_activity_login">"Log in"</string>
<string name="prompt_password">"Password"</string>
<string name="prompt_http_password">"HTTP Password"</string>
<string name="action_sign_in">"Go"</string>
<string name="error_invalid_password">"Password not long enough"</string>
<string name="error_field_required">"Field required"</string>
<string name="title_activity_login">"Entrar"</string>
<string name="prompt_password">"Senha"</string>
<string name="prompt_http_password">"Senha HTTP"</string>
<string name="action_sign_in">"Vamos lá"</string>
<string name="error_invalid_password">"Senha muito pequena"</string>
<string name="error_field_required">"Campo obrigatório"</string>
<string name="prompt_url">"Url"</string>
<string name="withLoginSwitch">"Login required ?"</string>
<string name="withHttpLoginSwitch">"HTTP Login required ?"</string>
<string name="login_url_problem">"Oops. You may need to add a \"/\" at the end of the url."</string>
<string name="prompt_login">"Username"</string>
<string name="prompt_http_login">"HTTP Username"</string>
<string name="label_share">"Share"</string>
<string name="readAll">"Read all"</string>
<string name="action_disconnect">"Disconnect"</string>
<string name="title_activity_settings">"Settings"</string>
<string name="pref_header_general">"General"</string>
<string name="pref_switch_actions_tap_title">"Tap action on the articles"</string>
<string name="withLoginSwitch">"É necessário o login ?"</string>
<string name="withHttpLoginSwitch">"É necessário o login HTTP ?"</string>
<string name="login_url_problem">"Oops. Talvez você precise adicionar uma \"/\" no final da url."</string>
<string name="prompt_login">"Usuário"</string>
<string name="prompt_http_login">"Usuário HTTP"</string>
<string name="label_share">"Compartilhar"</string>
<string name="readAll">"Ler todos"</string>
<string name="action_disconnect">"Desconectar"</string>
<string name="title_activity_settings">"Configurações"</string>
<string name="pref_header_general">"Geral"</string>
<string name="pref_switch_actions_tap_title">"Ação de tocar nos artigos"</string>
<string name="add_source_hint_tags">"Tag1, Tag2, Tag3"</string>
<string name="add_source_hint_url">"Link"</string>
<string name="add_source_hint_name">"Name"</string>
<string name="add_source">"Add a source"</string>
<string name="add_source_save">"Save"</string>
<string name="wrong_infos">"Check your details again."</string>
<string name="all_posts_not_read">"All posts weren't read"</string>
<string name="all_posts_read">"All posts were read"</string>
<string name="cant_get_favs">"Can't get favorites"</string>
<string name="cant_get_new_elements">"Can't get new articles"</string>
<string name="cant_get_read">"Can't get read articles"</string>
<string name="nothing_here">"Nothing here"</string>
<string name="tab_new">"New"</string>
<string name="tab_read">"All"</string>
<string name="tab_favs">"Favorites"</string>
<string name="action_about">"About"</string>
<string name="marked_as_read">"Item read"</string>
<string name="undo_string">"Undo"</string>
<string name="addStringNoUrl">"Log in to add sources."</string>
<string name="cant_get_sources">"Can't get sources list."</string>
<string name="cant_create_source">"Can't create source."</string>
<string name="cant_get_spouts">"Can't get spouts list."</string>
<string name="form_not_complete">"The form is not complete"</string>
<string name="add_source_hint_name">"Nome"</string>
<string name="add_source">"Adicionar uma fonte"</string>
<string name="add_source_save">"Salvar"</string>
<string name="wrong_infos">"Verifique os detalhes novamente."</string>
<string name="all_posts_not_read">"Nenhum post foi lido"</string>
<string name="all_posts_read">"Todos os posts foram lidos"</string>
<string name="cant_get_favs">"Não consigo obter os favoritos"</string>
<string name="cant_get_new_elements">"Não consigo obter novos artigos"</string>
<string name="cant_get_read">"Não consigo ler artigos"</string>
<string name="nothing_here">"Nada aqui"</string>
<string name="tab_new">"Novo"</string>
<string name="tab_read">"Todos"</string>
<string name="tab_favs">"Favoritos"</string>
<string name="action_about">"Sobre"</string>
<string name="marked_as_read">"Item lido"</string>
<string name="undo_string">"Desfazer"</string>
<string name="addStringNoUrl">"Faça login para adicionar fontes."</string>
<string name="cant_get_sources">"Não é possível obter a lista de fontes."</string>
<string name="cant_create_source">"Não é possível criar fonte."</string>
<string name="cant_get_spouts">"Não é possível obter a lista de spouts."</string>
<string name="form_not_complete">"O formulário não está completo"</string>
<string name="pref_header_links">"Links"</string>
<string name="issue_tracker_link">"Issue Tracker"</string>
<string name="issue_tracker_summary">"Report a bug or ask for a new feature"</string>
<string name="warning_wrong_url">"WARNING"</string>
<string name="issue_tracker_link">"Rastreador de problemas"</string>
<string name="issue_tracker_summary">"Informe um erro ou peça um novo recurso"</string>
<string name="warning_wrong_url">"ATENÇÃO"</string>
<string name="pref_switch_card_view_title">"Card View"</string>
<string name="cant_mark_favortie">"Can't mark article as favorite"</string>
<string name="cant_unmark_favortie">"Can't remove item from favorite"</string>
<string name="share">"Share"</string>
<string name="rating_prompt_title">"Enjoying the app ?"</string>
<string name="rating_prompt_yes">"Yes !"</string>
<string name="rating_prompt_no">"Not really …"</string>
<string name="rating_prompt_feedback_title">"Can you tell us why ?"</string>
<string name="cant_mark_favortie">"Não é possível marcar o artigo como favorito"</string>
<string name="cant_unmark_favortie">"Não é possível remover o item do favorito"</string>
<string name="share">"Compartilhar"</string>
<string name="rating_prompt_title">"Aproveitando o app ?"</string>
<string name="rating_prompt_yes">"Sim !"</string>
<string name="rating_prompt_no">"Na verdade não …"</string>
<string name="rating_prompt_feedback_title">"Você pode nos dizer o porquê ?"</string>
<string name="rating_prompt_feedback_yes">"OK !"</string>
<string name="rating_prompt_feedback_no">"Not now."</string>
<string name="rating_prompt_rating_title">"Great ! Can you rate us on the Store ?"</string>
<string name="rating_prompt_rating_yes">"Sure !"</string>
<string name="rating_prompt_rating_no">"Not right now."</string>
<string name="rating_prompt_thanks">"Thanks, your feedback help enhance the app !"</string>
<string name="switch_unread_count">"Display the unread count as a badge for the bottom bar."</string>
<string name="switch_unread_count_title">"Display unread count"</string>
<string name="display_all_counts_title">"Display count for favorite and read"</string>
<string name="menu_share_the_app">"Invite friends"</string>
<string name="invitation_title">"Try this app for your Selfoss RSS feeds !"</string>
<string name="invitation_message">"I use this app for my Selfoss RSS feeds. You may like it too !"</string>
<string name="invitation_cta">"Try the app"</string>
<string name="text_wrong_url">"You seem to be trying to use an invalid URL. Make sure it is correct, and if the problem persists, contact me (via the store contact link). Please note that the app needs you to be using Selfoss. You can't access RSS feeds without it."</string>
<string name="pref_general_internal_browser_title">"Open links inside the app"</string>
<string name="pref_general_internal_browser_on">"Articles will open inside the app"</string>
<string name="pref_general_internal_browser_off">"Articles will open with your default browser"</string>
<string name="prefer_article_viewer_title">"Use the article viewer"</string>
<string name="prefer_article_viewer_on">"Will use the article viewer instead of the internal browser"</string>
<string name="prefer_article_viewer_off">"Will use the internal browser instead of the article viewer"</string>
<string name="pref_general_category_links">"Link handeling"</string>
<string name="pref_general_category_displaying">"Displaying"</string>
<string name="pref_general_category_actions">"Actions"</string>
<string name="pref_switch_card_view_on">"The articles will be displayed as cards"</string>
<string name="pref_switch_card_view_off">"The articles will be displayed as a list"</string>
<string name="pref_switch_actions_tap_on">"Displays the action bar under the article"</string>
<string name="pref_switch_actions_tap_off">"When selecting an article it will open in your selected browser"</string>
<string name="menu_home_refresh">"Update remote"</string>
<string name="refresh_success_response">"The remote is updated, you can now reload the articles list"</string>
<string name="refresh_failer_message">"The update didn't work, try again later, or check your selfoss logs."</string>
<string name="refresh_in_progress">"Refresh in progress"</string>
<string name="new_apk_available_title">"A new APK is available."</string>
<string name="new_apk_available_message">"A new APK is available to download on the official repository."</string>
<string name="new_apk_available_get">"Download now"</string>
<string name="new_apk_available_no">"Ignore version"</string>
<string name="intro_hello_title">"Hi there !"</string>
<string name="intro_hello_message">"Thanks for downloading the app !"</string>
<string name="intro_needs_selfoss_title">"Before you start…"</string>
<string name="intro_needs_selfoss_message">"You can't use the app without a Selfoss instance."</string>
<string name="intro_needs_selfoss_link">"What is Selfoss ?"</string>
<string name="intro_all_set_title">"All set !"</string>
<string name="intro_all_set_message">"You are ready to use the app. Don't forget to go to the settings page to configure your app, and where you'll find some useful links."</string>
<string name="card_height_title">Full height cards</string>
<string name="card_height_on">Cards height will adjust to its content</string>
<string name="card_height_off">Card height will be fixed</string>
<string name="source_code">Source code</string>
<string name="cant_mark_read">Can\'t mark article as read</string>
<string name="drawer_error_loading_tags">Error loading tags…</string>
<string name="drawer_error_loading_sources">Error loading sources…</string>
<string name="drawer_item_filters">Filters</string>
<string name="drawer_action_clear">clear</string>
<string name="rating_prompt_feedback_no">"Não agora."</string>
<string name="rating_prompt_rating_title">"Ótimo ! Você pode nos avaliar na loja ?"</string>
<string name="rating_prompt_rating_yes">"Com certeza !"</string>
<string name="rating_prompt_rating_no">"Não agora."</string>
<string name="rating_prompt_thanks">"Obrigado, seu comentário ajuda a melhorar o app !"</string>
<string name="switch_unread_count">"Exibir a contagem de artigos não lidos como um badge na barra inferior."</string>
<string name="switch_unread_count_title">"Exibir contagem de artigos não lidos"</string>
<string name="display_all_counts_title">"Exibir contagem de lidos e favoritos"</string>
<string name="menu_share_the_app">"Convidar amigos"</string>
<string name="invitation_title">"Experimente este aplicativo para seus feeds RSS do Selfoss !"</string>
<string name="invitation_message">"Eu uso o app para o visualizar meu feed RSS do Selfoss. Você vai gostar também !"</string>
<string name="invitation_cta">"Experimente o aplicativo"</string>
<string name="text_wrong_url">"Parece que você está tentando utilizar uma URL inválida. Certifique-se de que está correto, e se o problema persistir, entre em contato comigo (através do link de contato da loja). Por favor, note que o aplicativo precisa que você esteja usando o Selfoss. Você não pode acessar feeds RSS sem ele."</string>
<string name="pref_general_internal_browser_title">"Abrir links dentro do aplicativo"</string>
<string name="pref_general_internal_browser_on">"Os artigos serão abertos dentro do aplicativo"</string>
<string name="pref_general_internal_browser_off">"Os artigos serão abertos com seu navegador padrão"</string>
<string name="prefer_article_viewer_title">"Use o visualizador de artigos"</string>
<string name="prefer_article_viewer_on">"Usará o visualizador de artigos em vez do navegador"</string>
<string name="prefer_article_viewer_off">"Utilizará o navegador em vez do visualizador de artigos"</string>
<string name="pref_general_category_links">"Manipulação de links"</string>
<string name="pref_general_category_displaying">"Mostrando"</string>
<string name="pref_general_category_actions">"Ações"</string>
<string name="pref_switch_card_view_on">"Os artigos serão exibidos no formato de cards"</string>
<string name="pref_switch_card_view_off">"Os artigos serão exibidos em lista"</string>
<string name="pref_switch_actions_tap_on">"Exibe a barra de ação sob o artigo"</string>
<string name="pref_switch_actions_tap_off">"Ao selecionar um artigo, ele será aberto no seu navegador selecionado"</string>
<string name="menu_home_refresh">"Atualizar controle remoto"</string>
<string name="refresh_success_response">"O controle remoto foi atualizado, agora você pode recarregar a lista de artigos"</string>
<string name="refresh_failer_message">"A atualização não funcionou, tente novamente mais tarde ou verifique seus logs do Selfoss."</string>
<string name="refresh_in_progress">"Atualização em progresso"</string>
<string name="new_apk_available_title">"Um novo APK está disponível."</string>
<string name="new_apk_available_message">"Um novo APK está disponível para download no repositório oficial."</string>
<string name="new_apk_available_get">"Baixar agora"</string>
<string name="new_apk_available_no">"Ignorar"</string>
<string name="intro_hello_title">"Olá !"</string>
<string name="intro_hello_message">"Obrigado por baixar o app !"</string>
<string name="intro_needs_selfoss_title">"Antes que você comece…"</string>
<string name="intro_needs_selfoss_message">"Você não pode usar o aplicativo sem uma instância do Selfoss."</string>
<string name="intro_needs_selfoss_link">"O que é Selfoss ?"</string>
<string name="intro_all_set_title">"Tudo pronto !"</string>
<string name="intro_all_set_message">"Você está pronto para usar o aplicativo. Não se esqueça de acessar a página de configurações para configurar seu aplicativo e onde você encontrará alguns links úteis."</string>
<string name="card_height_title">Cards com altura total</string>
<string name="card_height_on">Cards com altura ajustáveis de acordo com o conteúdo</string>
<string name="card_height_off">Cards com altura de tamanho fixo</string>
<string name="source_code">Código fonte</string>
<string name="cant_mark_read">Não é possível marcar o artigo como lido</string>
<string name="drawer_error_loading_tags">Erro ao carregar as tags…</string>
<string name="drawer_error_loading_sources">Erro ao carregar as fontes…</string>
<string name="drawer_item_filters">Filtros</string>
<string name="drawer_action_clear">limpar</string>
<string name="drawer_item_tags">Tags</string>
<string name="drawer_item_sources">Sources</string>
<string name="drawer_action_edit">edit</string>
<string name="cache_drawer_error" tools:keep="@string/cache_drawer_error">Couldn\'t cache your drawer data</string>
<string name="no_tags_loaded">No tags loaded</string>
<string name="no_sources_loaded">No sources loaded</string>
<string name="drawer_loading">Loading</string>
<string name="menu_home_search">Search</string>
<string name="can_delete_source">Can\'t delete the source…</string>
<string name="base_url_error">There was an issue when trying to communicate with your Selfoss Instance. If the issue persists, please get in touch with me.</string>
<string name="pref_header_theme">Themes</string>
<string name="default_theme">Default</string>
<string name="teal_orange_theme">Teal/Orange/Light</string>
<string name="cyan_pink_theme">Cyan/Pink/Light</string>
<string name="grey_orange_theme">Grey/Orange/Light</string>
<string name="blue_amber_theme">Blue/Amber/Light</string>
<string name="indigo_pink_theme">Indigo/Pink/Light</string>
<string name="red_teal_theme">Red/Teal/Light</string>
<string name="teal_orange_dark_theme">Teal/Orange/Dark</string>
<string name="cyan_pink_dark_theme">Cyan/Pink/Dark</string>
<string name="default_dark_theme">Default/Dark</string>
<string name="grey_orange_dark_theme">Grey/Orange/Dark</string>
<string name="blue_amber_dark_theme">Blue/Amber/Dark</string>
<string name="indigo_pink_dark_theme">Indigo/Pink/Dark</string>
<string name="red_teal_dark_theme">Red/Teal/Dark</string>
<string name="pref_header_debug">Debug</string>
<string name="login_debug_title">Activate to log login errors</string>
<string name="login_debug_on">Any error on the login page will be logged</string>
<string name="login_debug_off">No log on the login page</string>
<string name="login_menu_debug">Debug</string>
<string name="self_hosted_cert_switch">Using a self hosted certificate ?</string>
<string name="self_signed_cert_warning">Due to security reasons, self signed certificates are not supported by default. By activating this, I\'ll not be responsible of any security problem you encounter.</string>
<string name="drawer_item_sources">Fontes</string>
<string name="drawer_action_edit">editar</string>
<string name="cache_drawer_error" tools:keep="@string/cache_drawer_error">Não foi possível recuperar os dados em cache</string>
<string name="no_tags_loaded">Nenhuma tag carregada</string>
<string name="no_sources_loaded">Nenhuma fonte carregada</string>
<string name="drawer_loading">Carregando</string>
<string name="menu_home_search">Procurar</string>
<string name="can_delete_source">Não foi possível apagar a fonte…</string>
<string name="base_url_error">Houve um problema ao tentar se comunicar com o seu Selfoss. Se o problema persistir, entre em contato comigo.</string>
<string name="pref_header_theme">Temas</string>
<string name="default_theme">Padrão</string>
<string name="teal_orange_theme">Cerceta/Laranja/Claro</string>
<string name="cyan_pink_theme">Ciano/Rosa/Claro</string>
<string name="grey_orange_theme">Cinza/Laranja/Claro</string>
<string name="blue_amber_theme">Azul/Âmbar/Claro</string>
<string name="indigo_pink_theme">Índigo/Rosa/Claro</string>
<string name="red_teal_theme">Vermelho/Cerceta/Claro</string>
<string name="teal_orange_dark_theme">Cerceta/Laranja/Escuro</string>
<string name="cyan_pink_dark_theme">Ciano/Rosa/Escuro</string>
<string name="default_dark_theme">Padrão/Escuro</string>
<string name="grey_orange_dark_theme">Cinza/Laranja/Escuro</string>
<string name="blue_amber_dark_theme">Azul/Âmbar/Escuro</string>
<string name="indigo_pink_dark_theme">Índigo/Rosa/Escuro</string>
<string name="red_teal_dark_theme">Vermelho/Âmbar/Escuro</string>
<string name="pref_header_debug">Depurar</string>
<string name="login_debug_title">Ativar para registrar erros de login</string>
<string name="login_debug_on">Qualquer erro na página de login será registrado</string>
<string name="login_debug_off">Nenhum registro na página de login</string>
<string name="login_menu_debug">Depurar</string>
<string name="self_hosted_cert_switch">Usando um certificado autônomo ?</string>
<string name="self_signed_cert_warning">Por motivos de segurança, certificados autônomos não são suportados por padrão. Ao ativar, não serei responsável por qualquer problema de segurança que você encontre.</string>
<string name="pref_selfoss_category">Selfoss Api</string>
<string name="pref_api_items_number_title">Loaded items number</string>
<string name="read_debug_title">Read articles appearing as unread ?</string>
<string name="read_debug_off">No log when marking an item as read</string>
<string name="read_debug_on">Api calls will be logged when marking an article as read</string>
<string name="summary_debug_identifier">Debug identifier</string>
<string name="unique_id_to_clipboard">Identifier copied to your clipboard</string>
<string name="display_header_drawer_summary">Display a header with the selfoss instance url on the lateral drawer.</string>
<string name="display_header_drawer_title">Account header</string>
<string name="login_everything_title">Logging every api calls</string>
<string name="login_everything_on">This will log every api call for debug purpose.</string>
<string name="login_everything_off">No api call will be logged</string>
<string name="pref_general_infinite_loading_title">(BETA) Load more articles on scroll</string>
<string name="translation">Translation</string>
<string name="cant_open_invalid_url">The item url is invalid. I\'m looking into solving this issue so the app won\'t crash.</string>
<string name="drawer_report_bug">Report a bug</string>
<string name="pref_api_items_number_title">Quantidade de itens carregados</string>
<string name="read_debug_title">Ler os artigos que aparecem como não lidos ?</string>
<string name="read_debug_off">Nenhum registro ao marcar um item como lido</string>
<string name="read_debug_on">As chamadas Api serão registradas ao marcar um artigo como lido</string>
<string name="summary_debug_identifier">Identificador de depuração</string>
<string name="unique_id_to_clipboard">Identificador copiado para a área de transferência</string>
<string name="display_header_drawer_summary">Exibir um cabeçalho com o URL da instância do Selfoss na barra lateral.</string>
<string name="display_header_drawer_title">Cabeçalho da conta</string>
<string name="login_everything_title">Registrando todas as chamadas a api</string>
<string name="login_everything_on">Isso registrará todas as chamadas api para fins de depuração.</string>
<string name="login_everything_off">Nenhuma chamada a api será registrada</string>
<string name="pref_general_infinite_loading_title">(BETA) Carregar mais artigos ao realizar o scroll</string>
<string name="translation">Traduções</string>
<string name="cant_open_invalid_url">A url está inválida. Estou tentando resolver esse problema para que o aplicativo não encerre.</string>
<string name="drawer_report_bug">Reportar erro</string>
<string name="items_number_should_be_number">O número dos itens deve ser um número inteiro.</string>
<string name="reader_action_more">Read more</string>
<string name="reader_action_open">Open in browser</string>
<string name="reader_action_share">Share</string>
</resources>

View File

@ -154,4 +154,8 @@
<string name="translation">Translation</string>
<string name="cant_open_invalid_url">The item url is invalid. I\'m looking into solving this issue so the app won\'t crash.</string>
<string name="drawer_report_bug">Report a bug</string>
<string name="items_number_should_be_number">The items number should be an integer.</string>
<string name="reader_action_more">Read more</string>
<string name="reader_action_open">Open in browser</string>
<string name="reader_action_share">Share</string>
</resources>

View File

@ -154,4 +154,8 @@
<string name="translation">Translation</string>
<string name="cant_open_invalid_url">The item url is invalid. I\'m looking into solving this issue so the app won\'t crash.</string>
<string name="drawer_report_bug">Report a bug</string>
<string name="items_number_should_be_number">The items number should be an integer.</string>
<string name="reader_action_more">Read more</string>
<string name="reader_action_open">Open in browser</string>
<string name="reader_action_share">Share</string>
</resources>

View File

@ -154,4 +154,8 @@
<string name="translation">Translation</string>
<string name="cant_open_invalid_url">The item url is invalid. I\'m looking into solving this issue so the app won\'t crash.</string>
<string name="drawer_report_bug">Report a bug</string>
<string name="items_number_should_be_number">The items number should be an integer.</string>
<string name="reader_action_more">Read more</string>
<string name="reader_action_open">Open in browser</string>
<string name="reader_action_share">Share</string>
</resources>

View File

@ -154,4 +154,8 @@
<string name="translation">Translation</string>
<string name="cant_open_invalid_url">The item url is invalid. I\'m looking into solving this issue so the app won\'t crash.</string>
<string name="drawer_report_bug">Report a bug</string>
<string name="items_number_should_be_number">The items number should be an integer.</string>
<string name="reader_action_more">Read more</string>
<string name="reader_action_open">Open in browser</string>
<string name="reader_action_share">Share</string>
</resources>

View File

@ -154,4 +154,8 @@
<string name="translation">Translation</string>
<string name="cant_open_invalid_url">The item url is invalid. I\'m looking into solving this issue so the app won\'t crash.</string>
<string name="drawer_report_bug">Report a bug</string>
<string name="items_number_should_be_number">The items number should be an integer.</string>
<string name="reader_action_more">Read more</string>
<string name="reader_action_open">Open in browser</string>
<string name="reader_action_share">Share</string>
</resources>

View File

@ -154,4 +154,8 @@
<string name="translation">Translation</string>
<string name="cant_open_invalid_url">The item url is invalid. I\'m looking into solving this issue so the app won\'t crash.</string>
<string name="drawer_report_bug">Report a bug</string>
<string name="items_number_should_be_number">The items number should be an integer.</string>
<string name="reader_action_more">Read more</string>
<string name="reader_action_open">Open in browser</string>
<string name="reader_action_share">Share</string>
</resources>

View File

@ -154,4 +154,8 @@
<string name="translation">Translation</string>
<string name="cant_open_invalid_url">The item url is invalid. I\'m looking into solving this issue so the app won\'t crash.</string>
<string name="drawer_report_bug">Report a bug</string>
<string name="items_number_should_be_number">The items number should be an integer.</string>
<string name="reader_action_more">Read more</string>
<string name="reader_action_open">Open in browser</string>
<string name="reader_action_share">Share</string>
</resources>

View File

@ -154,4 +154,8 @@
<string name="translation">Translation</string>
<string name="cant_open_invalid_url">The item url is invalid. I\'m looking into solving this issue so the app won\'t crash.</string>
<string name="drawer_report_bug">Report a bug</string>
<string name="items_number_should_be_number">The items number should be an integer.</string>
<string name="reader_action_more">Read more</string>
<string name="reader_action_open">Open in browser</string>
<string name="reader_action_share">Share</string>
</resources>

View File

@ -157,4 +157,8 @@
<string name="report_github_user" translatable="false">aminecmi</string>
<string name="report_github_repo" translatable="false">ReaderforSelfoss</string>
<string name="drawer_report_bug">Report a bug</string>
<string name="items_number_should_be_number">The items number should be an integer.</string>
<string name="reader_action_more">Read more</string>
<string name="reader_action_open">Open in browser</string>
<string name="reader_action_share">Share</string>
</resources>

View File

@ -14,6 +14,8 @@
<item name="android:textColorPrimary">@color/md_grey_900</item>
<item name="android:textColorSecondary">@color/md_grey_400</item>
<item name="material_drawer_header_selection_text">@color/md_grey_900</item>
<item name="toolbarPopupTheme">@style/ThemeOverlay.AppCompat.Light</item>
</style>
<style name="NoBarDark" parent="MaterialDrawerTheme">
@ -27,6 +29,8 @@
<item name="android:textColorPrimary">@color/md_white_1000</item>
<item name="android:textColorSecondary">@color/md_grey_600</item>
<item name="material_drawer_header_selection_text">@color/md_grey_900</item>
<item name="toolbarPopupTheme">@style/ThemeOverlay.AppCompat.Dark</item>
</style>
<!-- ToolBar -->
@ -50,6 +54,8 @@
<item name="android:textColorPrimary">@color/md_grey_900</item>
<item name="android:textColorSecondary">@color/md_grey_400</item>
<item name="material_drawer_header_selection_text">@color/md_grey_900</item>
<item name="toolbarPopupTheme">@style/ThemeOverlay.AppCompat.Light</item>
</style>
<style name="NoBarBlueAmberDark" parent="MaterialDrawerTheme">
@ -63,6 +69,8 @@
<item name="android:textColorPrimary">@color/md_white_1000</item>
<item name="android:textColorSecondary">@color/md_grey_600</item>
<item name="material_drawer_header_selection_text">@color/md_grey_900</item>
<item name="toolbarPopupTheme">@style/ThemeOverlay.AppCompat.Dark</item>
</style>
<style name="NoBarGreyOrange" parent="MaterialDrawerTheme.Light">
@ -75,6 +83,8 @@
<item name="android:textColorPrimary">@color/md_grey_900</item>
<item name="android:textColorSecondary">@color/md_grey_400</item>
<item name="material_drawer_header_selection_text">@color/md_grey_900</item>
<item name="toolbarPopupTheme">@style/ThemeOverlay.AppCompat.Light</item>
</style>
<style name="NoBarGreyOrangeDark" parent="MaterialDrawerTheme">
@ -88,6 +98,8 @@
<item name="android:textColorPrimary">@color/md_white_1000</item>
<item name="android:textColorSecondary">@color/md_grey_600</item>
<item name="material_drawer_header_selection_text">@color/md_grey_900</item>
<item name="toolbarPopupTheme">@style/ThemeOverlay.AppCompat.Dark</item>
</style>
<style name="NoBarIndigoPink" parent="MaterialDrawerTheme.Light">
@ -100,6 +112,8 @@
<item name="android:textColorPrimary">@color/md_grey_900</item>
<item name="android:textColorSecondary">@color/md_grey_400</item>
<item name="material_drawer_header_selection_text">@color/md_grey_900</item>
<item name="toolbarPopupTheme">@style/ThemeOverlay.AppCompat.Light</item>
</style>
<style name="NoBarIndigoPinkDark" parent="MaterialDrawerTheme">
@ -113,6 +127,8 @@
<item name="android:textColorPrimary">@color/md_white_1000</item>
<item name="android:textColorSecondary">@color/md_grey_600</item>
<item name="material_drawer_header_selection_text">@color/md_grey_900</item>
<item name="toolbarPopupTheme">@style/ThemeOverlay.AppCompat.Dark</item>
</style>
<style name="NoBarRedTeal" parent="MaterialDrawerTheme.Light">
@ -125,6 +141,8 @@
<item name="android:textColorPrimary">@color/md_grey_900</item>
<item name="android:textColorSecondary">@color/md_grey_400</item>
<item name="material_drawer_header_selection_text">@color/md_grey_900</item>
<item name="toolbarPopupTheme">@style/ThemeOverlay.AppCompat.Light</item>
</style>
<style name="NoBarRedTealDark" parent="MaterialDrawerTheme">
@ -138,6 +156,8 @@
<item name="android:textColorPrimary">@color/md_white_1000</item>
<item name="android:textColorSecondary">@color/md_grey_600</item>
<item name="material_drawer_header_selection_text">@color/md_grey_900</item>
<item name="toolbarPopupTheme">@style/ThemeOverlay.AppCompat.Dark</item>
</style>
<style name="NoBarCyanPink" parent="MaterialDrawerTheme.Light">
@ -150,6 +170,8 @@
<item name="android:textColorPrimary">@color/md_grey_900</item>
<item name="android:textColorSecondary">@color/md_grey_400</item>
<item name="material_drawer_header_selection_text">@color/md_grey_900</item>
<item name="toolbarPopupTheme">@style/ThemeOverlay.AppCompat.Light</item>
</style>
<style name="NoBarCyanPinkDark" parent="MaterialDrawerTheme">
@ -163,6 +185,8 @@
<item name="android:textColorPrimary">@color/md_white_1000</item>
<item name="android:textColorSecondary">@color/md_grey_600</item>
<item name="material_drawer_header_selection_text">@color/md_grey_900</item>
<item name="toolbarPopupTheme">@style/ThemeOverlay.AppCompat.Dark</item>
</style>
@ -176,6 +200,8 @@
<item name="android:textColorPrimary">@color/md_grey_900</item>
<item name="android:textColorSecondary">@color/md_grey_400</item>
<item name="material_drawer_header_selection_text">@color/md_grey_900</item>
<item name="toolbarPopupTheme">@style/ThemeOverlay.AppCompat.Light</item>
</style>
<style name="NoBarTealOrangeDark" parent="MaterialDrawerTheme">
@ -189,6 +215,8 @@
<item name="android:textColorPrimary">@color/md_white_1000</item>
<item name="android:textColorSecondary">@color/md_grey_600</item>
<item name="material_drawer_header_selection_text">@color/md_grey_900</item>
<item name="toolbarPopupTheme">@style/ThemeOverlay.AppCompat.Dark</item>
</style>
<style name="Theme.App.Light" parent="Theme.IssueReporter.Light.DarkActionBar">