Compare commits
106 Commits
Author | SHA1 | Date | |
---|---|---|---|
c17980a032 | |||
a929e419d9 | |||
487d484bae | |||
0ca4c04c61 | |||
c857cf2d67 | |||
acb502028b | |||
533636f3a1 | |||
eb5672901b | |||
53a8716b51 | |||
3aaff612af | |||
fdcd8c6c6a | |||
bafd478604 | |||
987513a88b | |||
a450ab2a3b | |||
db89fe5aad | |||
67a30b92f6 | |||
c397de8c3e | |||
b4db532c45 | |||
ebecc9c80a | |||
4f8556fca8 | |||
68892fb41b | |||
6d6f6c72ac | |||
df5556b945 | |||
d6c74049c3 | |||
18946464a2 | |||
edb5eabee7 | |||
99a305f3e2 | |||
68dc5a6acf | |||
6816461502 | |||
15b93bbd9e | |||
cd61e140f6 | |||
4d861a84e6 | |||
f24de68618 | |||
3bcffff444 | |||
75e9031fa5 | |||
3b77e24399 | |||
0a738e895f | |||
242e5ba035 | |||
c94612106c | |||
320924b4ed | |||
403ecc4521 | |||
6a50b37364 | |||
d9d341ac5d | |||
e9805b731e | |||
c6d4337cd1 | |||
173f4b2ff7 | |||
3b9436264c | |||
35fe87d79d | |||
f1bb7ba9ad | |||
279f229166 | |||
be1794e27b | |||
4d4a2039c8 | |||
3013ae4f35 | |||
bb3f7d3786 | |||
f7cc305e44 | |||
da17f89148 | |||
ec71ab3c6f | |||
0d007f1492 | |||
96f8663b8f | |||
1a4bc1b301 | |||
b51ae58a97 | |||
b126fc32da | |||
b8d234c415 | |||
2c8902d404 | |||
80ad65b196 | |||
744d9ba72b | |||
0c1d708588 | |||
95e79e7c5d | |||
3ce3260d20 | |||
641f4f34d3 | |||
99620cb1c5 | |||
8f5f33f5d2 | |||
78e9230b82 | |||
78aa44c007 | |||
53fd944f00 | |||
9e6cb4ee3d | |||
87ad6f2826 | |||
9050f5a56f | |||
3437004082 | |||
dcf620af87 | |||
128085a02e | |||
302040ec25 | |||
e177c22032 | |||
a11007113a | |||
5e7897bcf4 | |||
9559af3637 | |||
4c499abcdb | |||
0055a503b3 | |||
3a189ee4b6 | |||
e25dc49271 | |||
4208a80db8 | |||
ddb75e0d93 | |||
8b37e992a2 | |||
bac59036cd | |||
6c89a3b77c | |||
dc2ef39fc6 | |||
a4806da2c5 | |||
ee30edb214 | |||
e4ed663fb3 | |||
01629309b0 | |||
059c2991fb | |||
686ec5dd90 | |||
eab9df8ed9 | |||
0107c3d7e2 | |||
2def2f2e2c | |||
44c79892a0 |
3
.github/CONTRIBUTING.md
vendored
@ -8,7 +8,7 @@ Please read the guidelines before contributing, and follow them (or try to) when
|
||||
|
||||
### What you can do to help.
|
||||
|
||||
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.
|
||||
There are many ways to contribute to this project, you could [translate the app](https://crowdin.com/project/readerforselfoss), 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/issues?q=is%3Aissue+is%3Aopen+label%3A%22Up+For+Grabs%22) or [develop new things](https://github.com/aminecmi/ReaderforSelfoss/issues)
|
||||
|
||||
@ -28,6 +28,7 @@ Always check if the web version of your instance is working.
|
||||
|
||||
### Pull requests
|
||||
|
||||
* Don't create a PR for translations. See [here](https://github.com/aminecmi/ReaderforSelfoss/pull/170#issuecomment-355715654) for an explanation why.
|
||||
* 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.
|
||||
|
1
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -5,6 +5,7 @@
|
||||
- [ ] I have updated the documentation accordingly.
|
||||
- [ ] I have added tests to cover my changes.
|
||||
- [ ] All new and existing tests passed.
|
||||
- [ ] This is **NOT** translation related. (See [here](https://github.com/aminecmi/ReaderforSelfoss/pull/170#issuecomment-355715654))
|
||||
|
||||
This closes issue #XXX
|
||||
|
||||
|
48
CHANGELOG.md
@ -1,19 +1,51 @@
|
||||
**1.5.7.x**
|
||||
|
||||
- Added confirmation to the mark as read and update menues.
|
||||
|
||||
- Add to favorites from article viewer.
|
||||
|
||||
- Added an option to use a webview in the article viewer (see #149)
|
||||
|
||||
- Fixes (#151 #152 #155 #157 #160 #174) and more.
|
||||
|
||||
- New year fixes !!!
|
||||
|
||||
- Changed page indicator position as it was overlaping content.
|
||||
|
||||
- Now using slack instead of gitter.
|
||||
|
||||
- Moved completely to a webview to fix #161.
|
||||
|
||||
- Fixed typos in French ( Thanks @aancel )
|
||||
|
||||
- Updated the Contribution guide about translations.
|
||||
|
||||
- Better handling for articles update. (See #169)
|
||||
|
||||
- Ability to change the article viewer content font size (see #153)
|
||||
|
||||
- Versions updates * 2.
|
||||
|
||||
- Added padding to the recyclerview.
|
||||
|
||||
**1.5.5.x (didn't last long) AND 1.5.6.x**
|
||||
|
||||
- Completed Dutch and Indonesian translation !
|
||||
|
||||
- Fixed #142.
|
||||
|
||||
- Added an animation to the viewpager.
|
||||
|
||||
- Changed versions handling.
|
||||
|
||||
- Toolbar in reader activity.
|
||||
|
||||
- Marking items as read on scroll (with settings to enable/disable).
|
||||
|
||||
- Swapped the title and subtitle in the article viewer.
|
||||
|
||||
- Added an animation to the viewpager.
|
||||
|
||||
- Completed Dutch, Indonesian and Portuguese translations !
|
||||
|
||||
- Fixed #142, #144, #147.
|
||||
|
||||
- Changed versions handling.
|
||||
|
||||
- Removed indonesian english as it was causing issues with the english version of the app.
|
||||
|
||||
**1.5.4.22**
|
||||
|
||||
- You can now scroll through the loaded articles !
|
||||
|
@ -1,11 +1,13 @@
|
||||
# ReaderForSelfoss
|
||||
|
||||
[](https://crowdin.com/project/readerforselfoss) [](https://gitter.im/amine-bou/ReaderForSelfoss)
|
||||
[](https://join.slack.com/t/readerforselfoss/shared_invite/enQtMjkyNzc3NjM2Mjc1LTUzZTZhOGM5YjQ1MTI5MWZiODRjMjE1ZDBmMzQxZmQ3NWZhYTNhMTBjNGEwNmE2ZGFjODU5NjUxZjBkMWJmMDQ)
|
||||
|
||||
[](http://jenkins.amine-bou.fr/job/ReaderForSelfoss/)
|
||||
|
||||
[](https://www.codetriage.com/aminecmi/readerforselfoss)
|
||||
|
||||
[](https://crowdin.com/project/readerforselfoss)
|
||||
|
||||
This is the repo of [Reader For Selfoss](https://play.google.com/store/apps/details?id=apps.amine.bou.readerforselfoss&hl=en).
|
||||
|
||||
It's an RSS Reader for Android, that **only** works with [Selfoss](https://selfoss.aditu.de/)
|
||||
@ -23,4 +25,4 @@ Check the [Contribution guide](https://github.com/aminecmi/ReaderforSelfoss/blob
|
||||
- [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)
|
||||
- [Ask for help](https://join.slack.com/t/readerforselfoss/shared_invite/enQtMjkyNzc3NjM2Mjc1LTUzZTZhOGM5YjQ1MTI5MWZiODRjMjE1ZDBmMzQxZmQ3NWZhYTNhMTBjNGEwNmE2ZGFjODU5NjUxZjBkMWJmMDQ)
|
||||
|
@ -12,6 +12,8 @@ ext {
|
||||
configuration = [
|
||||
buildDate: new Date()
|
||||
]
|
||||
// This will make me able to build multiple times a day. May break thinks. I may forget it.
|
||||
todaysBuilds = "1"
|
||||
}
|
||||
|
||||
def gitVersion() {
|
||||
@ -20,19 +22,19 @@ def gitVersion() {
|
||||
}
|
||||
|
||||
def versionCodeFromGit() {
|
||||
def versionCode = gitVersion() + (ext.configuration.buildDate.format("yyMd")).toInteger()
|
||||
def dayInYear = ext.configuration.buildDate.format("D").padLeft(3, '0')
|
||||
def versionCode = gitVersion() + (ext.configuration.buildDate.format("yyMM") + dayInYear + ext.todaysBuilds).toInteger()
|
||||
println "version code " + versionCode
|
||||
return versionCode.toInteger()
|
||||
}
|
||||
|
||||
def versionNameFromGit() {
|
||||
def versionName = gitVersion() + ext.configuration.buildDate.format('yyyyMMddHHmm')
|
||||
def dayInYear = ext.configuration.buildDate.format("D").padLeft(3, '0')
|
||||
def versionName = gitVersion() + ext.configuration.buildDate.format('yyMM') + dayInYear + ext.todaysBuilds
|
||||
println "version name " + versionName
|
||||
return versionName
|
||||
}
|
||||
|
||||
apply plugin: 'org.sonarqube'
|
||||
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
apply plugin: 'io.fabric'
|
||||
@ -49,7 +51,7 @@ repositories {
|
||||
|
||||
android {
|
||||
compileSdkVersion 27
|
||||
buildToolsVersion '27.0.0'
|
||||
buildToolsVersion '27.0.3'
|
||||
defaultConfig {
|
||||
applicationId "apps.amine.bou.readerforselfoss"
|
||||
minSdkVersion 16
|
||||
@ -96,6 +98,7 @@ android {
|
||||
buildConfigField "boolean", "GITHUB_VERSION", "true"
|
||||
}
|
||||
storeConfig {
|
||||
// As jenkins publishes to alpha first, this is the default suffix now.
|
||||
versionNameSuffix '-store'
|
||||
dimension "build"
|
||||
buildConfigField "boolean", "GITHUB_VERSION", "false"
|
||||
@ -105,82 +108,82 @@ android {
|
||||
|
||||
dependencies {
|
||||
// Testing
|
||||
androidTestCompile 'com.android.support.test.espresso:espresso-core:3.0.1'
|
||||
androidTestCompile 'com.android.support.test:runner:1.0.1'
|
||||
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
|
||||
androidTestImplementation 'com.android.support.test:runner:1.0.1'
|
||||
// Espresso-contrib for DatePicker, RecyclerView, Drawer actions, Accessibility checks, CountingIdlingResource
|
||||
androidTestCompile 'com.android.support.test.espresso:espresso-contrib:3.0.1'
|
||||
androidTestImplementation 'com.android.support.test.espresso:espresso-contrib:3.0.1'
|
||||
// Espresso-intents for validation and stubbing of Intents
|
||||
androidTestCompile 'com.android.support.test.espresso:espresso-intents:3.0.1'
|
||||
androidTestImplementation 'com.android.support.test.espresso:espresso-intents:3.0.1'
|
||||
|
||||
|
||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||
compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
|
||||
// Android Support
|
||||
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'
|
||||
implementation 'com.android.support:appcompat-v7:27.1.1'
|
||||
implementation 'com.android.support:design:27.1.1'
|
||||
implementation 'com.android.support:recyclerview-v7:27.1.1'
|
||||
implementation 'com.android.support:support-v4:27.1.1'
|
||||
implementation 'com.android.support:support-vector-drawable:27.1.1'
|
||||
implementation 'com.android.support:customtabs:27.1.1'
|
||||
implementation 'com.android.support:cardview-v7:27.1.1'
|
||||
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
|
||||
|
||||
// Firebase + crashlytics
|
||||
compile 'com.google.firebase:firebase-core:11.4.2'
|
||||
compile 'com.google.firebase:firebase-config:11.4.2'
|
||||
compile 'com.google.firebase:firebase-invites:11.4.2'
|
||||
compile('com.crashlytics.sdk.android:crashlytics:2.8.0@aar') {
|
||||
transitive = true;
|
||||
implementation 'com.google.firebase:firebase-core:12.0.1'
|
||||
implementation 'com.google.firebase:firebase-config:12.0.1'
|
||||
implementation 'com.google.firebase:firebase-invites:12.0.1'
|
||||
implementation('com.crashlytics.sdk.android:crashlytics:2.9.1@aar') {
|
||||
transitive = true
|
||||
}
|
||||
|
||||
//multidex
|
||||
compile 'com.android.support:multidex:1.0.2'
|
||||
implementation 'com.android.support:multidex:1.0.3'
|
||||
|
||||
// Intro
|
||||
compile 'agency.tango.android:material-intro-screen:0.0.5'
|
||||
implementation 'agency.tango.android:material-intro-screen:0.0.5'
|
||||
|
||||
// About
|
||||
compile('com.mikepenz:aboutlibraries:6.0.0@aar') {
|
||||
implementation('com.mikepenz:aboutlibraries:6.0.0@aar') {
|
||||
transitive = true
|
||||
}
|
||||
|
||||
// Retrofit + http logging + okhttp
|
||||
compile 'com.squareup.retrofit2:retrofit:2.3.0'
|
||||
compile 'com.squareup.okhttp3:logging-interceptor:3.9.0'
|
||||
compile 'com.squareup.retrofit2:converter-gson:2.3.0'
|
||||
compile 'com.burgstaller:okhttp-digest:1.12'
|
||||
implementation 'com.squareup.retrofit2:retrofit:2.3.0'
|
||||
implementation 'com.squareup.okhttp3:logging-interceptor:3.9.0'
|
||||
implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
|
||||
implementation 'com.burgstaller:okhttp-digest:1.12'
|
||||
|
||||
// Material-ish things
|
||||
compile 'com.ashokvarma.android:bottom-navigation-bar:2.0.3'
|
||||
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'
|
||||
implementation 'com.ashokvarma.android:bottom-navigation-bar:2.0.3'
|
||||
implementation 'com.github.jd-alexander:LikeButton:0.2.1'
|
||||
implementation 'com.amulyakhare:com.amulyakhare.textdrawable:1.0.1'
|
||||
|
||||
// glide
|
||||
compile 'com.github.bumptech.glide:glide:4.1.1'
|
||||
compile 'com.github.bumptech.glide:okhttp3-integration:4.1.1'
|
||||
implementation 'com.github.bumptech.glide:glide:4.1.1'
|
||||
implementation 'com.github.bumptech.glide:okhttp3-integration:4.1.1'
|
||||
|
||||
// Asking politely users to rate the app
|
||||
compile 'com.github.stkent:amplify:2.1.0'
|
||||
|
||||
// For the article reader
|
||||
compile 'com.klinkerapps:drag-dismiss-activity:1.5.0'
|
||||
implementation 'com.github.stkent:amplify:2.1.0'
|
||||
|
||||
// Drawer
|
||||
implementation 'co.zsmb:materialdrawer-kt:1.2.1'
|
||||
compile 'com.anupcowkur:reservoir:3.1.0'
|
||||
implementation 'com.anupcowkur:reservoir:3.1.0'
|
||||
|
||||
// Themes
|
||||
compile 'com.52inc:scoops:1.0.0'
|
||||
implementation 'com.52inc:scoops:1.0.0'
|
||||
implementation'com.jrummyapps:colorpicker:2.1.7'
|
||||
|
||||
// Github issues reporter
|
||||
compile 'com.heinrichreimersoftware:android-issue-reporter:1.3.1'
|
||||
implementation 'com.heinrichreimersoftware:android-issue-reporter:1.3.1'
|
||||
|
||||
compile 'com.github.rubensousa:floatingtoolbar:1.5.1'
|
||||
implementation 'com.github.rubensousa:floatingtoolbar:1.5.1'
|
||||
|
||||
// Pager
|
||||
compile 'me.relex:circleindicator:1.2.2@aar'
|
||||
implementation 'me.relex:circleindicator:1.2.2@aar'
|
||||
|
||||
implementation 'androidx.core:core-ktx:0.3'
|
||||
|
||||
}
|
||||
|
||||
apply plugin: 'com.google.gms.google-services'
|
||||
|
10
app/proguard-rules.pro
vendored
@ -48,7 +48,11 @@
|
||||
#}
|
||||
-dontwarn okio.**
|
||||
-dontwarn retrofit2.Platform$Java8
|
||||
-keepattributes Signature
|
||||
-keep class retrofit.** { *; }
|
||||
-keepclasseswithmembers class * {
|
||||
@retrofit.http.* <methods>;
|
||||
}
|
||||
-keepattributes *Annotation*,Signature
|
||||
-keepattributes Exceptions
|
||||
-dontwarn okio.**
|
||||
-dontwarn javax.annotation.Nullable
|
||||
@ -69,4 +73,6 @@
|
||||
|
||||
-dontwarn com.anupcowkur.reservoir.**
|
||||
|
||||
-dontwarn javax.annotation.**
|
||||
-dontwarn javax.annotation.**
|
||||
|
||||
-keep class android.support.v7.widget.SearchView { *; }
|
@ -1,8 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="apps.amine.bou.readerforselfoss">
|
||||
package="apps.amine.bou.readerforselfoss"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<!-- Remove unwanted permissions from Crashlytics.. see https://www.reddit.com/r/androiddev/comments/86c02l/google_play_services_1200_released/dw4ehln/?context=0 -->
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" tools:node="remove" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" tools:node="remove" />
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE" tools:node="remove" />
|
||||
|
||||
<!-- For firebase only -->
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
@ -71,6 +77,14 @@
|
||||
<meta-data
|
||||
android:name="apps.amine.bou.readerforselfoss.utils.glide.SelfSignedGlideModule"
|
||||
android:value="GlideModule" />
|
||||
|
||||
<meta-data android:name="android.webkit.WebView.MetricsOptOut"
|
||||
android:value="true" />
|
||||
|
||||
<meta-data android:name="android.webkit.WebView.EnableSafeBrowsing"
|
||||
android:value="true" />
|
||||
|
||||
<meta-data android:name="android.max_aspect" android:value="2.1" />
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
</manifest>
|
||||
|
@ -1,6 +1,7 @@
|
||||
package apps.amine.bou.readerforselfoss
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.preference.PreferenceManager
|
||||
import android.support.constraint.ConstraintLayout
|
||||
@ -16,6 +17,8 @@ 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.themes.AppColors
|
||||
import apps.amine.bou.readerforselfoss.themes.Toppings
|
||||
import apps.amine.bou.readerforselfoss.utils.Config
|
||||
import apps.amine.bou.readerforselfoss.utils.isBaseUrlValid
|
||||
import com.ftinc.scoop.Scoop
|
||||
@ -23,29 +26,69 @@ import kotlinx.android.synthetic.main.activity_add_source.*
|
||||
import retrofit2.Call
|
||||
import retrofit2.Callback
|
||||
import retrofit2.Response
|
||||
import android.graphics.PorterDuff
|
||||
|
||||
|
||||
|
||||
class AddSourceActivity : AppCompatActivity() {
|
||||
|
||||
private var mSpoutsValue: String? = null
|
||||
private lateinit var api: SelfossApi
|
||||
|
||||
private lateinit var appColors: AppColors
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
appColors = AppColors(this@AddSourceActivity)
|
||||
|
||||
super.onCreate(savedInstanceState)
|
||||
Scoop.getInstance().apply(this)
|
||||
|
||||
setContentView(R.layout.activity_add_source)
|
||||
|
||||
// TODO: input bubble cursor
|
||||
Scoop.getInstance()
|
||||
.bind(this, Toppings.PRIMARY.value, toolbar)
|
||||
.bindStatusBar(this, Toppings.PRIMARY_DARK.value)
|
||||
|
||||
val drawable = nameInput.background
|
||||
drawable.setColorFilter(appColors.colorAccent, PorterDuff.Mode.SRC_ATOP)
|
||||
|
||||
|
||||
// TODO: clean
|
||||
if(Build.VERSION.SDK_INT > 16) {
|
||||
nameInput.background = drawable
|
||||
} else{
|
||||
nameInput.setBackgroundDrawable(drawable)
|
||||
}
|
||||
|
||||
val drawable1 = sourceUri.background
|
||||
drawable1.setColorFilter(appColors.colorAccent, PorterDuff.Mode.SRC_ATOP)
|
||||
|
||||
if(Build.VERSION.SDK_INT > 16) {
|
||||
sourceUri.background = drawable1
|
||||
} else{
|
||||
sourceUri.setBackgroundDrawable(drawable1)
|
||||
}
|
||||
|
||||
val drawable2 = tags.background
|
||||
drawable2.setColorFilter(appColors.colorAccent, PorterDuff.Mode.SRC_ATOP)
|
||||
|
||||
if(Build.VERSION.SDK_INT > 16) {
|
||||
tags.background = drawable2
|
||||
} else{
|
||||
tags.setBackgroundDrawable(drawable2)
|
||||
}
|
||||
|
||||
setSupportActionBar(toolbar)
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
supportActionBar?.setDisplayShowHomeEnabled(true)
|
||||
|
||||
var api: SelfossApi? = null
|
||||
|
||||
try {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(this)
|
||||
api = SelfossApi(
|
||||
this,
|
||||
this@AddSourceActivity,
|
||||
prefs.getBoolean("isSelfSignedCert", false),
|
||||
prefs.getBoolean("should_log_everything", false)
|
||||
this,
|
||||
this@AddSourceActivity,
|
||||
prefs.getBoolean("isSelfSignedCert", false),
|
||||
prefs.getBoolean("should_log_everything", false)
|
||||
)
|
||||
} catch (e: IllegalArgumentException) {
|
||||
mustLoginToAddSource()
|
||||
@ -53,10 +96,15 @@ class AddSourceActivity : AppCompatActivity() {
|
||||
|
||||
maybeGetDetailsFromIntentSharing(intent, sourceUri, nameInput)
|
||||
|
||||
saveBtn.setTextColor(appColors.colorAccent)
|
||||
|
||||
saveBtn.setOnClickListener {
|
||||
handleSaveSource(tags, nameInput.text.toString(), sourceUri.text.toString(), api!!)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
val config = Config(this)
|
||||
|
||||
if (config.baseUrl.isEmpty() || !config.baseUrl.isBaseUrlValid()) {
|
||||
@ -67,16 +115,18 @@ class AddSourceActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
private fun handleSpoutsSpinner(
|
||||
spoutsSpinner: Spinner,
|
||||
api: SelfossApi?,
|
||||
mProgress: ProgressBar,
|
||||
formContainer: ConstraintLayout
|
||||
spoutsSpinner: Spinner,
|
||||
api: SelfossApi?,
|
||||
mProgress: ProgressBar,
|
||||
formContainer: ConstraintLayout
|
||||
) {
|
||||
val spoutsKV = HashMap<String, String>()
|
||||
spoutsSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||
override fun onItemSelected(adapterView: AdapterView<*>, view: View, i: Int, l: Long) {
|
||||
val spoutName = (view as TextView).text.toString()
|
||||
mSpoutsValue = spoutsKV[spoutName]
|
||||
override fun onItemSelected(adapterView: AdapterView<*>, view: View?, i: Int, l: Long) {
|
||||
if (view != null) {
|
||||
val spoutName = (view as TextView).text.toString()
|
||||
mSpoutsValue = spoutsKV[spoutName]
|
||||
}
|
||||
}
|
||||
|
||||
override fun onNothingSelected(adapterView: AdapterView<*>) {
|
||||
@ -87,26 +137,26 @@ class AddSourceActivity : AppCompatActivity() {
|
||||
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>>
|
||||
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)
|
||||
spoutsKV[value.name] = key
|
||||
}
|
||||
|
||||
mProgress.visibility = View.GONE
|
||||
formContainer.visibility = View.VISIBLE
|
||||
|
||||
val spinnerArrayAdapter =
|
||||
ArrayAdapter(
|
||||
this@AddSourceActivity,
|
||||
android.R.layout.simple_spinner_item,
|
||||
itemsStrings
|
||||
)
|
||||
ArrayAdapter(
|
||||
this@AddSourceActivity,
|
||||
android.R.layout.simple_spinner_item,
|
||||
itemsStrings
|
||||
)
|
||||
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||
spoutsSpinner.adapter = spinnerArrayAdapter
|
||||
} else {
|
||||
@ -120,9 +170,9 @@ class AddSourceActivity : AppCompatActivity() {
|
||||
|
||||
private fun handleProblemWithSpouts() {
|
||||
Toast.makeText(
|
||||
this@AddSourceActivity,
|
||||
R.string.cant_get_spouts,
|
||||
Toast.LENGTH_SHORT
|
||||
this@AddSourceActivity,
|
||||
R.string.cant_get_spouts,
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
mProgress.visibility = View.GONE
|
||||
}
|
||||
@ -130,9 +180,9 @@ class AddSourceActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
private fun maybeGetDetailsFromIntentSharing(
|
||||
intent: Intent,
|
||||
sourceUri: EditText,
|
||||
nameInput: EditText
|
||||
intent: Intent,
|
||||
sourceUri: EditText,
|
||||
nameInput: EditText
|
||||
) {
|
||||
if (Intent.ACTION_SEND == intent.action && "text/plain" == intent.type) {
|
||||
sourceUri.setText(intent.getStringExtra(Intent.EXTRA_TEXT))
|
||||
@ -149,38 +199,39 @@ class AddSourceActivity : AppCompatActivity() {
|
||||
|
||||
private fun handleSaveSource(tags: EditText, title: String, url: String, api: SelfossApi) {
|
||||
|
||||
val sourceDetailsAvailable = 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(
|
||||
title,
|
||||
url,
|
||||
mSpoutsValue!!,
|
||||
tags.text.toString(),
|
||||
""
|
||||
title,
|
||||
url,
|
||||
mSpoutsValue!!,
|
||||
tags.text.toString(),
|
||||
""
|
||||
).enqueue(object : Callback<SuccessResponse> {
|
||||
override fun onResponse(
|
||||
call: Call<SuccessResponse>,
|
||||
response: Response<SuccessResponse>
|
||||
call: Call<SuccessResponse>,
|
||||
response: Response<SuccessResponse>
|
||||
) {
|
||||
if (response.body() != null && response.body()!!.isSuccess) {
|
||||
finish()
|
||||
} else {
|
||||
Toast.makeText(
|
||||
this@AddSourceActivity,
|
||||
R.string.cant_create_source,
|
||||
Toast.LENGTH_SHORT
|
||||
this@AddSourceActivity,
|
||||
R.string.cant_create_source,
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<SuccessResponse>, t: Throwable) {
|
||||
Toast.makeText(
|
||||
this@AddSourceActivity,
|
||||
R.string.cant_create_source,
|
||||
Toast.LENGTH_SHORT
|
||||
this@AddSourceActivity,
|
||||
R.string.cant_create_source,
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
})
|
||||
|
@ -18,42 +18,42 @@ class IntroActivity : MaterialIntroActivity() {
|
||||
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
|
||||
|
||||
addSlide(
|
||||
SlideFragmentBuilder()
|
||||
.backgroundColor(R.color.colorPrimary)
|
||||
.buttonsColor(R.color.colorAccent)
|
||||
.image(R.drawable.web_hi_res_512)
|
||||
.title(getString(R.string.intro_hello_title))
|
||||
.description(getString(R.string.intro_hello_message))
|
||||
.build()
|
||||
SlideFragmentBuilder()
|
||||
.backgroundColor(R.color.colorPrimary)
|
||||
.buttonsColor(R.color.colorAccent)
|
||||
.image(R.drawable.web_hi_res_512)
|
||||
.title(getString(R.string.intro_hello_title))
|
||||
.description(getString(R.string.intro_hello_message))
|
||||
.build()
|
||||
)
|
||||
|
||||
addSlide(
|
||||
SlideFragmentBuilder()
|
||||
.backgroundColor(R.color.colorAccent)
|
||||
.buttonsColor(R.color.colorPrimary)
|
||||
.image(R.drawable.ic_info_outline_white_48px)
|
||||
.title(getString(R.string.intro_needs_selfoss_title))
|
||||
.description(getString(R.string.intro_needs_selfoss_message))
|
||||
.build(),
|
||||
MessageButtonBehaviour(
|
||||
View.OnClickListener {
|
||||
val browserIntent = Intent(
|
||||
Intent.ACTION_VIEW,
|
||||
Uri.parse("https://selfoss.aditu.de")
|
||||
)
|
||||
startActivity(browserIntent)
|
||||
}, getString(R.string.intro_needs_selfoss_link)
|
||||
)
|
||||
SlideFragmentBuilder()
|
||||
.backgroundColor(R.color.colorAccent)
|
||||
.buttonsColor(R.color.colorPrimary)
|
||||
.image(R.drawable.ic_info_outline_white_48px)
|
||||
.title(getString(R.string.intro_needs_selfoss_title))
|
||||
.description(getString(R.string.intro_needs_selfoss_message))
|
||||
.build(),
|
||||
MessageButtonBehaviour(
|
||||
View.OnClickListener {
|
||||
val browserIntent = Intent(
|
||||
Intent.ACTION_VIEW,
|
||||
Uri.parse("https://selfoss.aditu.de")
|
||||
)
|
||||
startActivity(browserIntent)
|
||||
}, getString(R.string.intro_needs_selfoss_link)
|
||||
)
|
||||
)
|
||||
|
||||
addSlide(
|
||||
SlideFragmentBuilder()
|
||||
.backgroundColor(R.color.colorPrimaryDark)
|
||||
.buttonsColor(R.color.colorAccentDark)
|
||||
.image(R.drawable.ic_thumb_up_white_48px)
|
||||
.title(getString(R.string.intro_all_set_title))
|
||||
.description(getString(R.string.intro_all_set_message))
|
||||
.build()
|
||||
SlideFragmentBuilder()
|
||||
.backgroundColor(R.color.colorPrimaryDark)
|
||||
.buttonsColor(R.color.colorAccentDark)
|
||||
.image(R.drawable.ic_thumb_up_white_48px)
|
||||
.title(getString(R.string.intro_all_set_title))
|
||||
.description(getString(R.string.intro_all_set_message))
|
||||
.build()
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -17,10 +17,10 @@ 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.themes.AppColors
|
||||
import apps.amine.bou.readerforselfoss.utils.Config
|
||||
import apps.amine.bou.readerforselfoss.utils.isBaseUrlValid
|
||||
import com.crashlytics.android.Crashlytics
|
||||
import com.ftinc.scoop.Scoop
|
||||
import com.google.firebase.analytics.FirebaseAnalytics
|
||||
import com.mikepenz.aboutlibraries.Libs
|
||||
import com.mikepenz.aboutlibraries.LibsBuilder
|
||||
@ -41,10 +41,13 @@ class LoginActivity : AppCompatActivity() {
|
||||
private lateinit var firebaseAnalytics: FirebaseAnalytics
|
||||
private lateinit var userIdentifier: String
|
||||
private var logErrors: Boolean = false
|
||||
private lateinit var appColors: AppColors
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
appColors = AppColors(this@LoginActivity)
|
||||
|
||||
super.onCreate(savedInstanceState)
|
||||
Scoop.getInstance().apply(this)
|
||||
|
||||
setContentView(R.layout.activity_login)
|
||||
|
||||
setSupportActionBar(toolbar)
|
||||
@ -77,13 +80,13 @@ class LoginActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
passwordView.setOnEditorActionListener(
|
||||
TextView.OnEditorActionListener { _, id, _ ->
|
||||
if (id == R.id.loginView || id == EditorInfo.IME_NULL) {
|
||||
attemptLogin()
|
||||
return@OnEditorActionListener true
|
||||
}
|
||||
false
|
||||
TextView.OnEditorActionListener { _, id, _ ->
|
||||
if (id == R.id.loginView || id == EditorInfo.IME_NULL) {
|
||||
attemptLogin()
|
||||
return@OnEditorActionListener true
|
||||
}
|
||||
false
|
||||
}
|
||||
)
|
||||
|
||||
signInButton.setOnClickListener { attemptLogin() }
|
||||
@ -111,9 +114,9 @@ class LoginActivity : AppCompatActivity() {
|
||||
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.BUTTON_NEUTRAL,
|
||||
"OK",
|
||||
{ dialog, _ -> dialog.dismiss() }
|
||||
)
|
||||
alertDialog.show()
|
||||
}
|
||||
@ -154,9 +157,9 @@ class LoginActivity : AppCompatActivity() {
|
||||
alertDialog.setTitle(getString(R.string.warning_wrong_url))
|
||||
alertDialog.setMessage(getString(R.string.text_wrong_url))
|
||||
alertDialog.setButton(
|
||||
AlertDialog.BUTTON_NEUTRAL,
|
||||
"OK",
|
||||
{ dialog, _ -> dialog.dismiss() }
|
||||
AlertDialog.BUTTON_NEUTRAL,
|
||||
"OK",
|
||||
{ dialog, _ -> dialog.dismiss() }
|
||||
)
|
||||
alertDialog.show()
|
||||
inValidCount = 0
|
||||
@ -191,10 +194,10 @@ class LoginActivity : AppCompatActivity() {
|
||||
editor.apply()
|
||||
|
||||
val api = SelfossApi(
|
||||
this,
|
||||
this@LoginActivity,
|
||||
isWithSelfSignedCert,
|
||||
isWithSelfSignedCert
|
||||
this,
|
||||
this@LoginActivity,
|
||||
isWithSelfSignedCert,
|
||||
isWithSelfSignedCert
|
||||
)
|
||||
api.login().enqueue(object : Callback<SuccessResponse> {
|
||||
private fun preferenceError(t: Throwable) {
|
||||
@ -214,17 +217,17 @@ class LoginActivity : AppCompatActivity() {
|
||||
Crashlytics.log(100, "LOGIN_DEBUG_ERRROR", t.message)
|
||||
Crashlytics.logException(t)
|
||||
Toast.makeText(
|
||||
this@LoginActivity,
|
||||
t.message,
|
||||
Toast.LENGTH_LONG
|
||||
this@LoginActivity,
|
||||
t.message,
|
||||
Toast.LENGTH_LONG
|
||||
).show()
|
||||
}
|
||||
showProgress(false)
|
||||
}
|
||||
|
||||
override fun onResponse(
|
||||
call: Call<SuccessResponse>,
|
||||
response: Response<SuccessResponse>
|
||||
call: Call<SuccessResponse>,
|
||||
response: Response<SuccessResponse>
|
||||
) {
|
||||
if (response.body() != null && response.body()!!.isSuccess) {
|
||||
firebaseAnalytics.logEvent(FirebaseAnalytics.Event.LOGIN, Bundle())
|
||||
@ -246,28 +249,28 @@ class LoginActivity : AppCompatActivity() {
|
||||
|
||||
loginForm.visibility = if (show) View.GONE else View.VISIBLE
|
||||
loginForm
|
||||
.animate()
|
||||
.setDuration(shortAnimTime.toLong())
|
||||
.alpha(
|
||||
if (show) 0F else 1F
|
||||
).setListener(object : AnimatorListenerAdapter() {
|
||||
override fun onAnimationEnd(animation: Animator) {
|
||||
loginForm.visibility = if (show) View.GONE else View.VISIBLE
|
||||
}
|
||||
}
|
||||
.animate()
|
||||
.setDuration(shortAnimTime.toLong())
|
||||
.alpha(
|
||||
if (show) 0F else 1F
|
||||
).setListener(object : AnimatorListenerAdapter() {
|
||||
override fun onAnimationEnd(animation: Animator) {
|
||||
loginForm.visibility = if (show) View.GONE else View.VISIBLE
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
loginProgress.visibility = if (show) View.VISIBLE else View.GONE
|
||||
loginProgress
|
||||
.animate()
|
||||
.setDuration(shortAnimTime.toLong())
|
||||
.alpha(
|
||||
if (show) 1F else 0F
|
||||
).setListener(object : AnimatorListenerAdapter() {
|
||||
override fun onAnimationEnd(animation: Animator) {
|
||||
loginProgress.visibility = if (show) View.VISIBLE else View.GONE
|
||||
}
|
||||
}
|
||||
.animate()
|
||||
.setDuration(shortAnimTime.toLong())
|
||||
.alpha(
|
||||
if (show) 1F else 0F
|
||||
).setListener(object : AnimatorListenerAdapter() {
|
||||
override fun onAnimationEnd(animation: Animator) {
|
||||
loginProgress.visibility = if (show) View.VISIBLE else View.GONE
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@ -281,10 +284,10 @@ class LoginActivity : AppCompatActivity() {
|
||||
when (item.itemId) {
|
||||
R.id.about -> {
|
||||
LibsBuilder()
|
||||
.withActivityStyle(Libs.ActivityStyle.LIGHT_DARK_TOOLBAR)
|
||||
.withAboutIconShown(true)
|
||||
.withAboutVersionShown(true)
|
||||
.start(this)
|
||||
.withActivityStyle(Libs.ActivityStyle.LIGHT_DARK_TOOLBAR)
|
||||
.withAboutIconShown(true)
|
||||
.withAboutVersionShown(true)
|
||||
.start(this)
|
||||
return true
|
||||
}
|
||||
R.id.login_debug -> {
|
||||
|
@ -14,7 +14,7 @@ class MainActivity : AppCompatActivity() {
|
||||
if (PreferenceManager.getDefaultSharedPreferences(baseContext).getBoolean(
|
||||
"firstStart",
|
||||
true
|
||||
)) {
|
||||
)) {
|
||||
val i = Intent(this@MainActivity, IntroActivity::class.java)
|
||||
startActivity(i)
|
||||
} else {
|
||||
|
@ -47,9 +47,9 @@ class MyApp : MultiDexApplication() {
|
||||
|
||||
private fun initAmplify() {
|
||||
Amplify.initSharedInstance(this)
|
||||
.setPositiveFeedbackCollectors(GooglePlayStoreFeedbackCollector())
|
||||
.setCriticalFeedbackCollectors(DefaultEmailFeedbackCollector(BuildConfig.FEEDBACK_EMAIL))
|
||||
.applyAllDefaultRules()
|
||||
.setPositiveFeedbackCollectors(GooglePlayStoreFeedbackCollector())
|
||||
.setCriticalFeedbackCollectors(DefaultEmailFeedbackCollector(BuildConfig.FEEDBACK_EMAIL))
|
||||
.applyAllDefaultRules()
|
||||
}
|
||||
|
||||
private fun initCache() {
|
||||
@ -63,15 +63,15 @@ class MyApp : MultiDexApplication() {
|
||||
private fun initDrawerImageLoader() {
|
||||
DrawerImageLoader.init(object : AbstractDrawerImageLoader() {
|
||||
override fun set(
|
||||
imageView: ImageView?,
|
||||
uri: Uri?,
|
||||
placeholder: Drawable?,
|
||||
tag: String?
|
||||
imageView: ImageView?,
|
||||
uri: Uri?,
|
||||
placeholder: Drawable?,
|
||||
tag: String?
|
||||
) {
|
||||
Glide.with(imageView?.context)
|
||||
.load(uri)
|
||||
.apply(RequestOptions.fitCenterTransform().placeholder(placeholder))
|
||||
.into(imageView)
|
||||
.load(uri)
|
||||
.apply(RequestOptions.fitCenterTransform().placeholder(placeholder))
|
||||
.into(imageView)
|
||||
}
|
||||
|
||||
override fun cancel(imageView: ImageView?) {
|
||||
@ -86,22 +86,10 @@ class MyApp : MultiDexApplication() {
|
||||
|
||||
private fun initTheme() {
|
||||
Scoop.waffleCone()
|
||||
.addFlavor(getString(R.string.default_theme), R.style.NoBar, true)
|
||||
.addFlavor(getString(R.string.default_dark_theme), R.style.NoBarDark)
|
||||
.addFlavor(getString(R.string.teal_orange_theme), R.style.NoBarTealOrange)
|
||||
.addFlavor(getString(R.string.teal_orange_dark_theme), R.style.NoBarTealOrangeDark)
|
||||
.addFlavor(getString(R.string.cyan_pink_theme), R.style.NoBarCyanPink)
|
||||
.addFlavor(getString(R.string.cyan_pink_dark_theme), R.style.NoBarCyanPinkDark)
|
||||
.addFlavor(getString(R.string.grey_orange_theme), R.style.NoBarGreyOrange)
|
||||
.addFlavor(getString(R.string.grey_orange_dark_theme), R.style.NoBarGreyOrangeDark)
|
||||
.addFlavor(getString(R.string.blue_amber_theme), R.style.NoBarBlueAmber)
|
||||
.addFlavor(getString(R.string.blue_amber_dark_theme), R.style.NoBarBlueAmberDark)
|
||||
.addFlavor(getString(R.string.indigo_pink_theme), R.style.NoBarIndigoPink)
|
||||
.addFlavor(getString(R.string.indigo_pink_dark_theme), R.style.NoBarIndigoPinkDark)
|
||||
.addFlavor(getString(R.string.red_teal_theme), R.style.NoBarRedTeal)
|
||||
.addFlavor(getString(R.string.red_teal_dark_theme), R.style.NoBarRedTealDark)
|
||||
.setSharedPreferences(PreferenceManager.getDefaultSharedPreferences(this))
|
||||
.initialize()
|
||||
.addFlavor(getString(R.string.default_theme), R.style.NoBar, true)
|
||||
.addFlavor(getString(R.string.default_dark_theme), R.style.NoBarDark, false)
|
||||
.setSharedPreferences(PreferenceManager.getDefaultSharedPreferences(this))
|
||||
.initialize()
|
||||
}
|
||||
|
||||
private fun tryToHandleBug() {
|
||||
@ -109,8 +97,8 @@ class MyApp : MultiDexApplication() {
|
||||
|
||||
Thread.setDefaultUncaughtExceptionHandler { thread, e ->
|
||||
if (e is java.lang.NoClassDefFoundError && e.stackTrace.asList().any {
|
||||
it.toString().contains("android.view.ViewDebug")
|
||||
}) {
|
||||
it.toString().contains("android.view.ViewDebug")
|
||||
}) {
|
||||
Unit
|
||||
} else {
|
||||
oldHandler.uncaughtException(thread, e)
|
||||
|
@ -1,20 +1,26 @@
|
||||
package apps.amine.bou.readerforselfoss
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.Resources
|
||||
import android.os.Bundle
|
||||
import android.preference.PreferenceManager
|
||||
import android.support.v4.app.FragmentManager
|
||||
import android.support.v4.app.FragmentStatePagerAdapter
|
||||
import android.support.v4.view.ViewPager
|
||||
import android.support.v7.app.AppCompatActivity
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.widget.Toast
|
||||
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.fragments.ArticleFragment
|
||||
import apps.amine.bou.readerforselfoss.themes.AppColors
|
||||
import apps.amine.bou.readerforselfoss.themes.Toppings
|
||||
import apps.amine.bou.readerforselfoss.transformers.DepthPageTransformer
|
||||
import apps.amine.bou.readerforselfoss.utils.Config
|
||||
import apps.amine.bou.readerforselfoss.utils.succeeded
|
||||
import apps.amine.bou.readerforselfoss.utils.toggleStar
|
||||
import com.crashlytics.android.Crashlytics
|
||||
import com.ftinc.scoop.Scoop
|
||||
import kotlinx.android.synthetic.main.activity_reader.*
|
||||
@ -25,13 +31,39 @@ import retrofit2.Response
|
||||
|
||||
class ReaderActivity : AppCompatActivity() {
|
||||
|
||||
private lateinit var allItems: ArrayList<Item>
|
||||
private var markOnScroll: Boolean = false
|
||||
private var debugReadingItems: Boolean = false
|
||||
private var currentItem: Int = 0
|
||||
private lateinit var userIdentifier: String
|
||||
|
||||
private lateinit var api: SelfossApi
|
||||
|
||||
private lateinit var toolbarMenu: Menu
|
||||
|
||||
private fun showMenuItem(willAddToFavorite: Boolean) {
|
||||
toolbarMenu.findItem(R.id.save).isVisible = willAddToFavorite
|
||||
toolbarMenu.findItem(R.id.unsave).isVisible = !willAddToFavorite
|
||||
}
|
||||
|
||||
private fun canFavorite() {
|
||||
showMenuItem(true)
|
||||
}
|
||||
|
||||
private fun canRemoveFromFavorite() {
|
||||
showMenuItem(false)
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
val appColors = AppColors(this@ReaderActivity)
|
||||
|
||||
super.onCreate(savedInstanceState)
|
||||
Scoop.getInstance().apply(this)
|
||||
|
||||
setContentView(R.layout.activity_reader)
|
||||
|
||||
Scoop.getInstance()
|
||||
.bind(this, Toppings.PRIMARY.value, toolBar)
|
||||
.bindStatusBar(this, Toppings.PRIMARY_DARK.value)
|
||||
|
||||
setSupportActionBar(toolBar)
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
supportActionBar?.setDisplayShowHomeEnabled(true)
|
||||
@ -39,79 +71,112 @@ class ReaderActivity : AppCompatActivity() {
|
||||
val settings = getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE)
|
||||
val sharedPref = PreferenceManager.getDefaultSharedPreferences(this)
|
||||
|
||||
val debugReadingItems = sharedPref.getBoolean("read_debug", false)
|
||||
val userIdentifier = sharedPref.getString("unique_id", "")
|
||||
val markOnScroll = sharedPref.getBoolean("mark_on_scroll", false)
|
||||
debugReadingItems = sharedPref.getBoolean("read_debug", false)
|
||||
userIdentifier = sharedPref.getString("unique_id", "")
|
||||
markOnScroll = sharedPref.getBoolean("mark_on_scroll", false)
|
||||
|
||||
val api = SelfossApi(
|
||||
this,
|
||||
this@ReaderActivity,
|
||||
settings.getBoolean("isSelfSignedCert", false),
|
||||
sharedPref.getBoolean("should_log_everything", false)
|
||||
if (allItems.isEmpty()) {
|
||||
finish()
|
||||
}
|
||||
|
||||
api = SelfossApi(
|
||||
this,
|
||||
this@ReaderActivity,
|
||||
settings.getBoolean("isSelfSignedCert", false),
|
||||
sharedPref.getBoolean("should_log_everything", false)
|
||||
)
|
||||
|
||||
allItems = intent.getParcelableArrayListExtra<Item>("allItems")
|
||||
val currentItem = intent.getIntExtra("currentItem", 0)
|
||||
currentItem = intent.getIntExtra("currentItem", 0)
|
||||
|
||||
var adapter = ScreenSlidePagerAdapter(supportFragmentManager)
|
||||
pager.adapter = adapter
|
||||
pager.adapter = ScreenSlidePagerAdapter(supportFragmentManager)
|
||||
pager.currentItem = currentItem
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
|
||||
(pager.adapter as ScreenSlidePagerAdapter).notifyDataSetChanged()
|
||||
|
||||
pager.setPageTransformer(true, DepthPageTransformer())
|
||||
(indicator as CircleIndicator).setViewPager(pager)
|
||||
|
||||
if (markOnScroll) {
|
||||
pager.addOnPageChangeListener(object : ViewPager.SimpleOnPageChangeListener() {
|
||||
pager.addOnPageChangeListener(
|
||||
object : ViewPager.SimpleOnPageChangeListener() {
|
||||
var isLastItem = false
|
||||
|
||||
override fun onPageSelected(position: Int) {
|
||||
isLastItem = (position === (allItems.size - 1))
|
||||
|
||||
if (allItems[position].starred) {
|
||||
canRemoveFromFavorite()
|
||||
} else {
|
||||
canFavorite()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPageScrollStateChanged(state: Int) {
|
||||
if (state === ViewPager.SCROLL_STATE_DRAGGING || (state === ViewPager.SCROLL_STATE_IDLE && isLastItem)) {
|
||||
if (markOnScroll && (state === ViewPager.SCROLL_STATE_DRAGGING || (state === ViewPager.SCROLL_STATE_IDLE && isLastItem))) {
|
||||
api.markItem(allItems[pager.currentItem].id).enqueue(
|
||||
object : Callback<SuccessResponse> {
|
||||
override fun onResponse(
|
||||
call: Call<SuccessResponse>,
|
||||
response: Response<SuccessResponse>
|
||||
) {
|
||||
if (!response.succeeded() && debugReadingItems) {
|
||||
val message =
|
||||
"message: ${response.message()} " +
|
||||
"response isSuccess: ${response.isSuccessful} " +
|
||||
"response code: ${response.code()} " +
|
||||
"response message: ${response.message()} " +
|
||||
"response errorBody: ${response.errorBody()?.string()} " +
|
||||
"body success: ${response.body()?.success} " +
|
||||
"body isSuccess: ${response.body()?.isSuccess}"
|
||||
Crashlytics.setUserIdentifier(userIdentifier)
|
||||
Crashlytics.log(100, "READ_DEBUG_SUCCESS", message)
|
||||
Crashlytics.logException(Exception("Was success, but did it work ?"))
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<SuccessResponse>, t: Throwable) {
|
||||
if (debugReadingItems) {
|
||||
Crashlytics.setUserIdentifier(userIdentifier)
|
||||
Crashlytics.log(100, "READ_DEBUG_ERROR", t.message)
|
||||
Crashlytics.logException(t)
|
||||
}
|
||||
object : Callback<SuccessResponse> {
|
||||
override fun onResponse(
|
||||
call: Call<SuccessResponse>,
|
||||
response: Response<SuccessResponse>
|
||||
) {
|
||||
if (!response.succeeded() && debugReadingItems) {
|
||||
val message =
|
||||
"message: ${response.message()} " +
|
||||
"response isSuccess: ${response.isSuccessful} " +
|
||||
"response code: ${response.code()} " +
|
||||
"response message: ${response.message()} " +
|
||||
"response errorBody: ${response.errorBody()?.string()} " +
|
||||
"body success: ${response.body()?.success} " +
|
||||
"body isSuccess: ${response.body()?.isSuccess}"
|
||||
Crashlytics.setUserIdentifier(userIdentifier)
|
||||
Crashlytics.log(
|
||||
100,
|
||||
"READ_DEBUG_SUCCESS",
|
||||
message
|
||||
)
|
||||
Crashlytics.logException(Exception("Was success, but did it work ?"))
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(
|
||||
call: Call<SuccessResponse>,
|
||||
t: Throwable
|
||||
) {
|
||||
if (debugReadingItems) {
|
||||
Crashlytics.setUserIdentifier(userIdentifier)
|
||||
Crashlytics.log(
|
||||
100,
|
||||
"READ_DEBUG_ERROR",
|
||||
t.message
|
||||
)
|
||||
Crashlytics.logException(t)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
pager.clearOnPageChangeListeners()
|
||||
if (markOnScroll) {
|
||||
pager.clearOnPageChangeListeners()
|
||||
}
|
||||
}
|
||||
|
||||
private inner class ScreenSlidePagerAdapter(fm: FragmentManager) : FragmentStatePagerAdapter(fm) {
|
||||
override fun onSaveInstanceState(oldInstanceState: Bundle?) {
|
||||
super.onSaveInstanceState(oldInstanceState)
|
||||
oldInstanceState!!.clear()
|
||||
}
|
||||
|
||||
private inner class ScreenSlidePagerAdapter(fm: FragmentManager) :
|
||||
FragmentStatePagerAdapter(fm) {
|
||||
override fun getCount(): Int {
|
||||
return allItems.size
|
||||
}
|
||||
@ -121,13 +186,77 @@ class ReaderActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
val inflater = menuInflater
|
||||
inflater.inflate(R.menu.reader_menu, menu)
|
||||
toolbarMenu = menu
|
||||
|
||||
if (!allItems.isEmpty() && allItems[currentItem].starred) {
|
||||
canRemoveFromFavorite()
|
||||
} else {
|
||||
canFavorite()
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
when (item.itemId) {
|
||||
android.R.id.home -> {
|
||||
onBackPressed()
|
||||
return true
|
||||
}
|
||||
R.id.save -> {
|
||||
api.starrItem(allItems[pager.currentItem].id)
|
||||
.enqueue(object : Callback<SuccessResponse> {
|
||||
override fun onResponse(
|
||||
call: Call<SuccessResponse>,
|
||||
response: Response<SuccessResponse>
|
||||
) {
|
||||
allItems[pager.currentItem] = allItems[pager.currentItem].toggleStar()
|
||||
canRemoveFromFavorite()
|
||||
}
|
||||
|
||||
override fun onFailure(
|
||||
call: Call<SuccessResponse>,
|
||||
t: Throwable
|
||||
) {
|
||||
Toast.makeText(
|
||||
baseContext,
|
||||
R.string.cant_mark_favortie,
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
})
|
||||
}
|
||||
R.id.unsave -> {
|
||||
api.unstarrItem(allItems[pager.currentItem].id)
|
||||
.enqueue(object : Callback<SuccessResponse> {
|
||||
override fun onResponse(
|
||||
call: Call<SuccessResponse>,
|
||||
response: Response<SuccessResponse>
|
||||
) {
|
||||
allItems[pager.currentItem] = allItems[pager.currentItem].toggleStar()
|
||||
canFavorite()
|
||||
}
|
||||
|
||||
override fun onFailure(
|
||||
call: Call<SuccessResponse>,
|
||||
t: Throwable
|
||||
) {
|
||||
Toast.makeText(
|
||||
baseContext,
|
||||
R.string.cant_unmark_favortie,
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
return super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
companion object {
|
||||
var allItems: ArrayList<Item> = ArrayList()
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package apps.amine.bou.readerforselfoss
|
||||
|
||||
import android.content.Intent
|
||||
import android.content.res.ColorStateList
|
||||
import android.os.Bundle
|
||||
import android.preference.PreferenceManager
|
||||
import android.support.v7.app.AppCompatActivity
|
||||
@ -9,6 +10,8 @@ import android.widget.Toast
|
||||
import apps.amine.bou.readerforselfoss.adapters.SourcesListAdapter
|
||||
import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi
|
||||
import apps.amine.bou.readerforselfoss.api.selfoss.Sources
|
||||
import apps.amine.bou.readerforselfoss.themes.AppColors
|
||||
import apps.amine.bou.readerforselfoss.themes.Toppings
|
||||
import com.ftinc.scoop.Scoop
|
||||
import kotlinx.android.synthetic.main.activity_sources.*
|
||||
import retrofit2.Call
|
||||
@ -17,14 +20,25 @@ import retrofit2.Response
|
||||
|
||||
class SourcesActivity : AppCompatActivity() {
|
||||
|
||||
private lateinit var appColors: AppColors
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
appColors = AppColors(this@SourcesActivity)
|
||||
|
||||
super.onCreate(savedInstanceState)
|
||||
Scoop.getInstance().apply(this)
|
||||
|
||||
setContentView(R.layout.activity_sources)
|
||||
|
||||
Scoop.getInstance()
|
||||
.bind(this, Toppings.PRIMARY.value, toolbar)
|
||||
.bindStatusBar(this, Toppings.PRIMARY_DARK.value)
|
||||
|
||||
setSupportActionBar(toolbar)
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
supportActionBar?.setDisplayShowHomeEnabled(true)
|
||||
|
||||
fab.rippleColor = appColors.colorAccentDark
|
||||
fab.backgroundTintList = ColorStateList.valueOf(appColors.colorAccent)
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
@ -39,10 +53,10 @@ class SourcesActivity : AppCompatActivity() {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(this)
|
||||
|
||||
val api = SelfossApi(
|
||||
this,
|
||||
this@SourcesActivity,
|
||||
prefs.getBoolean("isSelfSignedCert", false),
|
||||
prefs.getBoolean("should_log_everything", false)
|
||||
this,
|
||||
this@SourcesActivity,
|
||||
prefs.getBoolean("isSelfSignedCert", false),
|
||||
prefs.getBoolean("should_log_everything", false)
|
||||
)
|
||||
var items: ArrayList<Sources> = ArrayList()
|
||||
|
||||
@ -51,8 +65,8 @@ class SourcesActivity : AppCompatActivity() {
|
||||
|
||||
api.sources.enqueue(object : Callback<List<Sources>> {
|
||||
override fun onResponse(
|
||||
call: Call<List<Sources>>,
|
||||
response: Response<List<Sources>>
|
||||
call: Call<List<Sources>>,
|
||||
response: Response<List<Sources>>
|
||||
) {
|
||||
if (response.body() != null && response.body()!!.isNotEmpty()) {
|
||||
items = response.body() as ArrayList<Sources>
|
||||
@ -62,18 +76,18 @@ class SourcesActivity : AppCompatActivity() {
|
||||
mAdapter.notifyDataSetChanged()
|
||||
if (items.isEmpty()) {
|
||||
Toast.makeText(
|
||||
this@SourcesActivity,
|
||||
R.string.nothing_here,
|
||||
Toast.LENGTH_SHORT
|
||||
this@SourcesActivity,
|
||||
R.string.nothing_here,
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<List<Sources>>, t: Throwable) {
|
||||
Toast.makeText(
|
||||
this@SourcesActivity,
|
||||
R.string.cant_get_sources,
|
||||
Toast.LENGTH_SHORT
|
||||
this@SourcesActivity,
|
||||
R.string.cant_get_sources,
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
})
|
||||
|
@ -2,8 +2,6 @@ package apps.amine.bou.readerforselfoss.adapters
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.support.design.widget.Snackbar
|
||||
import android.support.v7.widget.CardView
|
||||
import android.support.v7.widget.RecyclerView
|
||||
import android.text.Html
|
||||
@ -11,7 +9,6 @@ import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView.ScaleType
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import apps.amine.bou.readerforselfoss.R
|
||||
import apps.amine.bou.readerforselfoss.api.selfoss.Item
|
||||
@ -26,12 +23,10 @@ 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 com.like.LikeButton
|
||||
import com.like.OnLikeListener
|
||||
import kotlinx.android.synthetic.main.card_item.view.*
|
||||
@ -40,20 +35,21 @@ import retrofit2.Callback
|
||||
import retrofit2.Response
|
||||
|
||||
class ItemCardAdapter(
|
||||
private val app: Activity,
|
||||
private val items: ArrayList<Item>,
|
||||
private val api: SelfossApi,
|
||||
private val helper: CustomTabActivityHelper,
|
||||
private val internalBrowser: Boolean,
|
||||
private val articleViewer: Boolean,
|
||||
private val fullHeightCards: Boolean,
|
||||
private val appColors: AppColors,
|
||||
val debugReadingItems: Boolean,
|
||||
val userIdentifier: String
|
||||
) : RecyclerView.Adapter<ItemCardAdapter.ViewHolder>() {
|
||||
override val app: Activity,
|
||||
override var items: ArrayList<Item>,
|
||||
override val api: SelfossApi,
|
||||
private val helper: CustomTabActivityHelper,
|
||||
private val internalBrowser: Boolean,
|
||||
private val articleViewer: Boolean,
|
||||
private val fullHeightCards: Boolean,
|
||||
override val appColors: AppColors,
|
||||
override val debugReadingItems: Boolean,
|
||||
override val userIdentifier: String
|
||||
) : ItemsAdapter<ItemCardAdapter.ViewHolder>() {
|
||||
private val c: Context = app.baseContext
|
||||
private val generator: ColorGenerator = ColorGenerator.MATERIAL
|
||||
private val imageMaxHeight: Int = c.resources.getDimension(R.dimen.card_image_max_height).toInt()
|
||||
private val imageMaxHeight: Int =
|
||||
c.resources.getDimension(R.dimen.card_image_max_height).toInt()
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
val v = LayoutInflater.from(c).inflate(R.layout.card_item, parent, false) as CardView
|
||||
@ -67,6 +63,8 @@ class ItemCardAdapter(
|
||||
holder.mView.favButton.isLiked = itm.starred
|
||||
holder.mView.title.text = Html.fromHtml(itm.title)
|
||||
|
||||
holder.mView.title.setLinkTextColor(appColors.colorAccent)
|
||||
|
||||
holder.mView.sourceTitleAndDate.text = itm.sourceAndDateText()
|
||||
|
||||
if (!fullHeightCards) {
|
||||
@ -87,10 +85,10 @@ class ItemCardAdapter(
|
||||
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.mView.sourceImage.setImageDrawable(drawable)
|
||||
} else {
|
||||
c.circularBitmapDrawable(itm.getIcon(c), holder.mView.sourceImage)
|
||||
@ -103,89 +101,9 @@ class ItemCardAdapter(
|
||||
return items.size
|
||||
}
|
||||
|
||||
private fun doUnmark(i: Item, position: Int) {
|
||||
val s = Snackbar
|
||||
.make(
|
||||
app.findViewById(R.id.coordLayout),
|
||||
R.string.marked_as_read,
|
||||
Snackbar.LENGTH_LONG
|
||||
)
|
||||
.setAction(R.string.undo_string) {
|
||||
items.add(position, i)
|
||||
notifyItemInserted(position)
|
||||
|
||||
api.unmarkItem(i.id).enqueue(object : Callback<SuccessResponse> {
|
||||
override fun onResponse(
|
||||
call: Call<SuccessResponse>,
|
||||
response: Response<SuccessResponse>
|
||||
) {
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<SuccessResponse>, t: Throwable) {
|
||||
items.remove(i)
|
||||
notifyItemRemoved(position)
|
||||
doUnmark(i, position)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
val view = s.view
|
||||
val tv: TextView = view.findViewById(android.support.design.R.id.snackbar_text)
|
||||
tv.setTextColor(Color.WHITE)
|
||||
s.show()
|
||||
}
|
||||
|
||||
fun removeItemAtIndex(position: Int) {
|
||||
|
||||
val i = items[position]
|
||||
|
||||
items.remove(i)
|
||||
notifyItemRemoved(position)
|
||||
|
||||
api.markItem(i.id).enqueue(object : Callback<SuccessResponse> {
|
||||
override fun onResponse(
|
||||
call: Call<SuccessResponse>,
|
||||
response: Response<SuccessResponse>
|
||||
) {
|
||||
if (!response.succeeded() && debugReadingItems) {
|
||||
val message =
|
||||
"message: ${response.message()} " +
|
||||
"response isSuccess: ${response.isSuccessful} " +
|
||||
"response code: ${response.code()} " +
|
||||
"response message: ${response.message()} " +
|
||||
"response errorBody: ${response.errorBody()?.string()} " +
|
||||
"body success: ${response.body()?.success} " +
|
||||
"body isSuccess: ${response.body()?.isSuccess}"
|
||||
Crashlytics.setUserIdentifier(userIdentifier)
|
||||
Crashlytics.log(100, "READ_DEBUG_SUCCESS", message)
|
||||
Crashlytics.logException(Exception("Was success, but did it work ?"))
|
||||
|
||||
Toast.makeText(c, message, Toast.LENGTH_LONG).show()
|
||||
}
|
||||
doUnmark(i, position)
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<SuccessResponse>, t: Throwable) {
|
||||
if (debugReadingItems) {
|
||||
Crashlytics.setUserIdentifier(userIdentifier)
|
||||
Crashlytics.log(100, "READ_DEBUG_ERROR", t.message)
|
||||
Crashlytics.logException(t)
|
||||
Toast.makeText(c, t.message, Toast.LENGTH_LONG).show()
|
||||
}
|
||||
Toast.makeText(
|
||||
app,
|
||||
app.getString(R.string.cant_mark_read),
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
items.add(i)
|
||||
notifyItemInserted(position)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
inner class ViewHolder(val mView: CardView) : RecyclerView.ViewHolder(mView) {
|
||||
init {
|
||||
mView.setCardBackgroundColor(appColors.cardBackground)
|
||||
mView.setCardBackgroundColor(appColors.cardBackgroundColor)
|
||||
handleClickListeners()
|
||||
handleCustomTabActions()
|
||||
}
|
||||
@ -197,20 +115,20 @@ class ItemCardAdapter(
|
||||
val (id) = items[adapterPosition]
|
||||
api.starrItem(id).enqueue(object : Callback<SuccessResponse> {
|
||||
override fun onResponse(
|
||||
call: Call<SuccessResponse>,
|
||||
response: Response<SuccessResponse>
|
||||
call: Call<SuccessResponse>,
|
||||
response: Response<SuccessResponse>
|
||||
) {
|
||||
}
|
||||
|
||||
override fun onFailure(
|
||||
call: Call<SuccessResponse>,
|
||||
t: Throwable
|
||||
call: Call<SuccessResponse>,
|
||||
t: Throwable
|
||||
) {
|
||||
mView.favButton.isLiked = false
|
||||
Toast.makeText(
|
||||
c,
|
||||
R.string.cant_mark_favortie,
|
||||
Toast.LENGTH_SHORT
|
||||
c,
|
||||
R.string.cant_mark_favortie,
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
})
|
||||
@ -220,20 +138,20 @@ class ItemCardAdapter(
|
||||
val (id) = items[adapterPosition]
|
||||
api.unstarrItem(id).enqueue(object : Callback<SuccessResponse> {
|
||||
override fun onResponse(
|
||||
call: Call<SuccessResponse>,
|
||||
response: Response<SuccessResponse>
|
||||
call: Call<SuccessResponse>,
|
||||
response: Response<SuccessResponse>
|
||||
) {
|
||||
}
|
||||
|
||||
override fun onFailure(
|
||||
call: Call<SuccessResponse>,
|
||||
t: Throwable
|
||||
call: Call<SuccessResponse>,
|
||||
t: Throwable
|
||||
) {
|
||||
mView.favButton.isLiked = true
|
||||
Toast.makeText(
|
||||
c,
|
||||
R.string.cant_unmark_favortie,
|
||||
Toast.LENGTH_SHORT
|
||||
c,
|
||||
R.string.cant_unmark_favortie,
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
})
|
||||
@ -255,13 +173,13 @@ class ItemCardAdapter(
|
||||
|
||||
mView.setOnClickListener {
|
||||
c.openItemUrl(
|
||||
items,
|
||||
adapterPosition,
|
||||
items[adapterPosition].getLinkDecoded(),
|
||||
customTabsIntent,
|
||||
internalBrowser,
|
||||
articleViewer,
|
||||
app
|
||||
items,
|
||||
adapterPosition,
|
||||
items[adapterPosition].getLinkDecoded(),
|
||||
customTabsIntent,
|
||||
internalBrowser,
|
||||
articleViewer,
|
||||
app
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -2,21 +2,19 @@ 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.RecyclerView
|
||||
import android.text.Html
|
||||
import android.util.TypedValue
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
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.themes.AppColors
|
||||
import apps.amine.bou.readerforselfoss.utils.buildCustomTabsIntent
|
||||
import apps.amine.bou.readerforselfoss.utils.customtabs.CustomTabActivityHelper
|
||||
import apps.amine.bou.readerforselfoss.utils.glide.bitmapCenterCrop
|
||||
@ -25,10 +23,9 @@ 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.crashlytics.android.Crashlytics
|
||||
import com.like.LikeButton
|
||||
import com.like.OnLikeListener
|
||||
import kotlinx.android.synthetic.main.list_item.view.*
|
||||
@ -39,25 +36,26 @@ import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
class ItemListAdapter(
|
||||
private val app: Activity,
|
||||
private val items: ArrayList<Item>,
|
||||
private val api: SelfossApi,
|
||||
private val helper: CustomTabActivityHelper,
|
||||
private val clickBehavior: Boolean,
|
||||
private val internalBrowser: Boolean,
|
||||
private val articleViewer: Boolean,
|
||||
val debugReadingItems: Boolean,
|
||||
val userIdentifier: String
|
||||
) : RecyclerView.Adapter<ItemListAdapter.ViewHolder>() {
|
||||
override val app: Activity,
|
||||
override var items: ArrayList<Item>,
|
||||
override val api: SelfossApi,
|
||||
private val helper: CustomTabActivityHelper,
|
||||
private val clickBehavior: Boolean,
|
||||
private val internalBrowser: Boolean,
|
||||
private val articleViewer: Boolean,
|
||||
override val debugReadingItems: Boolean,
|
||||
override val userIdentifier: String,
|
||||
override val appColors: AppColors
|
||||
) : ItemsAdapter<ItemListAdapter.ViewHolder>() {
|
||||
private val generator: ColorGenerator = ColorGenerator.MATERIAL
|
||||
private val c: Context = app.baseContext
|
||||
private val bars: ArrayList<Boolean> = ArrayList(Collections.nCopies(items.size + 1, false))
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
val v = LayoutInflater.from(c).inflate(
|
||||
R.layout.list_item,
|
||||
parent,
|
||||
false
|
||||
R.layout.list_item,
|
||||
parent,
|
||||
false
|
||||
) as ConstraintLayout
|
||||
return ViewHolder(v)
|
||||
}
|
||||
@ -66,21 +64,22 @@ class ItemListAdapter(
|
||||
val itm = items[position]
|
||||
|
||||
|
||||
holder.mView.favButton.isLiked = itm.starred
|
||||
holder.mView.title.text = Html.fromHtml(itm.title)
|
||||
|
||||
holder.mView.title.setLinkTextColor(appColors.colorAccent)
|
||||
|
||||
holder.mView.sourceTitleAndDate.text = itm.sourceAndDateText()
|
||||
|
||||
if (itm.getThumbnail(c).isEmpty()) {
|
||||
val sizeInInt = 46
|
||||
val sizeInDp = TypedValue.applyDimension(
|
||||
TypedValue.COMPLEX_UNIT_DIP, sizeInInt.toFloat(), c.resources
|
||||
TypedValue.COMPLEX_UNIT_DIP, sizeInInt.toFloat(), c.resources
|
||||
.displayMetrics
|
||||
).toInt()
|
||||
|
||||
val marginInInt = 16
|
||||
val marginInDp = TypedValue.applyDimension(
|
||||
TypedValue.COMPLEX_UNIT_DIP, marginInInt.toFloat(), c.resources
|
||||
TypedValue.COMPLEX_UNIT_DIP, marginInInt.toFloat(), c.resources
|
||||
.displayMetrics
|
||||
).toInt()
|
||||
|
||||
@ -92,14 +91,13 @@ class ItemListAdapter(
|
||||
|
||||
if (itm.getIcon(c).isEmpty()) {
|
||||
val color = generator.getColor(itm.sourcetitle)
|
||||
val textDrawable = StringBuilder()
|
||||
for (s in itm.sourcetitle.split(" ".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()) {
|
||||
textDrawable.append(s[0])
|
||||
}
|
||||
|
||||
val builder = TextDrawable.builder().round()
|
||||
val drawable =
|
||||
TextDrawable
|
||||
.builder()
|
||||
.round()
|
||||
.build(itm.sourcetitle.toTextDrawableString(), color)
|
||||
|
||||
val drawable = builder.build(textDrawable.toString(), color)
|
||||
holder.mView.itemImage.setImageDrawable(drawable)
|
||||
} else {
|
||||
c.circularBitmapDrawable(itm.getIcon(c), holder.mView.itemImage)
|
||||
@ -108,9 +106,14 @@ class ItemListAdapter(
|
||||
c.bitmapCenterCrop(itm.getThumbnail(c), holder.mView.itemImage)
|
||||
}
|
||||
|
||||
if (bars[position]) {
|
||||
holder.mView.actionBar.visibility = View.VISIBLE
|
||||
} else {
|
||||
// TODO: maybe handle this differently. It crashes when changing tab
|
||||
try {
|
||||
if (bars[position]) {
|
||||
holder.mView.actionBar.visibility = View.VISIBLE
|
||||
} else {
|
||||
holder.mView.actionBar.visibility = View.GONE
|
||||
}
|
||||
} catch (e: IndexOutOfBoundsException) {
|
||||
holder.mView.actionBar.visibility = View.GONE
|
||||
}
|
||||
|
||||
@ -119,85 +122,6 @@ class ItemListAdapter(
|
||||
|
||||
override fun getItemCount(): Int = items.size
|
||||
|
||||
private fun doUnmark(i: Item, position: Int) {
|
||||
val s = Snackbar
|
||||
.make(
|
||||
app.findViewById(R.id.coordLayout),
|
||||
R.string.marked_as_read,
|
||||
Snackbar.LENGTH_LONG
|
||||
)
|
||||
.setAction(R.string.undo_string) {
|
||||
items.add(position, i)
|
||||
notifyItemInserted(position)
|
||||
|
||||
api.unmarkItem(i.id).enqueue(object : Callback<SuccessResponse> {
|
||||
override fun onResponse(
|
||||
call: Call<SuccessResponse>,
|
||||
response: Response<SuccessResponse>
|
||||
) {
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<SuccessResponse>, t: Throwable) {
|
||||
items.remove(i)
|
||||
notifyItemRemoved(position)
|
||||
doUnmark(i, position)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
val view = s.view
|
||||
val tv: TextView = view.findViewById(android.support.design.R.id.snackbar_text)
|
||||
tv.setTextColor(Color.WHITE)
|
||||
s.show()
|
||||
}
|
||||
|
||||
fun removeItemAtIndex(position: Int) {
|
||||
|
||||
val i = items[position]
|
||||
|
||||
items.remove(i)
|
||||
notifyItemRemoved(position)
|
||||
|
||||
api.markItem(i.id).enqueue(object : Callback<SuccessResponse> {
|
||||
override fun onResponse(
|
||||
call: Call<SuccessResponse>,
|
||||
response: Response<SuccessResponse>
|
||||
) {
|
||||
if (!response.succeeded() && debugReadingItems) {
|
||||
val message =
|
||||
"message: ${response.message()} " +
|
||||
"response isSuccess: ${response.isSuccessful} " +
|
||||
"response code: ${response.code()} " +
|
||||
"response message: ${response.message()} " +
|
||||
"response errorBody: ${response.errorBody()?.string()} " +
|
||||
"body success: ${response.body()?.success} " +
|
||||
"body isSuccess: ${response.body()?.isSuccess}"
|
||||
Crashlytics.setUserIdentifier(userIdentifier)
|
||||
Crashlytics.log(100, "READ_DEBUG_SUCCESS", message)
|
||||
Crashlytics.logException(Exception("Was success, but did it work ?"))
|
||||
Toast.makeText(c, message, Toast.LENGTH_LONG).show()
|
||||
}
|
||||
doUnmark(i, position)
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<SuccessResponse>, t: Throwable) {
|
||||
if (debugReadingItems) {
|
||||
Crashlytics.setUserIdentifier(userIdentifier)
|
||||
Crashlytics.log(100, "READ_DEBUG_ERROR", t.message)
|
||||
Crashlytics.logException(t)
|
||||
Toast.makeText(c, t.message, Toast.LENGTH_LONG).show()
|
||||
}
|
||||
Toast.makeText(
|
||||
app,
|
||||
app.getString(R.string.cant_mark_read),
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
items.add(i)
|
||||
notifyItemInserted(position)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
inner class ViewHolder(val mView: ConstraintLayout) : RecyclerView.ViewHolder(mView) {
|
||||
|
||||
init {
|
||||
@ -212,20 +136,20 @@ class ItemListAdapter(
|
||||
val (id) = items[adapterPosition]
|
||||
api.starrItem(id).enqueue(object : Callback<SuccessResponse> {
|
||||
override fun onResponse(
|
||||
call: Call<SuccessResponse>,
|
||||
response: Response<SuccessResponse>
|
||||
call: Call<SuccessResponse>,
|
||||
response: Response<SuccessResponse>
|
||||
) {
|
||||
}
|
||||
|
||||
override fun onFailure(
|
||||
call: Call<SuccessResponse>,
|
||||
t: Throwable
|
||||
call: Call<SuccessResponse>,
|
||||
t: Throwable
|
||||
) {
|
||||
mView.favButton.isLiked = false
|
||||
Toast.makeText(
|
||||
c,
|
||||
R.string.cant_mark_favortie,
|
||||
Toast.LENGTH_SHORT
|
||||
c,
|
||||
R.string.cant_mark_favortie,
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
})
|
||||
@ -235,20 +159,20 @@ class ItemListAdapter(
|
||||
val (id) = items[adapterPosition]
|
||||
api.unstarrItem(id).enqueue(object : Callback<SuccessResponse> {
|
||||
override fun onResponse(
|
||||
call: Call<SuccessResponse>,
|
||||
response: Response<SuccessResponse>
|
||||
call: Call<SuccessResponse>,
|
||||
response: Response<SuccessResponse>
|
||||
) {
|
||||
}
|
||||
|
||||
override fun onFailure(
|
||||
call: Call<SuccessResponse>,
|
||||
t: Throwable
|
||||
call: Call<SuccessResponse>,
|
||||
t: Throwable
|
||||
) {
|
||||
mView.favButton.isLiked = true
|
||||
Toast.makeText(
|
||||
c,
|
||||
R.string.cant_unmark_favortie,
|
||||
Toast.LENGTH_SHORT
|
||||
c,
|
||||
R.string.cant_unmark_favortie,
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
})
|
||||
@ -273,13 +197,13 @@ class ItemListAdapter(
|
||||
if (!clickBehavior) {
|
||||
mView.setOnClickListener {
|
||||
c.openItemUrl(
|
||||
items,
|
||||
adapterPosition,
|
||||
items[adapterPosition].getLinkDecoded(),
|
||||
customTabsIntent,
|
||||
internalBrowser,
|
||||
articleViewer,
|
||||
app
|
||||
items,
|
||||
adapterPosition,
|
||||
items[adapterPosition].getLinkDecoded(),
|
||||
customTabsIntent,
|
||||
internalBrowser,
|
||||
articleViewer,
|
||||
app
|
||||
)
|
||||
}
|
||||
mView.setOnLongClickListener {
|
||||
@ -290,13 +214,13 @@ class ItemListAdapter(
|
||||
mView.setOnClickListener { actionBarShowHide() }
|
||||
mView.setOnLongClickListener {
|
||||
c.openItemUrl(
|
||||
items,
|
||||
adapterPosition,
|
||||
items[adapterPosition].getLinkDecoded(),
|
||||
customTabsIntent,
|
||||
internalBrowser,
|
||||
articleViewer,
|
||||
app
|
||||
items,
|
||||
adapterPosition,
|
||||
items[adapterPosition].getLinkDecoded(),
|
||||
customTabsIntent,
|
||||
internalBrowser,
|
||||
articleViewer,
|
||||
app
|
||||
)
|
||||
true
|
||||
}
|
||||
|
@ -0,0 +1,123 @@
|
||||
package apps.amine.bou.readerforselfoss.adapters
|
||||
|
||||
import android.app.Activity
|
||||
import android.graphics.Color
|
||||
import android.support.design.widget.Snackbar
|
||||
import android.support.v7.widget.RecyclerView
|
||||
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.themes.AppColors
|
||||
import apps.amine.bou.readerforselfoss.utils.succeeded
|
||||
import com.crashlytics.android.Crashlytics
|
||||
import retrofit2.Call
|
||||
import retrofit2.Callback
|
||||
import retrofit2.Response
|
||||
|
||||
abstract class ItemsAdapter<VH : RecyclerView.ViewHolder?> : RecyclerView.Adapter<VH>() {
|
||||
abstract var items: ArrayList<Item>
|
||||
abstract val api: SelfossApi
|
||||
abstract val debugReadingItems: Boolean
|
||||
abstract val userIdentifier: String
|
||||
abstract val app: Activity
|
||||
abstract val appColors: AppColors
|
||||
|
||||
fun updateAllItems(newItems: ArrayList<Item>) {
|
||||
items = newItems
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
private fun doUnmark(i: Item, position: Int) {
|
||||
val s = Snackbar
|
||||
.make(
|
||||
app.findViewById(R.id.coordLayout),
|
||||
R.string.marked_as_read,
|
||||
Snackbar.LENGTH_LONG
|
||||
)
|
||||
.setAction(R.string.undo_string) {
|
||||
items.add(position, i)
|
||||
notifyItemInserted(position)
|
||||
|
||||
api.unmarkItem(i.id).enqueue(object : Callback<SuccessResponse> {
|
||||
override fun onResponse(
|
||||
call: Call<SuccessResponse>,
|
||||
response: Response<SuccessResponse>
|
||||
) {
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<SuccessResponse>, t: Throwable) {
|
||||
items.remove(i)
|
||||
notifyItemRemoved(position)
|
||||
doUnmark(i, position)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
val view = s.view
|
||||
val tv: TextView = view.findViewById(android.support.design.R.id.snackbar_text)
|
||||
tv.setTextColor(Color.WHITE)
|
||||
s.show()
|
||||
}
|
||||
|
||||
fun removeItemAtIndex(position: Int) {
|
||||
|
||||
val i = items[position]
|
||||
|
||||
items.remove(i)
|
||||
notifyItemRemoved(position)
|
||||
|
||||
api.markItem(i.id).enqueue(object : Callback<SuccessResponse> {
|
||||
override fun onResponse(
|
||||
call: Call<SuccessResponse>,
|
||||
response: Response<SuccessResponse>
|
||||
) {
|
||||
if (!response.succeeded() && debugReadingItems) {
|
||||
val message =
|
||||
"message: ${response.message()} " +
|
||||
"response isSuccess: ${response.isSuccessful} " +
|
||||
"response code: ${response.code()} " +
|
||||
"response message: ${response.message()} " +
|
||||
"response errorBody: ${response.errorBody()?.string()} " +
|
||||
"body success: ${response.body()?.success} " +
|
||||
"body isSuccess: ${response.body()?.isSuccess}"
|
||||
Crashlytics.setUserIdentifier(userIdentifier)
|
||||
Crashlytics.log(100, "READ_DEBUG_SUCCESS", message)
|
||||
Crashlytics.logException(Exception("Was success, but did it work ?"))
|
||||
|
||||
Toast.makeText(app.baseContext, message, Toast.LENGTH_LONG).show()
|
||||
}
|
||||
doUnmark(i, position)
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<SuccessResponse>, t: Throwable) {
|
||||
if (debugReadingItems) {
|
||||
Crashlytics.setUserIdentifier(userIdentifier)
|
||||
Crashlytics.log(100, "READ_DEBUG_ERROR", t.message)
|
||||
Crashlytics.logException(t)
|
||||
Toast.makeText(app.baseContext, t.message, Toast.LENGTH_LONG).show()
|
||||
}
|
||||
Toast.makeText(
|
||||
app,
|
||||
app.getString(R.string.cant_mark_read),
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
items.add(i)
|
||||
notifyItemInserted(position)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun addItemAtIndex(item: Item, position: Int) {
|
||||
items.add(position, item)
|
||||
notifyItemInserted(position)
|
||||
}
|
||||
|
||||
fun addItemsAtEnd(newItems: List<Item>) {
|
||||
val oldSize = items.size
|
||||
items.addAll(newItems)
|
||||
notifyItemRangeInserted(oldSize, newItems.size)
|
||||
}
|
||||
}
|
@ -22,18 +22,18 @@ import retrofit2.Callback
|
||||
import retrofit2.Response
|
||||
|
||||
class SourcesListAdapter(
|
||||
private val app: Activity,
|
||||
private val items: ArrayList<Sources>,
|
||||
private val api: SelfossApi
|
||||
private val app: Activity,
|
||||
private val items: ArrayList<Sources>,
|
||||
private val api: SelfossApi
|
||||
) : RecyclerView.Adapter<SourcesListAdapter.ViewHolder>() {
|
||||
private val c: Context = app.baseContext
|
||||
private val generator: ColorGenerator = ColorGenerator.MATERIAL
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
val v = LayoutInflater.from(c).inflate(
|
||||
R.layout.source_list_item,
|
||||
parent,
|
||||
false
|
||||
R.layout.source_list_item,
|
||||
parent,
|
||||
false
|
||||
) as ConstraintLayout
|
||||
return ViewHolder(v)
|
||||
}
|
||||
@ -45,10 +45,10 @@ class SourcesListAdapter(
|
||||
val color = generator.getColor(itm.title)
|
||||
|
||||
val drawable =
|
||||
TextDrawable
|
||||
.builder()
|
||||
.round()
|
||||
.build(itm.title.toTextDrawableString(), color)
|
||||
TextDrawable
|
||||
.builder()
|
||||
.round()
|
||||
.build(itm.title.toTextDrawableString(), color)
|
||||
holder.mView.itemImage.setImageDrawable(drawable)
|
||||
} else {
|
||||
c.circularBitmapDrawable(itm.getIcon(c), holder.mView.itemImage)
|
||||
@ -73,8 +73,8 @@ class SourcesListAdapter(
|
||||
val (id) = items[adapterPosition]
|
||||
api.deleteSource(id).enqueue(object : Callback<SuccessResponse> {
|
||||
override fun onResponse(
|
||||
call: Call<SuccessResponse>,
|
||||
response: Response<SuccessResponse>
|
||||
call: Call<SuccessResponse>,
|
||||
response: Response<SuccessResponse>
|
||||
) {
|
||||
if (response.body() != null && response.body()!!.isSuccess) {
|
||||
items.removeAt(adapterPosition)
|
||||
@ -82,18 +82,18 @@ class SourcesListAdapter(
|
||||
notifyItemRangeChanged(adapterPosition, itemCount)
|
||||
} else {
|
||||
Toast.makeText(
|
||||
app,
|
||||
R.string.can_delete_source,
|
||||
Toast.LENGTH_SHORT
|
||||
app,
|
||||
R.string.can_delete_source,
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<SuccessResponse>, t: Throwable) {
|
||||
Toast.makeText(
|
||||
app,
|
||||
R.string.can_delete_source,
|
||||
Toast.LENGTH_SHORT
|
||||
app,
|
||||
R.string.can_delete_source,
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
})
|
||||
|
@ -21,15 +21,15 @@ class MercuryApi(private val key: String, shouldLog: Boolean) {
|
||||
val client = OkHttpClient.Builder().addInterceptor(interceptor).build()
|
||||
|
||||
val gson = GsonBuilder()
|
||||
.setLenient()
|
||||
.create()
|
||||
.setLenient()
|
||||
.create()
|
||||
val retrofit =
|
||||
Retrofit
|
||||
.Builder()
|
||||
.baseUrl("https://mercury.postlight.com")
|
||||
.client(client)
|
||||
.addConverterFactory(GsonConverterFactory.create(gson))
|
||||
.build()
|
||||
Retrofit
|
||||
.Builder()
|
||||
.baseUrl("https://mercury.postlight.com")
|
||||
.client(client)
|
||||
.addConverterFactory(GsonConverterFactory.create(gson))
|
||||
.build()
|
||||
service = retrofit.create(MercuryService::class.java)
|
||||
}
|
||||
|
||||
|
@ -5,39 +5,40 @@ import android.os.Parcelable
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
class ParsedContent(
|
||||
@SerializedName("title") val title: String,
|
||||
@SerializedName("content") val content: String,
|
||||
@SerializedName("date_published") val date_published: String,
|
||||
@SerializedName("lead_image_url") val lead_image_url: String,
|
||||
@SerializedName("dek") val dek: String,
|
||||
@SerializedName("url") val url: String,
|
||||
@SerializedName("domain") val domain: String,
|
||||
@SerializedName("excerpt") val excerpt: String,
|
||||
@SerializedName("total_pages") val total_pages: Int,
|
||||
@SerializedName("rendered_pages") val rendered_pages: Int,
|
||||
@SerializedName("next_page_url") val next_page_url: String
|
||||
@SerializedName("title") val title: String,
|
||||
@SerializedName("content") val content: String?,
|
||||
@SerializedName("date_published") val date_published: String,
|
||||
@SerializedName("lead_image_url") val lead_image_url: String?,
|
||||
@SerializedName("dek") val dek: String,
|
||||
@SerializedName("url") val url: String,
|
||||
@SerializedName("domain") val domain: String,
|
||||
@SerializedName("excerpt") val excerpt: String,
|
||||
@SerializedName("total_pages") val total_pages: Int,
|
||||
@SerializedName("rendered_pages") val rendered_pages: Int,
|
||||
@SerializedName("next_page_url") val next_page_url: String
|
||||
) : Parcelable {
|
||||
|
||||
companion object {
|
||||
@JvmField
|
||||
val CREATOR: Parcelable.Creator<ParsedContent> = object : Parcelable.Creator<ParsedContent> {
|
||||
override fun createFromParcel(source: Parcel): ParsedContent = ParsedContent(source)
|
||||
override fun newArray(size: Int): Array<ParsedContent?> = arrayOfNulls(size)
|
||||
}
|
||||
val CREATOR: Parcelable.Creator<ParsedContent> =
|
||||
object : Parcelable.Creator<ParsedContent> {
|
||||
override fun createFromParcel(source: Parcel): ParsedContent = ParsedContent(source)
|
||||
override fun newArray(size: Int): Array<ParsedContent?> = arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
|
||||
constructor(source: Parcel) : this(
|
||||
title = source.readString(),
|
||||
content = source.readString(),
|
||||
date_published = source.readString(),
|
||||
lead_image_url = source.readString(),
|
||||
dek = source.readString(),
|
||||
url = source.readString(),
|
||||
domain = source.readString(),
|
||||
excerpt = source.readString(),
|
||||
total_pages = source.readInt(),
|
||||
rendered_pages = source.readInt(),
|
||||
next_page_url = source.readString()
|
||||
title = source.readString(),
|
||||
content = source.readString(),
|
||||
date_published = source.readString(),
|
||||
lead_image_url = source.readString(),
|
||||
dek = source.readString(),
|
||||
url = source.readString(),
|
||||
domain = source.readString(),
|
||||
excerpt = source.readString(),
|
||||
total_pages = source.readInt(),
|
||||
rendered_pages = source.readInt(),
|
||||
next_page_url = source.readString()
|
||||
)
|
||||
|
||||
override fun describeContents() = 0
|
||||
|
@ -10,13 +10,13 @@ internal class BooleanTypeAdapter : JsonDeserializer<Boolean> {
|
||||
|
||||
@Throws(JsonParseException::class)
|
||||
override fun deserialize(
|
||||
json: JsonElement,
|
||||
typeOfT: Type,
|
||||
context: JsonDeserializationContext
|
||||
json: JsonElement,
|
||||
typeOfT: Type,
|
||||
context: JsonDeserializationContext
|
||||
): Boolean? =
|
||||
try {
|
||||
json.asInt == 1
|
||||
} catch (e: Exception) {
|
||||
json.asBoolean
|
||||
}
|
||||
try {
|
||||
json.asInt == 1
|
||||
} catch (e: Exception) {
|
||||
json.asBoolean
|
||||
}
|
||||
}
|
||||
|
@ -20,10 +20,10 @@ import retrofit2.converter.gson.GsonConverterFactory
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
class SelfossApi(
|
||||
c: Context,
|
||||
callingActivity: Activity,
|
||||
isWithSelfSignedCert: Boolean,
|
||||
shouldLog: Boolean
|
||||
c: Context,
|
||||
callingActivity: Activity,
|
||||
isWithSelfSignedCert: Boolean,
|
||||
shouldLog: Boolean
|
||||
) {
|
||||
|
||||
private lateinit var service: SelfossService
|
||||
@ -32,25 +32,25 @@ class SelfossApi(
|
||||
private val password: String
|
||||
|
||||
fun OkHttpClient.Builder.maybeWithSelfSigned(isWithSelfSignedCert: Boolean): OkHttpClient.Builder =
|
||||
if (isWithSelfSignedCert) {
|
||||
getUnsafeHttpClient()
|
||||
} else {
|
||||
this
|
||||
}
|
||||
if (isWithSelfSignedCert) {
|
||||
getUnsafeHttpClient()
|
||||
} else {
|
||||
this
|
||||
}
|
||||
|
||||
fun Credentials.createAuthenticator(): DispatchingAuthenticator =
|
||||
DispatchingAuthenticator.Builder()
|
||||
.with("digest", DigestAuthenticator(this))
|
||||
.with("basic", BasicAuthenticator(this))
|
||||
.build()
|
||||
DispatchingAuthenticator.Builder()
|
||||
.with("digest", DigestAuthenticator(this))
|
||||
.with("basic", BasicAuthenticator(this))
|
||||
.build()
|
||||
|
||||
fun DispatchingAuthenticator.getHttpClien(isWithSelfSignedCert: Boolean): OkHttpClient.Builder {
|
||||
val authCache = ConcurrentHashMap<String, CachingAuthenticator>()
|
||||
return OkHttpClient
|
||||
.Builder()
|
||||
.maybeWithSelfSigned(isWithSelfSignedCert)
|
||||
.authenticator(CachingAuthenticatorDecorator(this, authCache))
|
||||
.addInterceptor(AuthenticationCacheInterceptor(authCache))
|
||||
.Builder()
|
||||
.maybeWithSelfSigned(isWithSelfSignedCert)
|
||||
.authenticator(CachingAuthenticatorDecorator(this, authCache))
|
||||
.addInterceptor(AuthenticationCacheInterceptor(authCache))
|
||||
}
|
||||
|
||||
init {
|
||||
@ -58,16 +58,16 @@ class SelfossApi(
|
||||
password = config.userPassword
|
||||
|
||||
val authenticator =
|
||||
Credentials(
|
||||
config.httpUserLogin,
|
||||
config.httpUserPassword
|
||||
).createAuthenticator()
|
||||
Credentials(
|
||||
config.httpUserLogin,
|
||||
config.httpUserPassword
|
||||
).createAuthenticator()
|
||||
|
||||
val gson =
|
||||
GsonBuilder()
|
||||
.registerTypeAdapter(Boolean::class.javaPrimitiveType, BooleanTypeAdapter())
|
||||
.setLenient()
|
||||
.create()
|
||||
GsonBuilder()
|
||||
.registerTypeAdapter(Boolean::class.javaPrimitiveType, BooleanTypeAdapter())
|
||||
.setLenient()
|
||||
.create()
|
||||
|
||||
val logging = HttpLoggingInterceptor()
|
||||
|
||||
@ -83,12 +83,12 @@ class SelfossApi(
|
||||
|
||||
try {
|
||||
val retrofit =
|
||||
Retrofit
|
||||
.Builder()
|
||||
.baseUrl(config.baseUrl)
|
||||
.client(httpClient.build())
|
||||
.addConverterFactory(GsonConverterFactory.create(gson))
|
||||
.build()
|
||||
Retrofit
|
||||
.Builder()
|
||||
.baseUrl(config.baseUrl)
|
||||
.client(httpClient.build())
|
||||
.addConverterFactory(GsonConverterFactory.create(gson))
|
||||
.build()
|
||||
service = retrofit.create(SelfossService::class.java)
|
||||
} catch (e: IllegalArgumentException) {
|
||||
Config.logoutAndRedirect(c, callingActivity, config.settings.edit(), baseUrlFail = true)
|
||||
@ -96,59 +96,59 @@ class SelfossApi(
|
||||
}
|
||||
|
||||
fun login(): Call<SuccessResponse> =
|
||||
service.loginToSelfoss(config.userLogin, config.userPassword)
|
||||
service.loginToSelfoss(config.userLogin, config.userPassword)
|
||||
|
||||
fun readItems(
|
||||
tag: String?,
|
||||
sourceId: Long?,
|
||||
search: String?,
|
||||
itemsNumber: Int,
|
||||
offset: Int
|
||||
tag: String?,
|
||||
sourceId: Long?,
|
||||
search: String?,
|
||||
itemsNumber: Int,
|
||||
offset: Int
|
||||
): Call<List<Item>> =
|
||||
getItems("read", tag, sourceId, search, itemsNumber, offset)
|
||||
getItems("read", tag, sourceId, search, itemsNumber, offset)
|
||||
|
||||
fun newItems(
|
||||
tag: String?,
|
||||
sourceId: Long?,
|
||||
search: String?,
|
||||
itemsNumber: Int,
|
||||
offset: Int
|
||||
tag: String?,
|
||||
sourceId: Long?,
|
||||
search: String?,
|
||||
itemsNumber: Int,
|
||||
offset: Int
|
||||
): Call<List<Item>> =
|
||||
getItems("unread", tag, sourceId, search, itemsNumber, offset)
|
||||
getItems("unread", tag, sourceId, search, itemsNumber, offset)
|
||||
|
||||
fun starredItems(
|
||||
tag: String?,
|
||||
sourceId: Long?,
|
||||
search: String?,
|
||||
itemsNumber: Int,
|
||||
offset: Int
|
||||
tag: String?,
|
||||
sourceId: Long?,
|
||||
search: String?,
|
||||
itemsNumber: Int,
|
||||
offset: Int
|
||||
): Call<List<Item>> =
|
||||
getItems("starred", tag, sourceId, search, itemsNumber, offset)
|
||||
getItems("starred", tag, sourceId, search, itemsNumber, offset)
|
||||
|
||||
private fun getItems(
|
||||
type: String,
|
||||
tag: String?,
|
||||
sourceId: Long?,
|
||||
search: String?,
|
||||
items: Int,
|
||||
offset: Int
|
||||
type: String,
|
||||
tag: String?,
|
||||
sourceId: Long?,
|
||||
search: String?,
|
||||
items: Int,
|
||||
offset: Int
|
||||
): Call<List<Item>> =
|
||||
service.getItems(type, tag, sourceId, search, userName, password, items, offset)
|
||||
service.getItems(type, tag, sourceId, search, userName, password, items, offset)
|
||||
|
||||
fun markItem(itemId: String): Call<SuccessResponse> =
|
||||
service.markAsRead(itemId, userName, password)
|
||||
service.markAsRead(itemId, userName, password)
|
||||
|
||||
fun unmarkItem(itemId: String): Call<SuccessResponse> =
|
||||
service.unmarkAsRead(itemId, userName, password)
|
||||
service.unmarkAsRead(itemId, userName, password)
|
||||
|
||||
fun readAll(ids: List<String>): Call<SuccessResponse> =
|
||||
service.markAllAsRead(ids, userName, password)
|
||||
service.markAllAsRead(ids, userName, password)
|
||||
|
||||
fun starrItem(itemId: String): Call<SuccessResponse> =
|
||||
service.starr(itemId, userName, password)
|
||||
service.starr(itemId, userName, password)
|
||||
|
||||
fun unstarrItem(itemId: String): Call<SuccessResponse> =
|
||||
service.unstarr(itemId, userName, password)
|
||||
service.unstarr(itemId, userName, password)
|
||||
|
||||
val stats: Call<Stats>
|
||||
get() = service.stats(userName, password)
|
||||
@ -157,23 +157,23 @@ class SelfossApi(
|
||||
get() = service.tags(userName, password)
|
||||
|
||||
fun update(): Call<String> =
|
||||
service.update(userName, password)
|
||||
service.update(userName, password)
|
||||
|
||||
val sources: Call<List<Sources>>
|
||||
get() = service.sources(userName, password)
|
||||
|
||||
fun deleteSource(id: String): Call<SuccessResponse> =
|
||||
service.deleteSource(id, userName, password)
|
||||
service.deleteSource(id, userName, password)
|
||||
|
||||
fun spouts(): Call<Map<String, Spout>> =
|
||||
service.spouts(userName, password)
|
||||
service.spouts(userName, password)
|
||||
|
||||
fun createSource(
|
||||
title: String,
|
||||
url: String,
|
||||
spout: String,
|
||||
tags: String,
|
||||
filter: String
|
||||
title: String,
|
||||
url: String,
|
||||
spout: String,
|
||||
tags: String,
|
||||
filter: String
|
||||
): Call<SuccessResponse> =
|
||||
service.createSource(title, url, spout, tags, filter, userName, password)
|
||||
service.createSource(title, url, spout, tags, filter, userName, password)
|
||||
}
|
||||
|
@ -21,9 +21,9 @@ private fun constructUrl(config: Config?, path: String, file: String): String {
|
||||
}
|
||||
|
||||
data class Tag(
|
||||
@SerializedName("tag") val tag: String,
|
||||
@SerializedName("color") val color: String,
|
||||
@SerializedName("unread") val unread: Int
|
||||
@SerializedName("tag") val tag: String,
|
||||
@SerializedName("color") val color: String,
|
||||
@SerializedName("unread") val unread: Int
|
||||
)
|
||||
|
||||
class SuccessResponse(@SerializedName("success") val success: Boolean) {
|
||||
@ -32,23 +32,23 @@ class SuccessResponse(@SerializedName("success") val success: Boolean) {
|
||||
}
|
||||
|
||||
class Stats(
|
||||
@SerializedName("total") val total: Int,
|
||||
@SerializedName("unread") val unread: Int,
|
||||
@SerializedName("starred") val starred: Int
|
||||
@SerializedName("total") val total: Int,
|
||||
@SerializedName("unread") val unread: Int,
|
||||
@SerializedName("starred") val starred: Int
|
||||
)
|
||||
|
||||
data class Spout(
|
||||
@SerializedName("name") val name: String,
|
||||
@SerializedName("description") val description: String
|
||||
@SerializedName("name") val name: String,
|
||||
@SerializedName("description") val description: String
|
||||
)
|
||||
|
||||
data class Sources(
|
||||
@SerializedName("id") val id: String,
|
||||
@SerializedName("title") val title: String,
|
||||
@SerializedName("tags") val tags: String,
|
||||
@SerializedName("spout") val spout: String,
|
||||
@SerializedName("error") val error: String,
|
||||
@SerializedName("icon") val icon: String
|
||||
@SerializedName("id") val id: String,
|
||||
@SerializedName("title") val title: String,
|
||||
@SerializedName("tags") val tags: String,
|
||||
@SerializedName("spout") val spout: String,
|
||||
@SerializedName("error") val error: String,
|
||||
@SerializedName("icon") val icon: String
|
||||
) {
|
||||
var config: Config? = null
|
||||
|
||||
@ -61,16 +61,17 @@ data class Sources(
|
||||
}
|
||||
|
||||
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,
|
||||
@SerializedName("icon") val icon: String,
|
||||
@SerializedName("link") val link: String,
|
||||
@SerializedName("sourcetitle") val sourcetitle: String
|
||||
@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") var starred: Boolean,
|
||||
@SerializedName("thumbnail") val thumbnail: String,
|
||||
@SerializedName("icon") val icon: String,
|
||||
@SerializedName("link") val link: String,
|
||||
@SerializedName("sourcetitle") val sourcetitle: String,
|
||||
@SerializedName("tags") val tags: String
|
||||
) : Parcelable {
|
||||
|
||||
var config: Config? = null
|
||||
@ -83,16 +84,17 @@ data class Item(
|
||||
}
|
||||
|
||||
constructor(source: Parcel) : this(
|
||||
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()
|
||||
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(),
|
||||
tags = source.readString()
|
||||
)
|
||||
|
||||
override fun describeContents() = 0
|
||||
@ -108,6 +110,7 @@ data class Item(
|
||||
dest.writeString(icon)
|
||||
dest.writeString(link)
|
||||
dest.writeString(sourcetitle)
|
||||
dest.writeString(tags)
|
||||
}
|
||||
|
||||
fun getIcon(app: Context): String {
|
||||
@ -127,15 +130,16 @@ data class Item(
|
||||
// TODO: maybe find a better way to handle these kind of urls
|
||||
fun getLinkDecoded(): String {
|
||||
var stringUrl: String
|
||||
stringUrl = if (link.startsWith("http://news.google.com/news/") || link.startsWith("https://news.google.com/news/")) {
|
||||
if (link.contains("&url=")) {
|
||||
link.substringAfter("&url=")
|
||||
} else {
|
||||
this.link.replace("&", "&")
|
||||
}
|
||||
} else {
|
||||
this.link.replace("&", "&")
|
||||
}
|
||||
stringUrl =
|
||||
if (link.startsWith("http://news.google.com/news/") || link.startsWith("https://news.google.com/news/")) {
|
||||
if (link.contains("&url=")) {
|
||||
link.substringAfter("&url=")
|
||||
} else {
|
||||
this.link.replace("&", "&")
|
||||
}
|
||||
} else {
|
||||
this.link.replace("&", "&")
|
||||
}
|
||||
|
||||
// handle :443 => https
|
||||
if (stringUrl.contains(":443")) {
|
||||
@ -144,7 +148,7 @@ data class Item(
|
||||
|
||||
// handle url not starting with http
|
||||
if (stringUrl.startsWith("//")) {
|
||||
stringUrl = "http:" + stringUrl
|
||||
stringUrl = "http:$stringUrl"
|
||||
}
|
||||
|
||||
return stringUrl
|
||||
|
@ -17,102 +17,102 @@ internal interface SelfossService {
|
||||
|
||||
@GET("items")
|
||||
fun getItems(
|
||||
@Query("type") type: String,
|
||||
@Query("tag") tag: String?,
|
||||
@Query("source") source: Long?,
|
||||
@Query("search") search: String?,
|
||||
@Query("username") username: String,
|
||||
@Query("password") password: String,
|
||||
@Query("items") items: Int,
|
||||
@Query("offset") offset: Int
|
||||
@Query("type") type: String,
|
||||
@Query("tag") tag: String?,
|
||||
@Query("source") source: Long?,
|
||||
@Query("search") search: String?,
|
||||
@Query("username") username: String,
|
||||
@Query("password") password: String,
|
||||
@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
|
||||
@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
|
||||
@Path("id") id: String,
|
||||
@Query("username") username: String,
|
||||
@Query("password") password: String
|
||||
): Call<SuccessResponse>
|
||||
|
||||
@FormUrlEncoded
|
||||
@POST("mark")
|
||||
fun markAllAsRead(
|
||||
@Field("ids[]") ids: List<String>,
|
||||
@Query("username") username: String,
|
||||
@Query("password") password: String
|
||||
@Field("ids[]") ids: List<String>,
|
||||
@Query("username") username: String,
|
||||
@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
|
||||
@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,
|
||||
@Query("password") password: String
|
||||
@Path("id") id: String,
|
||||
@Query("username") username: String,
|
||||
@Query("password") password: String
|
||||
): Call<SuccessResponse>
|
||||
|
||||
@GET("stats")
|
||||
fun stats(
|
||||
@Query("username") username: String,
|
||||
@Query("password") password: String
|
||||
@Query("username") username: String,
|
||||
@Query("password") password: String
|
||||
): Call<Stats>
|
||||
|
||||
@GET("tags")
|
||||
fun tags(
|
||||
@Query("username") username: String,
|
||||
@Query("password") password: String
|
||||
@Query("username") username: String,
|
||||
@Query("password") password: String
|
||||
): Call<List<Tag>>
|
||||
|
||||
@GET("update")
|
||||
fun update(
|
||||
@Query("username") username: String,
|
||||
@Query("password") password: String
|
||||
@Query("username") username: String,
|
||||
@Query("password") password: String
|
||||
): Call<String>
|
||||
|
||||
@GET("sources/spouts")
|
||||
fun spouts(
|
||||
@Query("username") username: String,
|
||||
@Query("password") password: String
|
||||
@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
|
||||
@Query("username") username: String,
|
||||
@Query("password") password: String
|
||||
): Call<List<Sources>>
|
||||
|
||||
@DELETE("source/{id}")
|
||||
fun deleteSource(
|
||||
@Path("id") id: String,
|
||||
@Query("username") username: String,
|
||||
@Query("password") password: String
|
||||
@Path("id") id: String,
|
||||
@Query("username") username: String,
|
||||
@Query("password") password: String
|
||||
): Call<SuccessResponse>
|
||||
|
||||
@FormUrlEncoded
|
||||
@POST("source")
|
||||
fun createSource(
|
||||
@Field("title") title: String,
|
||||
@Field("url") url: String,
|
||||
@Field("spout") spout: String,
|
||||
@Field("tags") tags: String,
|
||||
@Field("filter") filter: String,
|
||||
@Query("username") username: String,
|
||||
@Query("password") password: String
|
||||
@Field("title") title: String,
|
||||
@Field("url") url: String,
|
||||
@Field("spout") spout: String,
|
||||
@Field("tags") tags: String,
|
||||
@Field("filter") filter: String,
|
||||
@Query("username") username: String,
|
||||
@Query("password") password: String
|
||||
): Call<SuccessResponse>
|
||||
}
|
||||
|
@ -1,52 +1,64 @@
|
||||
package apps.amine.bou.readerforselfoss.fragments
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.SharedPreferences
|
||||
import android.content.res.ColorStateList
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.preference.PreferenceManager
|
||||
import android.support.customtabs.CustomTabsIntent
|
||||
import android.support.design.widget.FloatingActionButton
|
||||
import android.support.v4.app.Fragment
|
||||
import android.support.v4.content.ContextCompat
|
||||
import android.support.v4.widget.NestedScrollView
|
||||
import android.text.Html
|
||||
import android.text.method.LinkMovementMethod
|
||||
import android.support.v7.app.AlertDialog
|
||||
import android.view.LayoutInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.webkit.WebSettings
|
||||
import apps.amine.bou.readerforselfoss.BuildConfig
|
||||
import apps.amine.bou.readerforselfoss.R
|
||||
import apps.amine.bou.readerforselfoss.api.mercury.MercuryApi
|
||||
import apps.amine.bou.readerforselfoss.api.mercury.ParsedContent
|
||||
import apps.amine.bou.readerforselfoss.api.selfoss.Item
|
||||
import apps.amine.bou.readerforselfoss.themes.AppColors
|
||||
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 apps.amine.bou.readerforselfoss.utils.sourceAndDateText
|
||||
import apps.amine.bou.readerforselfoss.utils.toPx
|
||||
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 kotlinx.android.synthetic.main.fragment_article.view.*
|
||||
import retrofit2.Call
|
||||
import retrofit2.Callback
|
||||
import retrofit2.Response
|
||||
|
||||
|
||||
import kotlinx.android.synthetic.main.fragment_article.view.*
|
||||
import java.net.MalformedURLException
|
||||
import java.net.URL
|
||||
|
||||
class ArticleFragment : Fragment() {
|
||||
private lateinit var pageNumber: Number
|
||||
private var fontSize: Int = 14
|
||||
private lateinit var allItems: ArrayList<Item>
|
||||
private lateinit var mCustomTabActivityHelper: CustomTabActivityHelper
|
||||
//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 var showMalformedUrl: Boolean = false
|
||||
private lateinit var editor: SharedPreferences.Editor
|
||||
private lateinit var fab: FloatingActionButton
|
||||
private lateinit var appColors: AppColors
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
@ -54,20 +66,26 @@ class ArticleFragment : Fragment() {
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
appColors = AppColors(activity!!)
|
||||
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
pageNumber = arguments!!.getInt(ARG_POSITION)
|
||||
allItems = arguments!!.getParcelableArrayList(ARG_ITEMS)
|
||||
}
|
||||
|
||||
private lateinit var rootView: ViewGroup
|
||||
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
rootView = inflater
|
||||
.inflate(R.layout.fragment_article, container, false) as ViewGroup
|
||||
.inflate(R.layout.fragment_article, container, false) as ViewGroup
|
||||
|
||||
val context: Context = activity!!
|
||||
|
||||
url = allItems[pageNumber.toInt()].getLinkDecoded()
|
||||
contentText = allItems[pageNumber.toInt()].content
|
||||
@ -76,21 +94,33 @@ class ArticleFragment : Fragment() {
|
||||
contentSource = allItems[pageNumber.toInt()].sourceAndDateText()
|
||||
|
||||
fab = rootView.fab
|
||||
val mFloatingToolbar: FloatingToolbar = rootView.floatingToolbar
|
||||
mFloatingToolbar.attachFab(fab)
|
||||
|
||||
fab.backgroundTintList = ColorStateList.valueOf(appColors.colorAccent)
|
||||
|
||||
fab.rippleColor = appColors.colorAccentDark
|
||||
|
||||
val floatingToolbar: FloatingToolbar = rootView.floatingToolbar
|
||||
floatingToolbar.attachFab(fab)
|
||||
|
||||
floatingToolbar.background = ColorDrawable(appColors.colorAccent)
|
||||
|
||||
val customTabsIntent = activity!!.buildCustomTabsIntent()
|
||||
mCustomTabActivityHelper = CustomTabActivityHelper()
|
||||
mCustomTabActivityHelper.bindCustomTabsService(activity)
|
||||
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(activity)
|
||||
editor = prefs.edit()
|
||||
fontSize = prefs.getString("reader_font_size", "14").toInt()
|
||||
showMalformedUrl = prefs.getBoolean("show_error_malformed_url", true)
|
||||
|
||||
mFloatingToolbar.setClickListener(object : FloatingToolbar.ItemClickListener {
|
||||
override fun onItemClick(item: MenuItem) {
|
||||
when (item.itemId) {
|
||||
R.id.more_action -> getContentFromMercury(customTabsIntent, prefs)
|
||||
R.id.share_action -> activity!!.shareLink(url)
|
||||
R.id.open_action -> activity!!.openItemUrl(
|
||||
|
||||
floatingToolbar.setClickListener(
|
||||
object : FloatingToolbar.ItemClickListener {
|
||||
override fun onItemClick(item: MenuItem) {
|
||||
when (item.itemId) {
|
||||
R.id.more_action -> getContentFromMercury(customTabsIntent, prefs, context)
|
||||
R.id.share_action -> activity!!.shareLink(url)
|
||||
R.id.open_action -> activity!!.openItemUrl(
|
||||
allItems,
|
||||
pageNumber.toInt(),
|
||||
url,
|
||||
@ -98,138 +128,317 @@ class ArticleFragment : Fragment() {
|
||||
false,
|
||||
false,
|
||||
activity!!
|
||||
)
|
||||
else -> Unit
|
||||
)
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
override fun onItemLongClick(item: MenuItem?) {
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
override fun onItemLongClick(item: MenuItem?) {
|
||||
}
|
||||
})
|
||||
|
||||
rootView.source.text = contentSource
|
||||
|
||||
if (contentText.isEmptyOrNullOrNullString()) {
|
||||
getContentFromMercury(customTabsIntent, prefs)
|
||||
getContentFromMercury(customTabsIntent, prefs, context)
|
||||
} else {
|
||||
rootView.source.text = contentSource
|
||||
rootView.titleView.text = contentTitle
|
||||
tryToHandleHtml(contentText, customTabsIntent, prefs)
|
||||
|
||||
htmlToWebview(contentText, prefs, context)
|
||||
|
||||
if (!contentImage.isEmptyOrNullOrNullString()) {
|
||||
rootView.imageView.visibility = View.VISIBLE
|
||||
Glide
|
||||
.with(activity!!.baseContext)
|
||||
.asBitmap()
|
||||
.load(contentImage)
|
||||
.apply(RequestOptions.fitCenterTransform())
|
||||
.into(rootView.imageView)
|
||||
.with(context)
|
||||
.asBitmap()
|
||||
.load(contentImage)
|
||||
.apply(RequestOptions.fitCenterTransform())
|
||||
.into(rootView.imageView)
|
||||
} else {
|
||||
rootView.imageView.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
rootView.nestedScrollView.setOnScrollChangeListener(
|
||||
NestedScrollView.OnScrollChangeListener { _, _, scrollY, _, oldScrollY ->
|
||||
if (scrollY > oldScrollY) {
|
||||
fab.hide()
|
||||
} else {
|
||||
if (mFloatingToolbar.isShowing) mFloatingToolbar.hide() else fab.show()
|
||||
}
|
||||
NestedScrollView.OnScrollChangeListener { _, _, scrollY, _, oldScrollY ->
|
||||
if (scrollY > oldScrollY) {
|
||||
fab.hide()
|
||||
} else {
|
||||
if (floatingToolbar.isShowing) floatingToolbar.hide() else fab.show()
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
rootView.content.movementMethod = LinkMovementMethod.getInstance()
|
||||
|
||||
return rootView
|
||||
}
|
||||
|
||||
private fun getContentFromMercury(
|
||||
customTabsIntent: CustomTabsIntent,
|
||||
prefs: SharedPreferences
|
||||
customTabsIntent: CustomTabsIntent,
|
||||
prefs: SharedPreferences,
|
||||
context: Context
|
||||
) {
|
||||
rootView.progressBar.visibility = View.VISIBLE
|
||||
val parser = MercuryApi(
|
||||
BuildConfig.MERCURY_KEY,
|
||||
prefs.getBoolean("should_log_everything", false)
|
||||
BuildConfig.MERCURY_KEY,
|
||||
prefs.getBoolean("should_log_everything", false)
|
||||
)
|
||||
|
||||
parser.parseUrl(url).enqueue(object : Callback<ParsedContent> {
|
||||
override fun onResponse(
|
||||
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()) {
|
||||
rootView.source.text = response.body()!!.domain
|
||||
rootView.titleView.text = response.body()!!.title
|
||||
url = response.body()!!.url
|
||||
) {
|
||||
// TODO: clean all the following after finding the mercury content issue
|
||||
try {
|
||||
if (response.body() != null && response.body()!!.content != null && !response.body()!!.content.isNullOrEmpty()) {
|
||||
try {
|
||||
rootView.titleView.text = response.body()!!.title
|
||||
url = response.body()!!.url
|
||||
} catch (e: Exception) {
|
||||
Crashlytics.setUserIdentifier(prefs.getString("unique_id", ""))
|
||||
Crashlytics.log(
|
||||
100,
|
||||
"MERCURY_CONTENT_EXCEPTION",
|
||||
"source titleView or url issues"
|
||||
)
|
||||
Crashlytics.logException(e)
|
||||
}
|
||||
|
||||
if (response.body()!!.content != null && !response.body()!!.content.isEmpty()) {
|
||||
tryToHandleHtml(response.body()!!.content, customTabsIntent, prefs)
|
||||
try {
|
||||
htmlToWebview(response.body()!!.content.orEmpty(), prefs, context)
|
||||
} catch (e: Exception) {
|
||||
Crashlytics.setUserIdentifier(prefs.getString("unique_id", ""))
|
||||
Crashlytics.log(
|
||||
100,
|
||||
"MERCURY_CONTENT_EXCEPTION",
|
||||
"Webview issue ${e.message}"
|
||||
)
|
||||
Crashlytics.logException(e)
|
||||
}
|
||||
|
||||
try {
|
||||
if (response.body()!!.lead_image_url != null && !response.body()!!.lead_image_url.isNullOrEmpty()) {
|
||||
rootView.imageView.visibility = View.VISIBLE
|
||||
try {
|
||||
Glide
|
||||
.with(context)
|
||||
.asBitmap()
|
||||
.load(response.body()!!.lead_image_url)
|
||||
.apply(RequestOptions.fitCenterTransform())
|
||||
.into(rootView.imageView)
|
||||
} catch (e: Exception) {
|
||||
Crashlytics.setUserIdentifier(
|
||||
prefs.getString(
|
||||
"unique_id",
|
||||
""
|
||||
)
|
||||
)
|
||||
Crashlytics.log(
|
||||
100,
|
||||
"MERCURY_CONTENT_EXCEPTION",
|
||||
"Glide issue with image ${response.body()!!.lead_image_url}"
|
||||
)
|
||||
Crashlytics.logException(e)
|
||||
}
|
||||
} else {
|
||||
rootView.imageView.visibility = View.GONE
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Crashlytics.setUserIdentifier(prefs.getString("unique_id", ""))
|
||||
Crashlytics.log(
|
||||
100,
|
||||
"MERCURY_CONTENT_EXCEPTION",
|
||||
"Glide or image issue"
|
||||
)
|
||||
Crashlytics.logException(e)
|
||||
}
|
||||
|
||||
try {
|
||||
rootView.nestedScrollView.scrollTo(0, 0)
|
||||
|
||||
rootView.progressBar.visibility = View.GONE
|
||||
} catch (e: Exception) {
|
||||
Crashlytics.setUserIdentifier(prefs.getString("unique_id", ""))
|
||||
Crashlytics.log(
|
||||
100,
|
||||
"MERCURY_CONTENT_EXCEPTION",
|
||||
"Scroll or visibility issues"
|
||||
)
|
||||
Crashlytics.logException(e)
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
openInBrowserAfterFailing(customTabsIntent)
|
||||
} catch (e: Exception) {
|
||||
Crashlytics.setUserIdentifier(prefs.getString("unique_id", ""))
|
||||
Crashlytics.log(
|
||||
100,
|
||||
"MERCURY_CONTENT_EXCEPTION",
|
||||
"Browser after failing issue"
|
||||
)
|
||||
Crashlytics.logException(e)
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Crashlytics.setUserIdentifier(prefs.getString("unique_id", ""))
|
||||
Crashlytics.log(
|
||||
100,
|
||||
"MERCURY_CONTENT_EXCEPTION",
|
||||
"UNCAUGHT (?) Fatal Exception on mercury response"
|
||||
)
|
||||
Crashlytics.logException(e)
|
||||
}
|
||||
|
||||
if (response.body()!!.lead_image_url != null && !response.body()!!.lead_image_url.isEmpty()) {
|
||||
rootView.imageView.visibility = View.VISIBLE
|
||||
Glide
|
||||
.with(activity!!.baseContext)
|
||||
.asBitmap()
|
||||
.load(response.body()!!.lead_image_url)
|
||||
.apply(RequestOptions.fitCenterTransform())
|
||||
.into(rootView.imageView)
|
||||
} else {
|
||||
rootView.imageView.visibility = View.GONE
|
||||
}
|
||||
|
||||
rootView.nestedScrollView.scrollTo(0, 0)
|
||||
|
||||
rootView.progressBar.visibility = View.GONE
|
||||
} else {
|
||||
openInBrowserAfterFailing(customTabsIntent)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(
|
||||
override fun onFailure(
|
||||
call: Call<ParsedContent>,
|
||||
t: Throwable
|
||||
) = openInBrowserAfterFailing(customTabsIntent)
|
||||
})
|
||||
) = openInBrowserAfterFailing(customTabsIntent)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private fun tryToHandleHtml(
|
||||
c: String,
|
||||
customTabsIntent: CustomTabsIntent,
|
||||
prefs: SharedPreferences
|
||||
) {
|
||||
try {
|
||||
rootView.content.text = Html.fromHtml(c, HtmlHttpImageGetter(rootView.content, null, true), null)
|
||||
private fun htmlToWebview(c: String, prefs: SharedPreferences, context: Context) {
|
||||
|
||||
//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)
|
||||
val stringColor = String.format("#%06X", 0xFFFFFF and appColors.colorAccent)
|
||||
|
||||
rootView.webcontent.visibility = View.VISIBLE
|
||||
val (textColor, backgroundColor) = if (appColors.isDarkTheme) {
|
||||
rootView.webcontent.setBackgroundColor(
|
||||
ContextCompat.getColor(
|
||||
context,
|
||||
R.color.dark_webview
|
||||
)
|
||||
)
|
||||
Pair(ContextCompat.getColor(context, R.color.dark_webview_text), ContextCompat.getColor(context, R.color.light_webview_text))
|
||||
} else {
|
||||
rootView.webcontent.setBackgroundColor(
|
||||
ContextCompat.getColor(
|
||||
context,
|
||||
R.color.light_webview
|
||||
)
|
||||
)
|
||||
Pair(ContextCompat.getColor(context, R.color.light_webview_text), ContextCompat.getColor(context, R.color.dark_webview_text))
|
||||
}
|
||||
|
||||
val stringTextColor = String.format("#%06X", 0xFFFFFF and textColor)
|
||||
val stringBackgroundColor = String.format("#%06X", 0xFFFFFF and backgroundColor)
|
||||
|
||||
rootView.webcontent.settings.useWideViewPort = true
|
||||
rootView.webcontent.settings.loadWithOverviewMode = true
|
||||
rootView.webcontent.settings.javaScriptEnabled = false
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
rootView.webcontent.settings.layoutAlgorithm =
|
||||
WebSettings.LayoutAlgorithm.TEXT_AUTOSIZING
|
||||
} else {
|
||||
rootView.webcontent.settings.layoutAlgorithm = WebSettings.LayoutAlgorithm.SINGLE_COLUMN
|
||||
}
|
||||
|
||||
var baseUrl: String? = null
|
||||
|
||||
try {
|
||||
val itemUrl = URL(url)
|
||||
baseUrl = itemUrl.protocol + "://" + itemUrl.host
|
||||
} catch (e: MalformedURLException) {
|
||||
if (showMalformedUrl) {
|
||||
val alertDialog = AlertDialog.Builder(context).create()
|
||||
alertDialog.setTitle("Error")
|
||||
alertDialog.setMessage("You are encountering a bug that I can't solve. Can you please contact me to solve the issue, please ?")
|
||||
alertDialog.setButton(
|
||||
AlertDialog.BUTTON_POSITIVE,
|
||||
"Send mail",
|
||||
{ dialog, _ ->
|
||||
|
||||
// This won't be translated because it should only be temporary.
|
||||
val to = BuildConfig.FEEDBACK_EMAIL
|
||||
val subject= "[MalformedURLException]"
|
||||
val body= "Please specify the source, item and spout you are using for the url below : \n ${e.message}"
|
||||
val mailTo = "mailto:" + to + "?&subject=" + Uri.encode(subject) + "&body=" + Uri.encode(body)
|
||||
|
||||
val emailIntent = Intent(Intent.ACTION_VIEW)
|
||||
emailIntent.data = Uri.parse(mailTo)
|
||||
startActivity(emailIntent)
|
||||
|
||||
dialog.dismiss()
|
||||
}
|
||||
)
|
||||
alertDialog.setButton(
|
||||
AlertDialog.BUTTON_NEUTRAL,
|
||||
"Not now",
|
||||
{ dialog, _ -> dialog.dismiss() }
|
||||
)
|
||||
alertDialog.setButton(
|
||||
AlertDialog.BUTTON_NEGATIVE,
|
||||
"Don't show anymore.",
|
||||
{ dialog, _ ->
|
||||
editor.putBoolean("show_error_malformed_url", false)
|
||||
editor.apply()
|
||||
dialog.dismiss()
|
||||
}
|
||||
)
|
||||
alertDialog.show()
|
||||
}
|
||||
}
|
||||
|
||||
rootView.webcontent.loadDataWithBaseURL(
|
||||
baseUrl,
|
||||
"""<style>
|
||||
|img {
|
||||
| display: inline-block;
|
||||
| height: auto;
|
||||
| width: 100%;
|
||||
| max-width: 100%;
|
||||
|}
|
||||
|a {
|
||||
| color: $stringColor !important;
|
||||
|}
|
||||
|*:not(a) {
|
||||
| color: $stringTextColor;
|
||||
|}
|
||||
|* {
|
||||
| font-size: ${fontSize.toPx}px;
|
||||
| text-align: justify;
|
||||
| word-break: break-word;
|
||||
| overflow:hidden;
|
||||
|}
|
||||
|a, pre, code {
|
||||
| text-align: left;
|
||||
|}
|
||||
|pre, code {
|
||||
| white-space: pre-wrap;
|
||||
| width:100%;
|
||||
| background-color: $stringBackgroundColor;
|
||||
|}</style>$c""".trimMargin(),
|
||||
"text/html; charset=utf-8",
|
||||
"utf-8",
|
||||
null
|
||||
)
|
||||
}
|
||||
|
||||
private fun openInBrowserAfterFailing(customTabsIntent: CustomTabsIntent) {
|
||||
rootView.progressBar.visibility = View.GONE
|
||||
activity!!.openItemUrl(
|
||||
allItems,
|
||||
pageNumber.toInt(),
|
||||
url,
|
||||
customTabsIntent,
|
||||
true,
|
||||
false,
|
||||
activity!!
|
||||
allItems,
|
||||
pageNumber.toInt(),
|
||||
url,
|
||||
customTabsIntent,
|
||||
true,
|
||||
false,
|
||||
activity!!
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
companion object {
|
||||
private val ARG_POSITION = "position"
|
||||
private val ARG_ITEMS = "items"
|
||||
private const val ARG_POSITION = "position"
|
||||
private const val ARG_ITEMS = "items"
|
||||
|
||||
fun newInstance(position: Int, allItems: ArrayList<Item>): ArticleFragment {
|
||||
fun newInstance(
|
||||
position: Int,
|
||||
allItems: ArrayList<Item>
|
||||
): ArticleFragment {
|
||||
val fragment = ArticleFragment()
|
||||
val args = Bundle()
|
||||
args.putInt(ARG_POSITION, position)
|
||||
@ -238,4 +447,6 @@ class ArticleFragment : Fragment() {
|
||||
return fragment
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -16,23 +16,27 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import apps.amine.bou.readerforselfoss.R;
|
||||
import com.ftinc.scoop.Scoop;
|
||||
|
||||
import apps.amine.bou.readerforselfoss.R;
|
||||
import apps.amine.bou.readerforselfoss.themes.AppColors;
|
||||
import apps.amine.bou.readerforselfoss.themes.Toppings;
|
||||
|
||||
|
||||
/**
|
||||
* A {@link PreferenceActivity} which implements and proxies the necessary calls
|
||||
* to be used with AppCompat.
|
||||
*/
|
||||
public abstract class AppCompatPreferenceActivity extends PreferenceActivity { //NOSONAR
|
||||
public abstract class AppCompatPreferenceActivity extends PreferenceActivity {
|
||||
|
||||
private AppCompatDelegate mDelegate;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
new AppColors(this);
|
||||
|
||||
getDelegate().installViewFactory();
|
||||
getDelegate().onCreate(savedInstanceState);
|
||||
Scoop.getInstance().apply(this);
|
||||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
@ -40,9 +44,15 @@ public abstract class AppCompatPreferenceActivity extends PreferenceActivity { /
|
||||
protected void onPostCreate(Bundle savedInstanceState) {
|
||||
super.onPostCreate(savedInstanceState);
|
||||
|
||||
LinearLayout root = (LinearLayout)findViewById(android.R.id.list).getParent().getParent().getParent();
|
||||
LinearLayout root = (LinearLayout) findViewById(android.R.id.list).getParent().getParent().getParent();
|
||||
AppBarLayout bar = (AppBarLayout) LayoutInflater.from(this).inflate(R.layout.settings_toolbar, root, false);
|
||||
Toolbar toolbar = bar.findViewById(R.id.toolbar);
|
||||
|
||||
// TODO: all switches
|
||||
Scoop.getInstance()
|
||||
.bind(this, Toppings.PRIMARY.getValue(), toolbar)
|
||||
.bindStatusBar(this, Toppings.PRIMARY_DARK.getValue());
|
||||
|
||||
setSupportActionBar(toolbar);
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
getSupportActionBar().setDisplayShowHomeEnabled(true);
|
||||
|
@ -1,8 +1,6 @@
|
||||
package apps.amine.bou.readerforselfoss.settings;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
@ -22,15 +20,23 @@ import android.preference.PreferenceFragment;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.preference.SwitchPreference;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.text.Editable;
|
||||
import android.text.InputFilter;
|
||||
import android.text.Spanned;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.ftinc.scoop.ui.ScoopSettingsActivity;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import apps.amine.bou.readerforselfoss.BuildConfig;
|
||||
import apps.amine.bou.readerforselfoss.R;
|
||||
import apps.amine.bou.readerforselfoss.themes.AppColors;
|
||||
import apps.amine.bou.readerforselfoss.utils.Config;
|
||||
import com.ftinc.scoop.ui.ScoopSettingsActivity;
|
||||
|
||||
|
||||
/**
|
||||
@ -44,7 +50,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 { //NOSONAR
|
||||
public class SettingsActivity extends AppCompatPreferenceActivity {
|
||||
/**
|
||||
* A preference value change listener that updates the preference's summary
|
||||
* to reflect its new value.
|
||||
@ -90,6 +96,7 @@ public class SettingsActivity extends AppCompatPreferenceActivity { //NOSONAR
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
new AppColors(this);
|
||||
super.onCreate(savedInstanceState);
|
||||
setupActionBar();
|
||||
}
|
||||
@ -130,8 +137,10 @@ public class SettingsActivity extends AppCompatPreferenceActivity { //NOSONAR
|
||||
protected boolean isValidFragment(String fragmentName) {
|
||||
return PreferenceFragment.class.getName().equals(fragmentName)
|
||||
|| GeneralPreferenceFragment.class.getName().equals(fragmentName)
|
||||
|| ArticleViewerPreferenceFragment.class.getName().equals(fragmentName)
|
||||
|| DebugPreferenceFragment.class.getName().equals(fragmentName)
|
||||
|| LinksPreferenceFragment.class.getName().equals(fragmentName);
|
||||
|| LinksPreferenceFragment.class.getName().equals(fragmentName)
|
||||
|| ThemePreferenceFragment.class.getName().equals(fragmentName);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -150,7 +159,7 @@ public class SettingsActivity extends AppCompatPreferenceActivity { //NOSONAR
|
||||
final SwitchPreference tabOnTap = (SwitchPreference) findPreference("tab_on_tap");
|
||||
tabOnTap.setEnabled(!cardViewActive.isChecked());
|
||||
cardViewActive.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue){
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
boolean isEnabled = (Boolean) newValue;
|
||||
tabOnTap.setEnabled(!isEnabled);
|
||||
return true;
|
||||
@ -159,21 +168,71 @@ public class SettingsActivity extends AppCompatPreferenceActivity { //NOSONAR
|
||||
|
||||
EditTextPreference itemsNumber = (EditTextPreference) findPreference("prefer_api_items_number");
|
||||
itemsNumber.getEditText().setFilters(new InputFilter[]{
|
||||
new InputFilter (){
|
||||
new InputFilter() {
|
||||
|
||||
@Override
|
||||
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
|
||||
try {
|
||||
int input = Integer.parseInt(dest.toString() + source.toString());
|
||||
if (input <= 200 && input >0)
|
||||
return null;
|
||||
} catch (NumberFormatException nfe) {
|
||||
Toast.makeText(getActivity(), R.string.items_number_should_be_number, Toast.LENGTH_LONG).show();
|
||||
@Override
|
||||
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
|
||||
try {
|
||||
int input = Integer.parseInt(dest.toString() + source.toString());
|
||||
if (input <= 200 && input > 0)
|
||||
return null;
|
||||
} catch (NumberFormatException nfe) {
|
||||
Toast.makeText(getActivity(), R.string.items_number_should_be_number, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
int id = item.getItemId();
|
||||
if (id == android.R.id.home) {
|
||||
getActivity().finish();
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
|
||||
public static class ArticleViewerPreferenceFragment extends PreferenceFragment {
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
addPreferencesFromResource(R.xml.pref_viewer);
|
||||
setHasOptionsMenu(true);
|
||||
|
||||
final EditTextPreference fontSize = (EditTextPreference) findPreference("reader_font_size");
|
||||
fontSize.getEditText().addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable editable) {
|
||||
try {
|
||||
fontSize.getEditText().setTextSize(Integer.parseInt(editable.toString()));
|
||||
} catch (NumberFormatException e) {}
|
||||
}
|
||||
});
|
||||
fontSize.getEditText().setFilters(new InputFilter[]{
|
||||
new InputFilter() {
|
||||
|
||||
@Override
|
||||
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
|
||||
try {
|
||||
int input = Integer.parseInt(dest.toString() + source.toString());
|
||||
if (input > 0)
|
||||
return null;
|
||||
} catch (NumberFormatException nfe) {}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -195,7 +254,7 @@ public class SettingsActivity extends AppCompatPreferenceActivity { //NOSONAR
|
||||
addPreferencesFromResource(R.xml.pref_debug);
|
||||
setHasOptionsMenu(true);
|
||||
|
||||
SharedPreferences pref = getActivity().getSharedPreferences(Config.Companion.getSettingsName(), Context.MODE_PRIVATE);
|
||||
SharedPreferences pref = getActivity().getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE);
|
||||
final String id = pref.getString("unique_id", "...");
|
||||
|
||||
final Preference identifier = findPreference("debug_identifier");
|
||||
@ -205,11 +264,14 @@ public class SettingsActivity extends AppCompatPreferenceActivity { //NOSONAR
|
||||
identifier.setOnPreferenceClickListener(new OnPreferenceClickListener() {
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
ClipData clip = ClipData.newPlainText("Selfoss unique id", id);
|
||||
clipboard.setPrimaryClip(clip);
|
||||
if (clipboard != null) {
|
||||
ClipData clip = ClipData.newPlainText("Selfoss unique id", id);
|
||||
clipboard.setPrimaryClip(clip);
|
||||
|
||||
Toast.makeText(getActivity(), R.string.unique_id_to_clipboard, Toast.LENGTH_LONG).show();
|
||||
return true;
|
||||
Toast.makeText(getActivity(), R.string.unique_id_to_clipboard, Toast.LENGTH_LONG).show();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
identifier.setTitle(id);
|
||||
@ -243,7 +305,7 @@ public class SettingsActivity extends AppCompatPreferenceActivity { //NOSONAR
|
||||
addPreferencesFromResource(R.xml.pref_links);
|
||||
setHasOptionsMenu(true);
|
||||
|
||||
findPreference( "trackerLink" ).setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
|
||||
findPreference("trackerLink").setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
openUrl(Uri.parse(BuildConfig.TRACKER_URL));
|
||||
@ -279,14 +341,38 @@ public class SettingsActivity extends AppCompatPreferenceActivity { //NOSONAR
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHeaderClick(Header header, int position) {
|
||||
super.onHeaderClick(header, position);
|
||||
if (header.id == R.id.theme_change) {
|
||||
Intent intent = ScoopSettingsActivity.createIntent(getApplicationContext());
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
getApplicationContext().startActivity(intent);
|
||||
finish();
|
||||
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
|
||||
public static class ThemePreferenceFragment extends PreferenceFragment {
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
addPreferencesFromResource(R.xml.pref_theme);
|
||||
setHasOptionsMenu(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
int id = item.getItemId();
|
||||
if (id == android.R.id.home) {
|
||||
getActivity().finish();
|
||||
return true;
|
||||
} else if (id == R.id.clear) {
|
||||
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(getActivity());
|
||||
SharedPreferences.Editor editor = pref.edit();
|
||||
editor.remove("color_primary");
|
||||
editor.remove("color_primary_dark");
|
||||
editor.remove("color_accent");
|
||||
editor.remove("color_accent_dark");
|
||||
editor.remove("dark_theme");
|
||||
editor.apply();
|
||||
getActivity().finish();
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
inflater.inflate(R.menu.settings_theme, menu);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,49 +2,65 @@ package apps.amine.bou.readerforselfoss.themes
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.preference.PreferenceManager
|
||||
import android.support.annotation.ColorInt
|
||||
import android.support.v7.view.ContextThemeWrapper
|
||||
import android.util.TypedValue
|
||||
import apps.amine.bou.readerforselfoss.R
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
|
||||
class AppColors(a: Activity) {
|
||||
@ColorInt val accent: Int
|
||||
@ColorInt val dark: Int
|
||||
@ColorInt val primary: Int
|
||||
@ColorInt val cardBackground: Int
|
||||
@ColorInt val windowBackground: Int
|
||||
|
||||
@ColorInt val colorPrimary: Int
|
||||
@ColorInt val colorPrimaryDark: Int
|
||||
@ColorInt val colorAccent: Int
|
||||
@ColorInt val colorAccentDark: Int
|
||||
@ColorInt val cardBackgroundColor: Int
|
||||
val isDarkTheme: Boolean
|
||||
|
||||
init {
|
||||
val sharedPref = PreferenceManager.getDefaultSharedPreferences(a)
|
||||
|
||||
colorPrimary =
|
||||
sharedPref.getInt(
|
||||
"color_primary",
|
||||
a.resources.getColor(R.color.colorPrimary)
|
||||
)
|
||||
colorPrimaryDark =
|
||||
sharedPref.getInt(
|
||||
"color_primary_dark",
|
||||
a.resources.getColor(R.color.colorPrimaryDark)
|
||||
)
|
||||
colorAccent =
|
||||
sharedPref.getInt(
|
||||
"color_accent",
|
||||
a.resources.getColor(R.color.colorAccent)
|
||||
)
|
||||
colorAccentDark =
|
||||
sharedPref.getInt(
|
||||
"color_accent_dark",
|
||||
a.resources.getColor(R.color.colorAccentDark)
|
||||
)
|
||||
isDarkTheme =
|
||||
sharedPref.getBoolean(
|
||||
"dark_theme",
|
||||
false
|
||||
)
|
||||
|
||||
if (isDarkTheme) {
|
||||
a.setTheme(R.style.NoBarDark)
|
||||
} else {
|
||||
a.setTheme(R.style.NoBar)
|
||||
}
|
||||
|
||||
val wrapper = Context::class.java
|
||||
val method = wrapper!!.getMethod("getThemeResId")
|
||||
method.isAccessible = true
|
||||
|
||||
isDarkTheme = when (method.invoke(a.baseContext)) {
|
||||
R.style.NoBarTealOrangeDark,
|
||||
R.style.NoBarDark,
|
||||
R.style.NoBarBlueAmberDark,
|
||||
R.style.NoBarGreyOrangeDark,
|
||||
R.style.NoBarIndigoPinkDark,
|
||||
R.style.NoBarRedTealDark,
|
||||
R.style.NoBarCyanPinkDark -> true
|
||||
else -> false
|
||||
}
|
||||
|
||||
val typedAccent = TypedValue()
|
||||
val typedAccentDark = TypedValue()
|
||||
val typedPrimary = TypedValue()
|
||||
val typedCardBackground = TypedValue()
|
||||
val typedWindowBackground = TypedValue()
|
||||
|
||||
a.theme.resolveAttribute(R.attr.colorAccent, typedAccent, true)
|
||||
a.theme.resolveAttribute(R.attr.colorAccent, typedAccent, true)
|
||||
a.theme.resolveAttribute(R.attr.colorPrimary, typedPrimary, true)
|
||||
a.theme.resolveAttribute(R.attr.cardBackgroundColor, typedCardBackground, true)
|
||||
a.theme.resolveAttribute(android.R.attr.colorBackground, typedWindowBackground, true)
|
||||
accent = typedAccent.data
|
||||
dark = typedAccentDark.data
|
||||
primary = typedPrimary.data
|
||||
cardBackground = typedCardBackground.data
|
||||
windowBackground = typedWindowBackground.data
|
||||
|
||||
cardBackgroundColor = typedCardBackground.data
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,8 @@
|
||||
package apps.amine.bou.readerforselfoss.themes
|
||||
|
||||
enum class Toppings(val value: Int) {
|
||||
PRIMARY(1),
|
||||
PRIMARY_DARK(2),
|
||||
ACCENT(3),
|
||||
ACCENT_DARK(4)
|
||||
}
|
@ -4,4 +4,4 @@ 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
|
||||
this.code() === 200 && this.body() != null && this.body()!!.isSuccess
|
@ -9,12 +9,12 @@ import apps.amine.bou.readerforselfoss.R
|
||||
import com.google.firebase.remoteconfig.FirebaseRemoteConfig
|
||||
|
||||
fun String?.isEmptyOrNullOrNullString(): Boolean =
|
||||
this == null || this == "null" || this.isEmpty()
|
||||
this == null || this == "null" || this.isEmpty()
|
||||
|
||||
fun Context.checkApkVersion(
|
||||
settings: SharedPreferences,
|
||||
editor: SharedPreferences.Editor,
|
||||
mFirebaseRemoteConfig: FirebaseRemoteConfig
|
||||
settings: SharedPreferences,
|
||||
editor: SharedPreferences.Editor,
|
||||
mFirebaseRemoteConfig: FirebaseRemoteConfig
|
||||
) = {
|
||||
fun isThereAnUpdate() {
|
||||
val APK_LINK = "github_apk"
|
||||
@ -26,8 +26,8 @@ fun Context.checkApkVersion(
|
||||
alertDialog.setTitle(getString(R.string.new_apk_available_title))
|
||||
alertDialog.setMessage(getString(R.string.new_apk_available_message))
|
||||
alertDialog.setButton(
|
||||
AlertDialog.BUTTON_POSITIVE,
|
||||
getString(R.string.new_apk_available_get)
|
||||
AlertDialog.BUTTON_POSITIVE,
|
||||
getString(R.string.new_apk_available_get)
|
||||
) { _, _ ->
|
||||
editor.putString(APK_LINK, apkLink)
|
||||
editor.apply()
|
||||
@ -35,25 +35,25 @@ fun Context.checkApkVersion(
|
||||
startActivity(browserIntent)
|
||||
}
|
||||
alertDialog.setButton(
|
||||
AlertDialog.BUTTON_NEUTRAL, getString(R.string.new_apk_available_no),
|
||||
{ dialog, _ ->
|
||||
editor.putString(APK_LINK, apkLink)
|
||||
editor.apply()
|
||||
dialog.dismiss()
|
||||
}
|
||||
AlertDialog.BUTTON_NEUTRAL, getString(R.string.new_apk_available_no),
|
||||
{ dialog, _ ->
|
||||
editor.putString(APK_LINK, apkLink)
|
||||
editor.apply()
|
||||
dialog.dismiss()
|
||||
}
|
||||
)
|
||||
alertDialog.show()
|
||||
}
|
||||
}
|
||||
|
||||
mFirebaseRemoteConfig.fetch(43200)
|
||||
.addOnCompleteListener { task ->
|
||||
if (task.isSuccessful) {
|
||||
mFirebaseRemoteConfig.activateFetched()
|
||||
}
|
||||
|
||||
isThereAnUpdate()
|
||||
.addOnCompleteListener { task ->
|
||||
if (task.isSuccessful) {
|
||||
mFirebaseRemoteConfig.activateFetched()
|
||||
}
|
||||
|
||||
isThereAnUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
fun String.longHash(): Long {
|
||||
@ -68,11 +68,11 @@ fun String.longHash(): Long {
|
||||
}
|
||||
|
||||
fun String.toStringUriWithHttp(): String =
|
||||
if (!this.startsWith("https://") && !this.startsWith("http://")) {
|
||||
"http://" + this
|
||||
} else {
|
||||
this
|
||||
}
|
||||
if (!this.startsWith("https://") && !this.startsWith("http://")) {
|
||||
"http://" + this
|
||||
} else {
|
||||
this
|
||||
}
|
||||
|
||||
fun Context.shareLink(itemUrl: String) {
|
||||
val sendIntent = Intent()
|
||||
@ -81,9 +81,9 @@ fun Context.shareLink(itemUrl: String) {
|
||||
sendIntent.putExtra(Intent.EXTRA_TEXT, itemUrl.toStringUriWithHttp())
|
||||
sendIntent.type = "text/plain"
|
||||
startActivity(
|
||||
Intent.createChooser(
|
||||
sendIntent,
|
||||
getString(R.string.share)
|
||||
).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
Intent.createChooser(
|
||||
sendIntent,
|
||||
getString(R.string.share)
|
||||
).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
)
|
||||
}
|
@ -26,13 +26,13 @@ class Config(c: Context) {
|
||||
get() = settings.getString("httpPassword", "")
|
||||
|
||||
companion object {
|
||||
val settingsName = "paramsselfoss"
|
||||
const val settingsName = "paramsselfoss"
|
||||
|
||||
fun logoutAndRedirect(
|
||||
c: Context,
|
||||
callingActivity: Activity,
|
||||
editor: SharedPreferences.Editor,
|
||||
baseUrlFail: Boolean = false
|
||||
c: Context,
|
||||
callingActivity: Activity,
|
||||
editor: SharedPreferences.Editor,
|
||||
baseUrlFail: Boolean = false
|
||||
): Boolean {
|
||||
editor.remove("url")
|
||||
editor.remove("login")
|
||||
|
@ -7,37 +7,37 @@ import javax.net.ssl.SSLContext
|
||||
import javax.net.ssl.TrustManager
|
||||
import javax.net.ssl.X509TrustManager
|
||||
|
||||
fun getUnsafeHttpClient() =
|
||||
try {
|
||||
// Create a trust manager that does not validate certificate chains
|
||||
val trustAllCerts = arrayOf<TrustManager>(object : X509TrustManager {
|
||||
override fun getAcceptedIssuers(): Array<X509Certificate> =
|
||||
arrayOf()
|
||||
fun getUnsafeHttpClient(): OkHttpClient.Builder =
|
||||
try {
|
||||
// Create a trust manager that does not validate certificate chains
|
||||
val trustAllCerts = arrayOf<TrustManager>(object : X509TrustManager {
|
||||
override fun getAcceptedIssuers(): Array<X509Certificate> =
|
||||
arrayOf()
|
||||
|
||||
@Throws(CertificateException::class)
|
||||
override fun checkClientTrusted(
|
||||
chain: Array<java.security.cert.X509Certificate>,
|
||||
authType: String
|
||||
) {
|
||||
}
|
||||
@Throws(CertificateException::class)
|
||||
override fun checkClientTrusted(
|
||||
chain: Array<java.security.cert.X509Certificate>,
|
||||
authType: String
|
||||
) {
|
||||
}
|
||||
|
||||
@Throws(CertificateException::class)
|
||||
override fun checkServerTrusted(
|
||||
chain: Array<java.security.cert.X509Certificate>,
|
||||
authType: String
|
||||
) {
|
||||
}
|
||||
})
|
||||
@Throws(CertificateException::class)
|
||||
override fun checkServerTrusted(
|
||||
chain: Array<java.security.cert.X509Certificate>,
|
||||
authType: String
|
||||
) {
|
||||
}
|
||||
})
|
||||
|
||||
// Install the all-trusting trust manager
|
||||
val sslContext = SSLContext.getInstance("SSL")
|
||||
sslContext.init(null, trustAllCerts, java.security.SecureRandom())
|
||||
// Install the all-trusting trust manager
|
||||
val sslContext = SSLContext.getInstance("SSL")
|
||||
sslContext.init(null, trustAllCerts, java.security.SecureRandom())
|
||||
|
||||
val sslSocketFactory = sslContext.socketFactory
|
||||
val sslSocketFactory = sslContext.socketFactory
|
||||
|
||||
OkHttpClient.Builder()
|
||||
.sslSocketFactory(sslSocketFactory, trustAllCerts[0] as X509TrustManager)
|
||||
.hostnameVerifier { _, _ -> true }
|
||||
} catch (e: Exception) {
|
||||
throw RuntimeException(e)
|
||||
}
|
||||
OkHttpClient.Builder()
|
||||
.sslSocketFactory(sslSocketFactory, trustAllCerts[0] as X509TrustManager)
|
||||
.hostnameVerifier { _, _ -> true }
|
||||
} catch (e: Exception) {
|
||||
throw RuntimeException(e)
|
||||
}
|
@ -2,14 +2,24 @@ package apps.amine.bou.readerforselfoss.utils
|
||||
|
||||
import android.text.format.DateUtils
|
||||
import apps.amine.bou.readerforselfoss.api.selfoss.Item
|
||||
import com.crashlytics.android.Crashlytics
|
||||
import java.text.ParseException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
fun String.toTextDrawableString(): String {
|
||||
val textDrawable = StringBuilder()
|
||||
for (s in this.split(" ".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()) {
|
||||
textDrawable.append(s[0])
|
||||
for (s in this.split(" ".toRegex()).filter { !it.isEmpty() }.toTypedArray()) {
|
||||
try {
|
||||
textDrawable.append(s[0])
|
||||
} catch (e: StringIndexOutOfBoundsException) {
|
||||
Crashlytics.log(
|
||||
100,
|
||||
"TEXT_DRAWABLE_INDEX_OUT_OF_BOUND",
|
||||
this + " produces ${e.message}"
|
||||
)
|
||||
Crashlytics.logException(e)
|
||||
}
|
||||
}
|
||||
return textDrawable.toString()
|
||||
}
|
||||
@ -17,10 +27,10 @@ fun String.toTextDrawableString(): String {
|
||||
fun Item.sourceAndDateText(): String {
|
||||
val formattedDate: String = try {
|
||||
" " + DateUtils.getRelativeTimeSpanString(
|
||||
SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(this.datetime).time,
|
||||
Date().time,
|
||||
DateUtils.MINUTE_IN_MILLIS,
|
||||
DateUtils.FORMAT_ABBREV_RELATIVE
|
||||
SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(this.datetime).time,
|
||||
Date().time,
|
||||
DateUtils.MINUTE_IN_MILLIS,
|
||||
DateUtils.FORMAT_ABBREV_RELATIVE
|
||||
)
|
||||
} catch (e: ParseException) {
|
||||
e.printStackTrace()
|
||||
@ -28,4 +38,18 @@ fun Item.sourceAndDateText(): String {
|
||||
}
|
||||
|
||||
return this.sourcetitle + formattedDate
|
||||
}
|
||||
}
|
||||
|
||||
fun Item.toggleStar(): Item {
|
||||
this.starred = !this.starred
|
||||
return this
|
||||
}
|
||||
|
||||
fun List<Item>.flattenTags(): List<Item> =
|
||||
this.flatMap {
|
||||
val item = it
|
||||
val tags: List<String> = it.tags.split(",")
|
||||
tags.map {
|
||||
item.copy(tags = it.trim())
|
||||
}
|
||||
}
|
@ -20,10 +20,10 @@ fun Context.buildCustomTabsIntent(): CustomTabsIntent {
|
||||
val actionIntent = Intent(Intent.ACTION_SEND)
|
||||
actionIntent.type = "text/plain"
|
||||
val createPendingShareIntent: PendingIntent = PendingIntent.getActivity(
|
||||
this,
|
||||
0,
|
||||
actionIntent,
|
||||
0
|
||||
this,
|
||||
0,
|
||||
actionIntent,
|
||||
0
|
||||
)
|
||||
|
||||
val intentBuilder = CustomTabsIntent.Builder()
|
||||
@ -35,14 +35,14 @@ fun Context.buildCustomTabsIntent(): CustomTabsIntent {
|
||||
|
||||
|
||||
intentBuilder.setStartAnimations(
|
||||
this,
|
||||
R.anim.slide_in_right,
|
||||
R.anim.slide_out_left
|
||||
this,
|
||||
R.anim.slide_in_right,
|
||||
R.anim.slide_out_left
|
||||
)
|
||||
intentBuilder.setExitAnimations(
|
||||
this,
|
||||
android.R.anim.slide_in_left,
|
||||
android.R.anim.slide_out_right
|
||||
this,
|
||||
android.R.anim.slide_in_left,
|
||||
android.R.anim.slide_out_right
|
||||
)
|
||||
|
||||
val closeicon = BitmapFactory.decodeResource(resources, R.drawable.ic_close_white_24dp)
|
||||
@ -50,8 +50,8 @@ fun Context.buildCustomTabsIntent(): CustomTabsIntent {
|
||||
|
||||
val shareLabel = this.getString(R.string.label_share)
|
||||
val icon = BitmapFactory.decodeResource(
|
||||
resources,
|
||||
R.drawable.ic_share_white_24dp
|
||||
resources,
|
||||
R.drawable.ic_share_white_24dp
|
||||
)
|
||||
intentBuilder.setActionButton(icon, shareLabel, createPendingShareIntent)
|
||||
|
||||
@ -59,24 +59,24 @@ fun Context.buildCustomTabsIntent(): CustomTabsIntent {
|
||||
}
|
||||
|
||||
fun Context.openItemUrlInternally(
|
||||
allItems: ArrayList<Item>,
|
||||
currentItem: Int,
|
||||
linkDecoded: String,
|
||||
customTabsIntent: CustomTabsIntent,
|
||||
articleViewer: Boolean,
|
||||
app: Activity
|
||||
allItems: ArrayList<Item>,
|
||||
currentItem: Int,
|
||||
linkDecoded: String,
|
||||
customTabsIntent: CustomTabsIntent,
|
||||
articleViewer: Boolean,
|
||||
app: Activity
|
||||
) {
|
||||
if (articleViewer) {
|
||||
ReaderActivity.allItems = allItems
|
||||
val intent = Intent(this, ReaderActivity::class.java)
|
||||
intent.putParcelableArrayListExtra("allItems", allItems)
|
||||
intent.putExtra("currentItem", currentItem)
|
||||
app.startActivity(intent)
|
||||
} else {
|
||||
try {
|
||||
CustomTabActivityHelper.openCustomTab(
|
||||
app,
|
||||
customTabsIntent,
|
||||
Uri.parse(linkDecoded)
|
||||
app,
|
||||
customTabsIntent,
|
||||
Uri.parse(linkDecoded)
|
||||
) { _, uri ->
|
||||
val intent = Intent(Intent.ACTION_VIEW, uri)
|
||||
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
@ -89,32 +89,32 @@ fun Context.openItemUrlInternally(
|
||||
}
|
||||
|
||||
fun Context.openItemUrl(
|
||||
allItems: ArrayList<Item>,
|
||||
currentItem: Int,
|
||||
linkDecoded: String,
|
||||
customTabsIntent: CustomTabsIntent,
|
||||
internalBrowser: Boolean,
|
||||
articleViewer: Boolean,
|
||||
app: Activity
|
||||
allItems: ArrayList<Item>,
|
||||
currentItem: Int,
|
||||
linkDecoded: String,
|
||||
customTabsIntent: CustomTabsIntent,
|
||||
internalBrowser: Boolean,
|
||||
articleViewer: Boolean,
|
||||
app: Activity
|
||||
) {
|
||||
|
||||
if (!linkDecoded.isUrlValid()) {
|
||||
Toast.makeText(
|
||||
this,
|
||||
this.getString(R.string.cant_open_invalid_url),
|
||||
Toast.LENGTH_LONG
|
||||
this,
|
||||
this.getString(R.string.cant_open_invalid_url),
|
||||
Toast.LENGTH_LONG
|
||||
).show()
|
||||
} else {
|
||||
if (!internalBrowser) {
|
||||
openInBrowser(linkDecoded, app)
|
||||
} else {
|
||||
this.openItemUrlInternally(
|
||||
allItems,
|
||||
currentItem,
|
||||
linkDecoded,
|
||||
customTabsIntent,
|
||||
articleViewer,
|
||||
app
|
||||
allItems,
|
||||
currentItem,
|
||||
linkDecoded,
|
||||
customTabsIntent,
|
||||
articleViewer,
|
||||
app
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -127,7 +127,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)
|
||||
|
@ -7,37 +7,38 @@ import android.util.AttributeSet
|
||||
import android.view.View
|
||||
|
||||
class ScrollAwareFABBehavior(
|
||||
context: Context,
|
||||
attrs: AttributeSet
|
||||
context: Context,
|
||||
attrs: AttributeSet
|
||||
) : CoordinatorLayout.Behavior<FloatingActionButton>() {
|
||||
|
||||
|
||||
override fun onStartNestedScroll(
|
||||
coordinatorLayout: CoordinatorLayout,
|
||||
child: FloatingActionButton,
|
||||
directTargetChild: View,
|
||||
target: View,
|
||||
nestedScrollAxes: Int
|
||||
coordinatorLayout: CoordinatorLayout,
|
||||
child: FloatingActionButton,
|
||||
directTargetChild: View,
|
||||
target: View,
|
||||
nestedScrollAxes: Int
|
||||
): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onNestedScroll(
|
||||
coordinatorLayout: CoordinatorLayout,
|
||||
child: FloatingActionButton,
|
||||
target: View,
|
||||
dxConsumed: Int,
|
||||
dyConsumed: Int,
|
||||
dxUnconsumed: Int,
|
||||
dyUnconsumed: Int
|
||||
coordinatorLayout: CoordinatorLayout,
|
||||
child: FloatingActionButton,
|
||||
target: View,
|
||||
dxConsumed: Int,
|
||||
dyConsumed: Int,
|
||||
dxUnconsumed: Int,
|
||||
dyUnconsumed: Int
|
||||
) {
|
||||
super.onNestedScroll(
|
||||
coordinatorLayout,
|
||||
child,
|
||||
target,
|
||||
dxConsumed,
|
||||
dyConsumed,
|
||||
dxUnconsumed,
|
||||
dyUnconsumed
|
||||
coordinatorLayout,
|
||||
child,
|
||||
target,
|
||||
dxConsumed,
|
||||
dyConsumed,
|
||||
dxUnconsumed,
|
||||
dyUnconsumed
|
||||
)
|
||||
if (dyConsumed > 0 && child.visibility == View.VISIBLE) {
|
||||
child.hide(object : FloatingActionButton.OnVisibilityChangedListener() {
|
||||
|
@ -0,0 +1,9 @@
|
||||
package apps.amine.bou.readerforselfoss.utils
|
||||
|
||||
import android.content.res.Resources
|
||||
|
||||
val Int.toPx: Int
|
||||
get() = (this * Resources.getSystem().displayMetrics.density).toInt()
|
||||
|
||||
val Int.toDp: Int
|
||||
get() = (this / Resources.getSystem().displayMetrics.density).toInt()
|
@ -9,4 +9,4 @@ fun TextBadgeItem.removeBadge(): TextBadgeItem {
|
||||
}
|
||||
|
||||
fun TextBadgeItem.maybeShow(): TextBadgeItem =
|
||||
if (this.isHidden) this.show() else this
|
||||
if (this.isHidden) this.show() else this
|
||||
|
@ -1,8 +1,6 @@
|
||||
package apps.amine.bou.readerforselfoss.utils.customtabs;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
@ -11,6 +9,8 @@ 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.
|
||||
*/
|
||||
@ -23,15 +23,15 @@ public class CustomTabActivityHelper implements ServiceConnectionCallback {
|
||||
/**
|
||||
* Opens the URL on a Custom Tab if possible. Otherwise fallsback to opening it on a WebView.
|
||||
*
|
||||
* @param activity The host activity.
|
||||
* @param activity The host activity.
|
||||
* @param customTabsIntent a CustomTabsIntent to be used if Custom Tabs is available.
|
||||
* @param uri the Uri to be opened.
|
||||
* @param fallback a CustomTabFallback to be used if Custom Tabs is not available.
|
||||
* @param uri the Uri to be opened.
|
||||
* @param fallback a CustomTabFallback to be used if Custom Tabs is not available.
|
||||
*/
|
||||
public static void openCustomTab(Activity activity,
|
||||
CustomTabsIntent customTabsIntent,
|
||||
Uri uri,
|
||||
CustomTabFallback fallback) {
|
||||
CustomTabsIntent customTabsIntent,
|
||||
Uri uri,
|
||||
CustomTabFallback fallback) {
|
||||
String packageName = CustomTabsHelper.getPackageNameToUse(activity);
|
||||
|
||||
//If we cant find a package name, it means theres no browser that supports
|
||||
@ -48,6 +48,7 @@ public class CustomTabActivityHelper implements ServiceConnectionCallback {
|
||||
|
||||
/**
|
||||
* Unbinds the Activity from the Custom Tabs Service.
|
||||
*
|
||||
* @param activity the activity that is connected to the service.
|
||||
*/
|
||||
public void unbindCustomTabsService(Activity activity) {
|
||||
@ -74,6 +75,7 @@ public class CustomTabActivityHelper implements ServiceConnectionCallback {
|
||||
|
||||
/**
|
||||
* Register a Callback to be called when connected or disconnected from the Custom Tabs Service.
|
||||
*
|
||||
* @param connectionCallback
|
||||
*/
|
||||
public void setConnectionCallback(ConnectionCallback connectionCallback) {
|
||||
@ -82,6 +84,7 @@ public class CustomTabActivityHelper implements ServiceConnectionCallback {
|
||||
|
||||
/**
|
||||
* Binds the Activity to the Custom Tabs Service.
|
||||
*
|
||||
* @param activity the activity to be binded to the service.
|
||||
*/
|
||||
public void bindCustomTabsService(Activity activity) {
|
||||
@ -95,16 +98,15 @@ public class CustomTabActivityHelper implements ServiceConnectionCallback {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see {@link CustomTabsSession#mayLaunchUrl(Uri, Bundle, List)}.
|
||||
* @return true if call to mayLaunchUrl was accepted.
|
||||
* @see {@link CustomTabsSession#mayLaunchUrl(Uri, Bundle, List)}.
|
||||
*/
|
||||
public boolean mayLaunchUrl(Uri uri, Bundle extras, List<Bundle> otherLikelyBundles) {
|
||||
if (mClient == null) return false;
|
||||
|
||||
CustomTabsSession session = getSession();
|
||||
if (session == null) return false;
|
||||
return session != null && session.mayLaunchUrl(uri, extras, otherLikelyBundles);
|
||||
|
||||
return session.mayLaunchUrl(uri, extras, otherLikelyBundles);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -142,9 +144,8 @@ public class CustomTabActivityHelper implements ServiceConnectionCallback {
|
||||
*/
|
||||
public interface CustomTabFallback {
|
||||
/**
|
||||
*
|
||||
* @param activity The Activity that wants to open the Uri.
|
||||
* @param uri The uri to be opened by the fallback.
|
||||
* @param uri The uri to be opened by the fallback.
|
||||
*/
|
||||
void openUri(Activity activity, Uri uri);
|
||||
}
|
||||
|
@ -1,9 +1,6 @@
|
||||
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;
|
||||
@ -14,6 +11,9 @@ import android.support.customtabs.CustomTabsService;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import apps.amine.bou.readerforselfoss.utils.customtabs.helpers.KeepAliveService;
|
||||
|
||||
@SuppressWarnings("ALL")
|
||||
@ -28,7 +28,8 @@ class CustomTabsHelper {
|
||||
|
||||
private static String sPackageNameToUse;
|
||||
|
||||
private CustomTabsHelper() {}
|
||||
private CustomTabsHelper() {
|
||||
}
|
||||
|
||||
public static void addKeepAliveExtra(Context context, Intent intent) {
|
||||
Intent keepAliveIntent = new Intent().setClassName(
|
||||
@ -40,7 +41,7 @@ class CustomTabsHelper {
|
||||
* Goes through all apps that handle VIEW intents and have a warmup service. Picks
|
||||
* the one chosen by the user if there is one, otherwise makes a best effort to return a
|
||||
* valid package name.
|
||||
*
|
||||
* <p>
|
||||
* This is <strong>not</strong> threadsafe.
|
||||
*
|
||||
* @param context {@link Context} to use for accessing {@link PackageManager}.
|
||||
@ -94,6 +95,7 @@ class CustomTabsHelper {
|
||||
|
||||
/**
|
||||
* Used to check whether there is a specialized handler for a given intent.
|
||||
*
|
||||
* @param intent The intent to check with.
|
||||
* @return Whether there is a specialized handler for the given intent.
|
||||
*/
|
||||
|
@ -1,12 +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
|
||||
|
@ -7,6 +7,7 @@ import android.support.customtabs.CustomTabsClient;
|
||||
public interface ServiceConnectionCallback {
|
||||
/**
|
||||
* Called when the service is connected.
|
||||
*
|
||||
* @param client a CustomTabsClient
|
||||
*/
|
||||
void onServiceConnected(CustomTabsClient client);
|
||||
|
@ -15,7 +15,8 @@ import com.mikepenz.materialdrawer.util.DrawerImageLoader
|
||||
import com.mikepenz.materialdrawer.util.DrawerUIUtils
|
||||
import com.mikepenz.materialize.util.UIUtils
|
||||
|
||||
abstract class CustomUrlBasePrimaryDrawerItem<T, VH : RecyclerView.ViewHolder> : BaseDrawerItem<T, VH>() {
|
||||
abstract class CustomUrlBasePrimaryDrawerItem<T, VH : RecyclerView.ViewHolder> :
|
||||
BaseDrawerItem<T, VH>() {
|
||||
fun withIcon(url: String): T {
|
||||
this.icon = ImageHolder(url)
|
||||
return this as T
|
||||
@ -76,8 +77,8 @@ abstract class CustomUrlBasePrimaryDrawerItem<T, VH : RecyclerView.ViewHolder> :
|
||||
|
||||
//set the background for the item
|
||||
UIUtils.setBackground(
|
||||
viewHolder.view,
|
||||
UIUtils.getSelectableBackground(ctx, selectedColor, true)
|
||||
viewHolder.view,
|
||||
UIUtils.getSelectableBackground(ctx, selectedColor, true)
|
||||
)
|
||||
//set the text for the name
|
||||
StringHolder.applyTo(this.getName(), viewHolder.name)
|
||||
@ -88,9 +89,9 @@ abstract class CustomUrlBasePrimaryDrawerItem<T, VH : RecyclerView.ViewHolder> :
|
||||
viewHolder.name.setTextColor(getTextColorStateList(color, selectedTextColor))
|
||||
//set the description text color
|
||||
ColorHolder.applyToOr(
|
||||
descriptionTextColor,
|
||||
viewHolder.description,
|
||||
getTextColorStateList(color, selectedTextColor)
|
||||
descriptionTextColor,
|
||||
viewHolder.description,
|
||||
getTextColorStateList(color, selectedTextColor)
|
||||
)
|
||||
|
||||
//define the typeface for our textViews
|
||||
|
@ -10,7 +10,9 @@ import com.mikepenz.materialdrawer.holder.BadgeStyle
|
||||
import com.mikepenz.materialdrawer.holder.StringHolder
|
||||
import com.mikepenz.materialdrawer.model.interfaces.ColorfulBadgeable
|
||||
|
||||
class CustomUrlPrimaryDrawerItem : CustomUrlBasePrimaryDrawerItem<CustomUrlPrimaryDrawerItem, CustomUrlPrimaryDrawerItem.ViewHolder>(), ColorfulBadgeable<CustomUrlPrimaryDrawerItem> {
|
||||
class CustomUrlPrimaryDrawerItem :
|
||||
CustomUrlBasePrimaryDrawerItem<CustomUrlPrimaryDrawerItem, CustomUrlPrimaryDrawerItem.ViewHolder>(),
|
||||
ColorfulBadgeable<CustomUrlPrimaryDrawerItem> {
|
||||
protected var mBadge: StringHolder = StringHolder("")
|
||||
protected var mBadgeStyle = BadgeStyle()
|
||||
|
||||
@ -64,8 +66,8 @@ class CustomUrlPrimaryDrawerItem : CustomUrlBasePrimaryDrawerItem<CustomUrlPrima
|
||||
//style the badge if it is visible
|
||||
if (badgeVisible) {
|
||||
mBadgeStyle.style(
|
||||
viewHolder.badge,
|
||||
getTextColorStateList(getColor(ctx), getSelectedTextColor(ctx))
|
||||
viewHolder.badge,
|
||||
getTextColorStateList(getColor(ctx), getSelectedTextColor(ctx))
|
||||
)
|
||||
viewHolder.badgeContainer.visibility = View.VISIBLE
|
||||
} else {
|
||||
|
@ -9,31 +9,31 @@ import com.bumptech.glide.request.RequestOptions
|
||||
import com.bumptech.glide.request.target.BitmapImageViewTarget
|
||||
|
||||
fun Context.bitmapCenterCrop(url: String, iv: ImageView) =
|
||||
Glide.with(this)
|
||||
.asBitmap()
|
||||
.load(url)
|
||||
.apply(RequestOptions.centerCropTransform())
|
||||
.into(iv)
|
||||
Glide.with(this)
|
||||
.asBitmap()
|
||||
.load(url)
|
||||
.apply(RequestOptions.centerCropTransform())
|
||||
.into(iv)
|
||||
|
||||
fun Context.bitmapFitCenter(url: String, iv: ImageView) =
|
||||
Glide.with(this)
|
||||
.asBitmap()
|
||||
.load(url)
|
||||
.apply(RequestOptions.fitCenterTransform())
|
||||
.into(iv)
|
||||
Glide.with(this)
|
||||
.asBitmap()
|
||||
.load(url)
|
||||
.apply(RequestOptions.fitCenterTransform())
|
||||
.into(iv)
|
||||
|
||||
fun Context.circularBitmapDrawable(url: String, iv: ImageView) =
|
||||
Glide.with(this)
|
||||
.asBitmap()
|
||||
.load(url)
|
||||
.apply(RequestOptions.centerCropTransform())
|
||||
.into(object : BitmapImageViewTarget(iv) {
|
||||
override fun setResource(resource: Bitmap?) {
|
||||
val circularBitmapDrawable = RoundedBitmapDrawableFactory.create(
|
||||
resources,
|
||||
resource
|
||||
)
|
||||
circularBitmapDrawable.isCircular = true
|
||||
iv.setImageDrawable(circularBitmapDrawable)
|
||||
}
|
||||
})
|
||||
Glide.with(this)
|
||||
.asBitmap()
|
||||
.load(url)
|
||||
.apply(RequestOptions.centerCropTransform())
|
||||
.into(object : BitmapImageViewTarget(iv) {
|
||||
override fun setResource(resource: Bitmap?) {
|
||||
val circularBitmapDrawable = RoundedBitmapDrawableFactory.create(
|
||||
resources,
|
||||
resource
|
||||
)
|
||||
circularBitmapDrawable.isCircular = true
|
||||
iv.setImageDrawable(circularBitmapDrawable)
|
||||
}
|
||||
})
|
@ -23,9 +23,9 @@ class SelfSignedGlideModule : GlideModule {
|
||||
val client = getUnsafeHttpClient().build()
|
||||
|
||||
registry?.append(
|
||||
GlideUrl::class.java,
|
||||
InputStream::class.java,
|
||||
com.bumptech.glide.integration.okhttp3.OkHttpUrlLoader.Factory(client)
|
||||
GlideUrl::class.java,
|
||||
InputStream::class.java,
|
||||
com.bumptech.glide.integration.okhttp3.OkHttpUrlLoader.Factory(client)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 206 B |
BIN
app/src/main/res/drawable-hdpi/ic_history.png
Normal file
After Width: | Height: | Size: 551 B |
After Width: | Height: | Size: 134 B |
BIN
app/src/main/res/drawable-mdpi/ic_history.png
Normal file
After Width: | Height: | Size: 352 B |
After Width: | Height: | Size: 174 B |
BIN
app/src/main/res/drawable-xhdpi/ic_history.png
Normal file
After Width: | Height: | Size: 684 B |
After Width: | Height: | Size: 255 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_history.png
Normal file
After Width: | Height: | Size: 986 B |
After Width: | Height: | Size: 311 B |
BIN
app/src/main/res/drawable-xxxhdpi/ic_history.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
@ -1,36 +1,37 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
<ScrollView xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context="apps.amine.bou.readerforselfoss.AddSourceActivity"
|
||||
android:orientation="vertical">
|
||||
<android.support.design.widget.AppBarLayout
|
||||
tools:context="apps.amine.bou.readerforselfoss.AddSourceActivity">
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<android.support.v7.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
app:theme="@style/ToolBarStyle"
|
||||
app:popupTheme="?attr/toolbarPopupTheme" />
|
||||
|
||||
</android.support.design.widget.AppBarLayout>
|
||||
|
||||
|
||||
<android.support.constraint.ConstraintLayout
|
||||
android:paddingBottom="@dimen/activity_vertical_margin"
|
||||
android:paddingLeft="@dimen/activity_horizontal_margin"
|
||||
android:paddingRight="@dimen/activity_horizontal_margin"
|
||||
android:paddingTop="@dimen/activity_vertical_margin"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="match_parent">
|
||||
<android.support.constraint.ConstraintLayout
|
||||
android:orientation="vertical">
|
||||
|
||||
<android.support.design.widget.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<android.support.v7.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
app:theme="@style/ToolBarStyle"
|
||||
app:popupTheme="?attr/toolbarPopupTheme" />
|
||||
|
||||
</android.support.design.widget.AppBarLayout>
|
||||
|
||||
|
||||
|
||||
<android.support.constraint.ConstraintLayout
|
||||
android:paddingBottom="@dimen/activity_vertical_margin"
|
||||
android:paddingLeft="@dimen/activity_horizontal_margin"
|
||||
android:paddingRight="@dimen/activity_horizontal_margin"
|
||||
android:paddingTop="@dimen/activity_vertical_margin"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="match_parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
@ -119,19 +120,20 @@
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:layout_marginBottom="16dp"
|
||||
app:layout_constraintVertical_bias="0.0"/>
|
||||
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
|
||||
<ProgressBar
|
||||
style="?android:attr/progressBarStyleLarge"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/progress"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
style="?android:attr/progressBarStyleLarge"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="visible"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:visibility="visible"/>
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:visibility="gone" />
|
||||
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
@ -88,12 +88,14 @@
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Headline"
|
||||
android:background="@color/transparent"
|
||||
android:visibility="gone" />
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/recyclerView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/transparent"
|
||||
android:clipToPadding="false"
|
||||
android:paddingBottom="60dp"
|
||||
android:scrollbars="vertical"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
|
||||
</LinearLayout>
|
||||
|
@ -115,6 +115,7 @@
|
||||
android:visibility="gone">
|
||||
|
||||
<EditText
|
||||
android:inputType="text"
|
||||
android:id="@+id/httpLoginView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
@ -1,7 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.constraint.ConstraintLayout 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">
|
||||
|
||||
@ -26,6 +25,7 @@
|
||||
android:id="@+id/pager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:paddingTop="20dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
@ -37,8 +37,8 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="20dp"
|
||||
android:background="#55000000"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent" />
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/pager" />
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
|
@ -1,13 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<android.support.design.widget.CoordinatorLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<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"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context="apps.amine.bou.readerforselfoss.SourcesActivity"
|
||||
xmlns:fab="http://schemas.android.com/apk/res-auto">
|
||||
tools:context="apps.amine.bou.readerforselfoss.SourcesActivity">
|
||||
<android.support.design.widget.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
@ -3,7 +3,8 @@
|
||||
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">
|
||||
android:layout_height="match_parent"
|
||||
android:descendantFocusability="blocksDescendants">
|
||||
|
||||
<android.support.v4.widget.NestedScrollView
|
||||
android:id="@+id/nestedScrollView"
|
||||
@ -52,34 +53,22 @@
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/imageView" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/content"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:layout_marginTop="24dp"
|
||||
android:paddingBottom="48dp"
|
||||
android:textColorLink="?attr/colorAccent"
|
||||
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"
|
||||
<WebView
|
||||
android:id="@+id/webcontent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:textColorLink="?attr/colorAccent"
|
||||
android:visibility="gone"
|
||||
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/titleView" />-->
|
||||
app:layout_constraintTop_toBottomOf="@+id/source"
|
||||
tools:visibility="visible" />
|
||||
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
|
||||
@ -98,16 +87,12 @@
|
||||
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"
|
||||
|
@ -7,18 +7,11 @@
|
||||
android:minHeight="88dp">
|
||||
|
||||
|
||||
<android.support.constraint.Guideline
|
||||
android:id="@+id/guideline4"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintGuide_begin="99dp" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/itemImage"
|
||||
android:layout_width="88dp"
|
||||
android:layout_height="88dp"
|
||||
app:layout_constraintBottom_toTopOf="@+id/guideline4"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/actionBar"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
@ -26,24 +19,21 @@
|
||||
android:id="@+id/title"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:ellipsize="end"
|
||||
android:fontFamily="sans-serif"
|
||||
android:gravity="start"
|
||||
android:maxLines="3"
|
||||
android:ellipsize="end"
|
||||
android:textAlignment="viewStart"
|
||||
android:textAllCaps="false"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toTopOf="@+id/sourceTitleAndDate"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintStart_toEndOf="@+id/itemImage"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.0"
|
||||
tools:text="Titre" />
|
||||
|
||||
<TextView
|
||||
@ -53,13 +43,15 @@
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:gravity="start"
|
||||
android:textAlignment="viewStart"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintBottom_toTopOf="@+id/guideline4"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/actionBar"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintStart_toEndOf="@+id/itemImage"
|
||||
app:layout_constraintTop_toBottomOf="@+id/title"
|
||||
tools:text="Google Actualité Il y a 5h" />
|
||||
|
||||
<RelativeLayout
|
||||
@ -71,8 +63,6 @@
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/guideline4"
|
||||
app:layout_constraintVertical_bias="1.0"
|
||||
tools:visibility="visible">
|
||||
|
||||
<com.like.LikeButton
|
||||
|
17
app/src/main/res/menu/reader_menu.xml
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item
|
||||
android:id="@+id/unsave"
|
||||
android:icon="@drawable/heart_on"
|
||||
android:title="@string/remove_to_favs_reader"
|
||||
android:visible="true"
|
||||
app:showAsAction="ifRoom" />
|
||||
<item
|
||||
android:id="@+id/save"
|
||||
android:icon="@drawable/heart_off"
|
||||
android:title="@string/add_to_favs_reader"
|
||||
android:visible="true"
|
||||
app:showAsAction="ifRoom" />
|
||||
</menu>
|
@ -1,6 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item
|
||||
|
10
app/src/main/res/menu/settings_theme.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item
|
||||
android:id="@+id/clear"
|
||||
android:icon="@drawable/ic_history"
|
||||
android:title="@string/drawer_action_clear"
|
||||
app:showAsAction="ifRoom" />
|
||||
</menu>
|
@ -158,5 +158,13 @@
|
||||
<string name="reader_action_more">Read more</string>
|
||||
<string name="reader_action_open">Open in browser</string>
|
||||
<string name="reader_action_share">Share</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark articles as read when scrolling between articles.</string>
|
||||
<string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
|
||||
<string name="add_to_favs_reader">Add to favorites</string>
|
||||
<string name="remove_to_favs_reader">Remove from favorites</string>
|
||||
<string name="pref_content_reader_font_size">Article reader content font size</string>
|
||||
<string name="pref_header_viewer">Article viewer</string>
|
||||
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
|
||||
<string name="markall_dialog_message">This will mark all the items as read.</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
|
||||
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
|
||||
</resources>
|
||||
|
@ -158,5 +158,13 @@
|
||||
<string name="reader_action_more">Read more</string>
|
||||
<string name="reader_action_open">Open in browser</string>
|
||||
<string name="reader_action_share">Share</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark articles as read when scrolling between articles.</string>
|
||||
<string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
|
||||
<string name="add_to_favs_reader">Add to favorites</string>
|
||||
<string name="remove_to_favs_reader">Remove from favorites</string>
|
||||
<string name="pref_content_reader_font_size">Article reader content font size</string>
|
||||
<string name="pref_header_viewer">Article viewer</string>
|
||||
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
|
||||
<string name="markall_dialog_message">This will mark all the items as read.</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
|
||||
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
|
||||
</resources>
|
||||
|
@ -158,5 +158,13 @@
|
||||
<string name="reader_action_more">Read more</string>
|
||||
<string name="reader_action_open">Open in browser</string>
|
||||
<string name="reader_action_share">Share</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark articles as read when scrolling between articles.</string>
|
||||
<string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
|
||||
<string name="add_to_favs_reader">Add to favorites</string>
|
||||
<string name="remove_to_favs_reader">Remove from favorites</string>
|
||||
<string name="pref_content_reader_font_size">Article reader content font size</string>
|
||||
<string name="pref_header_viewer">Article viewer</string>
|
||||
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
|
||||
<string name="markall_dialog_message">This will mark all the items as read.</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
|
||||
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
|
||||
</resources>
|
||||
|
@ -158,5 +158,13 @@
|
||||
<string name="reader_action_more">Read more</string>
|
||||
<string name="reader_action_open">Open in browser</string>
|
||||
<string name="reader_action_share">Share</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark articles as read when scrolling between articles.</string>
|
||||
<string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
|
||||
<string name="add_to_favs_reader">Add to favorites</string>
|
||||
<string name="remove_to_favs_reader">Remove from favorites</string>
|
||||
<string name="pref_content_reader_font_size">Article reader content font size</string>
|
||||
<string name="pref_header_viewer">Article viewer</string>
|
||||
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
|
||||
<string name="markall_dialog_message">This will mark all the items as read.</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
|
||||
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
|
||||
</resources>
|
||||
|
@ -158,5 +158,13 @@
|
||||
<string name="reader_action_more">Read more</string>
|
||||
<string name="reader_action_open">Open in browser</string>
|
||||
<string name="reader_action_share">Share</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark articles as read when scrolling between articles.</string>
|
||||
<string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
|
||||
<string name="add_to_favs_reader">Add to favorites</string>
|
||||
<string name="remove_to_favs_reader">Remove from favorites</string>
|
||||
<string name="pref_content_reader_font_size">Article reader content font size</string>
|
||||
<string name="pref_header_viewer">Article viewer</string>
|
||||
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
|
||||
<string name="markall_dialog_message">This will mark all the items as read.</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
|
||||
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
|
||||
</resources>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--Generated by crowdin.com-->
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<string name="app_name">"Reader für Selfoss"</string>
|
||||
<string name="app_name">"Reader für selfoss"</string>
|
||||
<string name="title_activity_login">"Anmelden"</string>
|
||||
<string name="prompt_password">"Passwort"</string>
|
||||
<string name="prompt_http_password">"HTTP Passwort"</string>
|
||||
@ -33,7 +33,7 @@
|
||||
<string name="cant_get_read">"Gelese Artikel können nicht abgerufen werden"</string>
|
||||
<string name="nothing_here">"Keine Einträge vorhanden"</string>
|
||||
<string name="tab_new">"Neu"</string>
|
||||
<string name="tab_read">"All"</string>
|
||||
<string name="tab_read">"Alle"</string>
|
||||
<string name="tab_favs">"Favoriten"</string>
|
||||
<string name="action_about">"Über"</string>
|
||||
<string name="marked_as_read">"Artikel gelesen"</string>
|
||||
@ -138,7 +138,7 @@
|
||||
<string name="login_menu_debug">Debug</string>
|
||||
<string name="self_hosted_cert_switch">Verwenden Sie einen selbst gehostetes Zertifikat?</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="pref_selfoss_category">Selfoss Api</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>
|
||||
@ -153,10 +153,18 @@
|
||||
<string name="pref_general_infinite_loading_title">Load more articles on scroll</string>
|
||||
<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="drawer_report_bug">Melde einen Fehler</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>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark articles as read when scrolling between articles.</string>
|
||||
<string name="reader_action_open">Im Browser öffnen</string>
|
||||
<string name="reader_action_share">Teilen</string>
|
||||
<string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
|
||||
<string name="add_to_favs_reader">Zu Favoriten hinzufügen</string>
|
||||
<string name="remove_to_favs_reader">Remove from favorites</string>
|
||||
<string name="pref_content_reader_font_size">Article reader content font size</string>
|
||||
<string name="pref_header_viewer">Article viewer</string>
|
||||
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
|
||||
<string name="markall_dialog_message">This will mark all the items as read.</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
|
||||
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
|
||||
</resources>
|
||||
|
@ -158,5 +158,13 @@
|
||||
<string name="reader_action_more">Read more</string>
|
||||
<string name="reader_action_open">Open in browser</string>
|
||||
<string name="reader_action_share">Share</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark articles as read when scrolling between articles.</string>
|
||||
<string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
|
||||
<string name="add_to_favs_reader">Add to favorites</string>
|
||||
<string name="remove_to_favs_reader">Remove from favorites</string>
|
||||
<string name="pref_content_reader_font_size">Article reader content font size</string>
|
||||
<string name="pref_header_viewer">Article viewer</string>
|
||||
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
|
||||
<string name="markall_dialog_message">This will mark all the items as read.</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
|
||||
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
|
||||
</resources>
|
||||
|
@ -1,162 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--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="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="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="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="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="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 handling"</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="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="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">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="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>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark articles as read when scrolling between articles.</string>
|
||||
</resources>
|
@ -158,5 +158,13 @@
|
||||
<string name="reader_action_more">Leer más</string>
|
||||
<string name="reader_action_open">Abrir en el navegador</string>
|
||||
<string name="reader_action_share">Compartir</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark articles as read when scrolling between articles.</string>
|
||||
<string name="pref_switch_actions_pager_scroll_on">Marcar artículos como leidos al desplazarse entre ellos.</string>
|
||||
<string name="add_to_favs_reader">Añadir a Favoritos</string>
|
||||
<string name="remove_to_favs_reader">Eliminar de favoritos</string>
|
||||
<string name="pref_content_reader_font_size">Tamaño de la fuente</string>
|
||||
<string name="pref_header_viewer">Visor de artículos</string>
|
||||
<string name="refresh_dialog_message">Esto actualizará su instancia de Selfoss.</string>
|
||||
<string name="markall_dialog_message">Esto marcará todos los artículos como leídos.</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Marcar como leído al arrastrar</string>
|
||||
<string name="pref_switch_actions_pager_scroll_off">No marca artículos como leídos al arrastrar.</string>
|
||||
</resources>
|
||||
|
@ -158,5 +158,13 @@
|
||||
<string name="reader_action_more">Read more</string>
|
||||
<string name="reader_action_open">Open in browser</string>
|
||||
<string name="reader_action_share">Share</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark articles as read when scrolling between articles.</string>
|
||||
<string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
|
||||
<string name="add_to_favs_reader">Add to favorites</string>
|
||||
<string name="remove_to_favs_reader">Remove from favorites</string>
|
||||
<string name="pref_content_reader_font_size">Article reader content font size</string>
|
||||
<string name="pref_header_viewer">Article viewer</string>
|
||||
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
|
||||
<string name="markall_dialog_message">This will mark all the items as read.</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
|
||||
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
|
||||
</resources>
|
||||
|
@ -43,8 +43,8 @@
|
||||
<string name="cant_create_source">"Impossible de créer la source."</string>
|
||||
<string name="cant_get_spouts">"Impossible de récupérer vos Spouts pour rajouter des sources"</string>
|
||||
<string name="form_not_complete">"Il manque des données. Terminez le formulaire."</string>
|
||||
<string name="pref_header_links">"Liens utils"</string>
|
||||
<string name="issue_tracker_link">"Suivie des problèmes"</string>
|
||||
<string name="pref_header_links">"Liens utiles"</string>
|
||||
<string name="issue_tracker_link">"Suivi des problèmes"</string>
|
||||
<string name="issue_tracker_summary">"Pour signaler un bug ou demander une nouvelle fonctionnalité"</string>
|
||||
<string name="warning_wrong_url">"ATTENTION"</string>
|
||||
<string name="pref_switch_card_view_title">"Card View"</string>
|
||||
@ -65,10 +65,10 @@
|
||||
<string name="switch_unread_count_title">"Afficher le nombre de non lus"</string>
|
||||
<string name="display_all_counts_title">"Afficher le nombre de favoris et d'articles lus"</string>
|
||||
<string name="menu_share_the_app">"Inviter des amis"</string>
|
||||
<string name="invitation_title">"Essaye cette application pour les flux RSS Selfoss !"</string>
|
||||
<string name="invitation_title">"Essaye cette application pour les flux RSS Selfoss !"</string>
|
||||
<string name="invitation_message">"J'utilise cette applications pour mon flux RSS Selfoss. Tu aimeras peut être !"</string>
|
||||
<string name="invitation_cta">"Essayer maintenant"</string>
|
||||
<string name="text_wrong_url">"Vous semblez essayer de vous connceter avec une URL invalide. Assurez-vous que c'est la bonne, et si le problème persiste, contactez-moi via le lien du play store. Notez aussi que l'application ne peut fonctionner sans l'application web Selfoss. Vous ne pouvez pas utiliser l'application pour accéder directement aux flux RSS."</string>
|
||||
<string name="text_wrong_url">"Vous semblez essayer de vous connecter avec une URL invalide. Assurez-vous que c'est la bonne, et si le problème persiste, contactez-moi via le lien du play store. Notez aussi que l'application ne peut fonctionner sans l'application web Selfoss. Vous ne pouvez pas utiliser l'application pour accéder directement aux flux RSS."</string>
|
||||
<string name="pref_general_internal_browser_title">"Ouvrir les liens dans l'application"</string>
|
||||
<string name="pref_general_internal_browser_on">"Les articles s'ouvriront dans l'application"</string>
|
||||
<string name="pref_general_internal_browser_off">"Les articles s'ouvriront dans votre naviguateur par défaut"</string>
|
||||
@ -81,7 +81,7 @@
|
||||
<string name="pref_switch_card_view_on">"Les articles seront affichés en forme de carte"</string>
|
||||
<string name="pref_switch_card_view_off">"Les articles seront affichés en liste"</string>
|
||||
<string name="pref_switch_actions_tap_on">"Afficher la barre d'action sous l'article"</string>
|
||||
<string name="pref_switch_actions_tap_off">"Le clique sur un article l'ouvrira dans le naviguateur selectionné"</string>
|
||||
<string name="pref_switch_actions_tap_off">"Le clic sur un article l'ouvrira dans le navigateur sélectionné"</string>
|
||||
<string name="menu_home_refresh">"Mettre à jour"</string>
|
||||
<string name="refresh_success_response">"Mise à jour effectuée."</string>
|
||||
<string name="refresh_failer_message">"La mise à jour n'a pas fonctionné. Vérifiez vos logs selfoss."</string>
|
||||
@ -132,19 +132,19 @@
|
||||
<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 logguer toutes les erreurs de connexion</string>
|
||||
<string name="login_debug_title">Activez pour loguer 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>
|
||||
<string name="self_hosted_cert_switch">Certificat auto-signé ?</string>
|
||||
<string name="self_signed_cert_warning">Pour des raisons de sécurités, les certificats auto-signés sont désactivés par défaut. En les activant, je ne serais pas responsable de quelconques problèmes de sécurité rencontrés.</string>
|
||||
<string name="self_signed_cert_warning">Pour des raisons de sécurité, les certificats auto-signés sont désactivés par défaut. En les activant, je ne serais pas responsable de quelconques problèmes de sécurité rencontrés.</string>
|
||||
<string name="pref_selfoss_category">Api Selfoss</string>
|
||||
<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 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="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>
|
||||
<string name="display_header_drawer_title">Entête de compte</string>
|
||||
<string name="login_everything_title">Log de tous les appels à l\'API</string>
|
||||
@ -158,5 +158,13 @@
|
||||
<string name="reader_action_more">Lire plus</string>
|
||||
<string name="reader_action_open">Ouvrir</string>
|
||||
<string name="reader_action_share">Partager</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Marquer les articles comme lues au sroll.</string>
|
||||
<string name="pref_switch_actions_pager_scroll_on">Marquer les articles comme lus à la navigation dans le lecteur d\'article.</string>
|
||||
<string name="add_to_favs_reader">Ajouter aux favoris</string>
|
||||
<string name="remove_to_favs_reader">Supprimer des favoris</string>
|
||||
<string name="pref_content_reader_font_size">Taille du texte du contenu du lecteur d\'articles</string>
|
||||
<string name="pref_header_viewer">Lecteur d\'articles</string>
|
||||
<string name="refresh_dialog_message">En validant, votre instance Selfoss sera mise à jour.</string>
|
||||
<string name="markall_dialog_message">Marquer tous les éléments comme lus ?</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Marquer comme lu à la navigation.</string>
|
||||
<string name="pref_switch_actions_pager_scroll_off">Ne pas marquer les articles comme lus à la navigation.</string>
|
||||
</resources>
|
||||
|
@ -158,5 +158,13 @@
|
||||
<string name="reader_action_more">Read more</string>
|
||||
<string name="reader_action_open">Open in browser</string>
|
||||
<string name="reader_action_share">Share</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark articles as read when scrolling between articles.</string>
|
||||
<string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
|
||||
<string name="add_to_favs_reader">Add to favorites</string>
|
||||
<string name="remove_to_favs_reader">Remove from favorites</string>
|
||||
<string name="pref_content_reader_font_size">Article reader content font size</string>
|
||||
<string name="pref_header_viewer">Article viewer</string>
|
||||
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
|
||||
<string name="markall_dialog_message">This will mark all the items as read.</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
|
||||
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
|
||||
</resources>
|
||||
|
@ -158,5 +158,13 @@
|
||||
<string name="reader_action_more">Baca lebih lanjut</string>
|
||||
<string name="reader_action_open">Buka di peramban</string>
|
||||
<string name="reader_action_share">Bagikan</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark articles as read when scrolling between articles.</string>
|
||||
<string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
|
||||
<string name="add_to_favs_reader">Add to favorites</string>
|
||||
<string name="remove_to_favs_reader">Remove from favorites</string>
|
||||
<string name="pref_content_reader_font_size">Article reader content font size</string>
|
||||
<string name="pref_header_viewer">Article viewer</string>
|
||||
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
|
||||
<string name="markall_dialog_message">This will mark all the items as read.</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
|
||||
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
|
||||
</resources>
|
||||
|
@ -158,5 +158,13 @@
|
||||
<string name="reader_action_more">Read more</string>
|
||||
<string name="reader_action_open">Open in browser</string>
|
||||
<string name="reader_action_share">Share</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark articles as read when scrolling between articles.</string>
|
||||
<string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
|
||||
<string name="add_to_favs_reader">Add to favorites</string>
|
||||
<string name="remove_to_favs_reader">Remove from favorites</string>
|
||||
<string name="pref_content_reader_font_size">Article reader content font size</string>
|
||||
<string name="pref_header_viewer">Article viewer</string>
|
||||
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
|
||||
<string name="markall_dialog_message">This will mark all the items as read.</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
|
||||
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
|
||||
</resources>
|
||||
|
@ -158,5 +158,13 @@
|
||||
<string name="reader_action_more">Read more</string>
|
||||
<string name="reader_action_open">Open in browser</string>
|
||||
<string name="reader_action_share">Share</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark articles as read when scrolling between articles.</string>
|
||||
<string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
|
||||
<string name="add_to_favs_reader">Add to favorites</string>
|
||||
<string name="remove_to_favs_reader">Remove from favorites</string>
|
||||
<string name="pref_content_reader_font_size">Article reader content font size</string>
|
||||
<string name="pref_header_viewer">Article viewer</string>
|
||||
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
|
||||
<string name="markall_dialog_message">This will mark all the items as read.</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
|
||||
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
|
||||
</resources>
|
||||
|
@ -158,5 +158,13 @@
|
||||
<string name="reader_action_more">Read more</string>
|
||||
<string name="reader_action_open">Open in browser</string>
|
||||
<string name="reader_action_share">Share</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark articles as read when scrolling between articles.</string>
|
||||
<string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
|
||||
<string name="add_to_favs_reader">Add to favorites</string>
|
||||
<string name="remove_to_favs_reader">Remove from favorites</string>
|
||||
<string name="pref_content_reader_font_size">Article reader content font size</string>
|
||||
<string name="pref_header_viewer">Article viewer</string>
|
||||
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
|
||||
<string name="markall_dialog_message">This will mark all the items as read.</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
|
||||
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
|
||||
</resources>
|
||||
|
@ -158,5 +158,13 @@
|
||||
<string name="reader_action_more">Read more</string>
|
||||
<string name="reader_action_open">Open in browser</string>
|
||||
<string name="reader_action_share">Share</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark articles as read when scrolling between articles.</string>
|
||||
<string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
|
||||
<string name="add_to_favs_reader">Add to favorites</string>
|
||||
<string name="remove_to_favs_reader">Remove from favorites</string>
|
||||
<string name="pref_content_reader_font_size">Article reader content font size</string>
|
||||
<string name="pref_header_viewer">Article viewer</string>
|
||||
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
|
||||
<string name="markall_dialog_message">This will mark all the items as read.</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
|
||||
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
|
||||
</resources>
|
||||
|
@ -158,5 +158,13 @@
|
||||
<string name="reader_action_more">Lees meer</string>
|
||||
<string name="reader_action_open">Openen in browser</string>
|
||||
<string name="reader_action_share">Delen</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark articles as read when scrolling between articles.</string>
|
||||
<string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
|
||||
<string name="add_to_favs_reader">Add to favorites</string>
|
||||
<string name="remove_to_favs_reader">Remove from favorites</string>
|
||||
<string name="pref_content_reader_font_size">Article reader content font size</string>
|
||||
<string name="pref_header_viewer">Article viewer</string>
|
||||
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
|
||||
<string name="markall_dialog_message">This will mark all the items as read.</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
|
||||
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
|
||||
</resources>
|
||||
|
@ -158,5 +158,13 @@
|
||||
<string name="reader_action_more">Read more</string>
|
||||
<string name="reader_action_open">Open in browser</string>
|
||||
<string name="reader_action_share">Share</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark articles as read when scrolling between articles.</string>
|
||||
<string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
|
||||
<string name="add_to_favs_reader">Add to favorites</string>
|
||||
<string name="remove_to_favs_reader">Remove from favorites</string>
|
||||
<string name="pref_content_reader_font_size">Article reader content font size</string>
|
||||
<string name="pref_header_viewer">Article viewer</string>
|
||||
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
|
||||
<string name="markall_dialog_message">This will mark all the items as read.</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
|
||||
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
|
||||
</resources>
|
||||
|
@ -158,5 +158,13 @@
|
||||
<string name="reader_action_more">Read more</string>
|
||||
<string name="reader_action_open">Open in browser</string>
|
||||
<string name="reader_action_share">Share</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark articles as read when scrolling between articles.</string>
|
||||
<string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
|
||||
<string name="add_to_favs_reader">Add to favorites</string>
|
||||
<string name="remove_to_favs_reader">Remove from favorites</string>
|
||||
<string name="pref_content_reader_font_size">Article reader content font size</string>
|
||||
<string name="pref_header_viewer">Article viewer</string>
|
||||
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
|
||||
<string name="markall_dialog_message">This will mark all the items as read.</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
|
||||
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
|
||||
</resources>
|
||||
|
@ -158,5 +158,13 @@
|
||||
<string name="reader_action_more">Leia mais</string>
|
||||
<string name="reader_action_open">Abrir no navegador</string>
|
||||
<string name="reader_action_share">Compartilhar</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark articles as read when scrolling between articles.</string>
|
||||
<string name="pref_switch_actions_pager_scroll_on">Se esta configuração estiver ativada, os artigos serão marcados como lidos ao deslizar para a esquerda e para a direita no leitor do artigo.</string>
|
||||
<string name="add_to_favs_reader">Adicionar aos favoritos</string>
|
||||
<string name="remove_to_favs_reader">Remover dos favoritos</string>
|
||||
<string name="pref_content_reader_font_size">Tamanho da fonte do conteúdo do leitor de artigos</string>
|
||||
<string name="pref_header_viewer">Visualizador de artigos</string>
|
||||
<string name="refresh_dialog_message">Isso atualizará sua instância do Selfoss.</string>
|
||||
<string name="markall_dialog_message">Isso marcará todos os itens como lidos.</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
|
||||
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
|
||||
</resources>
|
||||
|
@ -1,162 +1,170 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--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="app_name">"Leitor para Selfoss"</string>
|
||||
<string name="title_activity_login">"Iniciar sessão"</string>
|
||||
<string name="prompt_password">"Palavra passe"</string>
|
||||
<string name="prompt_http_password">"Senha HTTP"</string>
|
||||
<string name="action_sign_in">"Ir"</string>
|
||||
<string name="error_invalid_password">"Senha não é longa o suficiente"</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 fazer login?"</string>
|
||||
<string name="withHttpLoginSwitch">"É necessário fazer login on HTTP?"</string>
|
||||
<string name="login_url_problem">"Uups. Você pode precisar adicionar uma \"/\" no final da url."</string>
|
||||
<string name="prompt_login">"Nome do usuário"</string>
|
||||
<string name="prompt_http_login">"Nome de utilizador HTTP"</string>
|
||||
<string name="label_share">"Compartilhar"</string>
|
||||
<string name="readAll">"Ler tudo"</string>
|
||||
<string name="action_disconnect">"Desligar"</string>
|
||||
<string name="title_activity_settings">"Configurações"</string>
|
||||
<string name="pref_header_general">"Geral"</string>
|
||||
<string name="pref_switch_actions_tap_title">"Toque em ação sobre os 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 seus dados novamente."</string>
|
||||
<string name="all_posts_not_read">"Todas as postagens não foram lidas"</string>
|
||||
<string name="all_posts_read">"Todas as postagens foram lidas"</string>
|
||||
<string name="cant_get_favs">"Não é possível obter favoritos"</string>
|
||||
<string name="cant_get_new_elements">"Não é possível obter novos artigos"</string>
|
||||
<string name="cant_get_read">"Não é possível ler artigos"</string>
|
||||
<string name="nothing_here">"Nada aqui"</string>
|
||||
<string name="tab_new">"Novo"</string>
|
||||
<string name="tab_read">"Tudo"</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">"Logar 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 a fonte."</string>
|
||||
<string name="cant_get_spouts">"Não é possível obter a lista de bicos."</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="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="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 handling"</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="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="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">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="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>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark articles as read when scrolling between articles.</string>
|
||||
<string name="issue_tracker_link">"Rastreador de problemas"</string>
|
||||
<string name="issue_tracker_summary">"Relatar um bug ou pedir um novo recurso"</string>
|
||||
<string name="warning_wrong_url">"AVISO"</string>
|
||||
<string name="pref_switch_card_view_title">"Vista de cartão"</string>
|
||||
<string name="cant_mark_favortie">"Não é possível marcar o artigo como favorito"</string>
|
||||
<string name="cant_unmark_favortie">"Não pode remover o item do favorito"</string>
|
||||
<string name="share">"Compartilhar"</string>
|
||||
<string name="rating_prompt_title">"Gosta da aplicação?"</string>
|
||||
<string name="rating_prompt_yes">"Sim!"</string>
|
||||
<string name="rating_prompt_no">"Não realmente…"</string>
|
||||
<string name="rating_prompt_feedback_title">"Pode nos dizer por que?"</string>
|
||||
<string name="rating_prompt_feedback_yes">"Okey!"</string>
|
||||
<string name="rating_prompt_feedback_no">"Agora não."</string>
|
||||
<string name="rating_prompt_rating_title">"Legal! Você pode classificar-na loja?"</string>
|
||||
<string name="rating_prompt_rating_yes">"Claro!"</string>
|
||||
<string name="rating_prompt_rating_no">"Agora não."</string>
|
||||
<string name="rating_prompt_thanks">"Obrigado, seu feedback ajudar a realçar o app!"</string>
|
||||
<string name="switch_unread_count">"Exibir a contagem não lida como um emblema para a barra inferior."</string>
|
||||
<string name="switch_unread_count_title">"Exibir a contagem não lida"</string>
|
||||
<string name="display_all_counts_title">"Exibir a contagem para o favorito e leitura"</string>
|
||||
<string name="menu_share_the_app">"Convidar amigos"</string>
|
||||
<string name="invitation_title">"Tente este aplicativo para seus Selfoss RSS feeds!"</string>
|
||||
<string name="invitation_message">"Eu uso este app para meus Selfoss RSS feeds. Você pode gostar também!"</string>
|
||||
<string name="invitation_cta">"Tente o aplicativo"</string>
|
||||
<string name="text_wrong_url">"Você parece estar tentando usar um URL inválido. 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 app"</string>
|
||||
<string name="pref_general_internal_browser_on">"Artigos serão aberto dentro do aplicativo"</string>
|
||||
<string name="pref_general_internal_browser_off">"Artigos serão aberto com o seu navegador padrão"</string>
|
||||
<string name="prefer_article_viewer_title">"Use o Visualizador de artigo"</string>
|
||||
<string name="prefer_article_viewer_on">"Vai usar o Visualizador de artigo em vez do navegador interno"</string>
|
||||
<string name="prefer_article_viewer_off">"Vai usar o navegador interno em vez do Visualizador de artigo"</string>
|
||||
<string name="pref_general_category_links">"Manipulação de ligações"</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 como cartões"</string>
|
||||
<string name="pref_switch_card_view_off">"Os artigos serão exibidos como 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">"Atualização remota"</string>
|
||||
<string name="refresh_success_response">"O remoto é atualizado, você agora pode recarregar a lista de artigos"</string>
|
||||
<string name="refresh_failer_message">"A atualização não funcionar, tente novamente mais tarde ou verifique seus logs de selfoss."</string>
|
||||
<string name="refresh_in_progress">"Atualização em curso"</string>
|
||||
<string name="new_apk_available_title">"Está disponível um novo APK."</string>
|
||||
<string name="new_apk_available_message">"Um APK novo está disponível para download no repositório oficial."</string>
|
||||
<string name="new_apk_available_get">"Fazer download agora"</string>
|
||||
<string name="new_apk_available_no">"Ignorar esta versão"</string>
|
||||
<string name="intro_hello_title">"Olá ai!"</string>
|
||||
<string name="intro_hello_message">"Obrigado por baixar o aplicativo!"</string>
|
||||
<string name="intro_needs_selfoss_title">"Antes de começar…"</string>
|
||||
<string name="intro_needs_selfoss_message">"Você não pode usar o app sem uma instância de Selfoss."</string>
|
||||
<string name="intro_needs_selfoss_link">"O que é Selfoss?"</string>
|
||||
<string name="intro_all_set_title">"Tudo configurado!"</string>
|
||||
<string name="intro_all_set_message">"Você está pronto para usar o app. não se esqueça de ir para a página de configurações para configurar o seu aplicativo, e onde você encontrará alguns links úteis."</string>
|
||||
<string name="card_height_title">Cartões de altura total</string>
|
||||
<string name="card_height_on">Altura de cartas irá ajustar ao seu conteúdo</string>
|
||||
<string name="card_height_off">Altura do cartão será corrigida</string>
|
||||
<string name="source_code">Código fonte</string>
|
||||
<string name="cant_mark_read">Não pode marcar o artigo como lido</string>
|
||||
<string name="drawer_error_loading_tags">Erro ao carregar etiquetas…</string>
|
||||
<string name="drawer_error_loading_sources">Erro ao carregar fontes…</string>
|
||||
<string name="drawer_item_filters">Filtros</string>
|
||||
<string name="drawer_action_clear">limpar</string>
|
||||
<string name="drawer_item_tags">Etiquetas</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 armazenar em cache dados sua gaveta</string>
|
||||
<string name="no_tags_loaded">Não tags carregado</string>
|
||||
<string name="no_sources_loaded">Não há fontes carregadas</string>
|
||||
<string name="drawer_loading">A carregar…</string>
|
||||
<string name="menu_home_search">Buscar</string>
|
||||
<string name="can_delete_source">Não é possível excluir a fonte…</string>
|
||||
<string name="base_url_error">Houve um problema ao tentar se comunicar com sua instância de Selfoss. Se o problema persistir, por favor entre em contato comigo.</string>
|
||||
<string name="pref_header_theme">Temas</string>
|
||||
<string name="default_theme">Predefinição</string>
|
||||
<string name="teal_orange_theme">Verde-azulado/laranja/Luz</string>
|
||||
<string name="cyan_pink_theme">Ciano/rosa/luz</string>
|
||||
<string name="grey_orange_theme">Cinza/laranja/luz</string>
|
||||
<string name="blue_amber_theme">Azul/âmbar/luz</string>
|
||||
<string name="indigo_pink_theme">Índigo/rosa/luz</string>
|
||||
<string name="red_teal_theme">Vermelha/verde-azulado/Luz</string>
|
||||
<string name="teal_orange_dark_theme">Verde-azulado/laranja/escuro</string>
|
||||
<string name="cyan_pink_dark_theme">Ciano/rosa/escura</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/escura</string>
|
||||
<string name="red_teal_dark_theme">Verde-azulado/vermelho/escuro</string>
|
||||
<string name="pref_header_debug">Depurar</string>
|
||||
<string name="login_debug_title">Ativar para registrar erros de logon</string>
|
||||
<string name="login_debug_on">Qualquer erro na página de login será registrado</string>
|
||||
<string name="login_debug_off">Não há registro na página de login</string>
|
||||
<string name="login_menu_debug">Depurar</string>
|
||||
<string name="self_hosted_cert_switch">Usando um certificado hospedado?</string>
|
||||
<string name="self_signed_cert_warning">Devido a razões de segurança, auto certificados auto-assinados não são suportados por padrão. Ao activar isto, eu não vou ser responsável de qualquer problema de segurança que você encontrar.</string>
|
||||
<string name="pref_selfoss_category">Api de Selfoss</string>
|
||||
<string name="pref_api_items_number_title">Número de itens carregados</string>
|
||||
<string name="read_debug_title">Leia artigos aparecem como não lidas?</string>
|
||||
<string name="read_debug_off">Sem log quando marcar um item como lido</string>
|
||||
<string name="read_debug_on">Chamadas de Api serão registradas quando marcar um artigo como lido</string>
|
||||
<string name="summary_debug_identifier">Depurar o identificador</string>
|
||||
<string name="unique_id_to_clipboard">Identificador de copiados para a área de transferência</string>
|
||||
<string name="display_header_drawer_summary">Exibir um cabeçalho com o url de instância de selfoss na gaveta lateral.</string>
|
||||
<string name="display_header_drawer_title">Cabeçalho de conta</string>
|
||||
<string name="login_everything_title">Logando todas as chamadas api</string>
|
||||
<string name="login_everything_on">Isto irá registrar todas as chamadas de api para fins de depuração.</string>
|
||||
<string name="login_everything_off">Nenhuma chamada de api será registrada</string>
|
||||
<string name="pref_general_infinite_loading_title">Carregar mais artigos no pergaminho</string>
|
||||
<string name="translation">Tradução</string>
|
||||
<string name="cant_open_invalid_url">A url do item é inválido. Eu estou olhando para resolver esta questão, para que o app não vai falhar.</string>
|
||||
<string name="drawer_report_bug">Reportar falha</string>
|
||||
<string name="items_number_should_be_number">O número de itens deve ser um número inteiro.</string>
|
||||
<string name="reader_action_more">Ler mais</string>
|
||||
<string name="reader_action_open">Abrir no browser</string>
|
||||
<string name="reader_action_share">Compartilhar</string>
|
||||
<string name="pref_switch_actions_pager_scroll_on">Artigos de marca como lida quando passar entre artigos.</string>
|
||||
<string name="add_to_favs_reader">Add to favorites</string>
|
||||
<string name="remove_to_favs_reader">Remove from favorites</string>
|
||||
<string name="pref_content_reader_font_size">Article reader content font size</string>
|
||||
<string name="pref_header_viewer">Article viewer</string>
|
||||
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
|
||||
<string name="markall_dialog_message">This will mark all the items as read.</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
|
||||
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
|
||||
</resources>
|
||||
|
@ -158,5 +158,13 @@
|
||||
<string name="reader_action_more">Read more</string>
|
||||
<string name="reader_action_open">Open in browser</string>
|
||||
<string name="reader_action_share">Share</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark articles as read when scrolling between articles.</string>
|
||||
<string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
|
||||
<string name="add_to_favs_reader">Add to favorites</string>
|
||||
<string name="remove_to_favs_reader">Remove from favorites</string>
|
||||
<string name="pref_content_reader_font_size">Article reader content font size</string>
|
||||
<string name="pref_header_viewer">Article viewer</string>
|
||||
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
|
||||
<string name="markall_dialog_message">This will mark all the items as read.</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
|
||||
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
|
||||
</resources>
|
||||
|
@ -158,5 +158,13 @@
|
||||
<string name="reader_action_more">Read more</string>
|
||||
<string name="reader_action_open">Open in browser</string>
|
||||
<string name="reader_action_share">Share</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark articles as read when scrolling between articles.</string>
|
||||
<string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
|
||||
<string name="add_to_favs_reader">Add to favorites</string>
|
||||
<string name="remove_to_favs_reader">Remove from favorites</string>
|
||||
<string name="pref_content_reader_font_size">Article reader content font size</string>
|
||||
<string name="pref_header_viewer">Article viewer</string>
|
||||
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
|
||||
<string name="markall_dialog_message">This will mark all the items as read.</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
|
||||
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
|
||||
</resources>
|
||||
|
@ -158,5 +158,13 @@
|
||||
<string name="reader_action_more">Read more</string>
|
||||
<string name="reader_action_open">Open in browser</string>
|
||||
<string name="reader_action_share">Share</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark articles as read when scrolling between articles.</string>
|
||||
<string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
|
||||
<string name="add_to_favs_reader">Add to favorites</string>
|
||||
<string name="remove_to_favs_reader">Remove from favorites</string>
|
||||
<string name="pref_content_reader_font_size">Article reader content font size</string>
|
||||
<string name="pref_header_viewer">Article viewer</string>
|
||||
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
|
||||
<string name="markall_dialog_message">This will mark all the items as read.</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
|
||||
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
|
||||
</resources>
|
||||
|
@ -158,5 +158,13 @@
|
||||
<string name="reader_action_more">Read more</string>
|
||||
<string name="reader_action_open">Open in browser</string>
|
||||
<string name="reader_action_share">Share</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark articles as read when scrolling between articles.</string>
|
||||
<string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
|
||||
<string name="add_to_favs_reader">Add to favorites</string>
|
||||
<string name="remove_to_favs_reader">Remove from favorites</string>
|
||||
<string name="pref_content_reader_font_size">Article reader content font size</string>
|
||||
<string name="pref_header_viewer">Article viewer</string>
|
||||
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
|
||||
<string name="markall_dialog_message">This will mark all the items as read.</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
|
||||
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
|
||||
</resources>
|
||||
|
@ -158,5 +158,13 @@
|
||||
<string name="reader_action_more">Daha fazlasını görüntüle</string>
|
||||
<string name="reader_action_open">Tarayıcıda aç</string>
|
||||
<string name="reader_action_share">Paylaş</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark articles as read when scrolling between articles.</string>
|
||||
<string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
|
||||
<string name="add_to_favs_reader">Add to favorites</string>
|
||||
<string name="remove_to_favs_reader">Remove from favorites</string>
|
||||
<string name="pref_content_reader_font_size">Article reader content font size</string>
|
||||
<string name="pref_header_viewer">Article viewer</string>
|
||||
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
|
||||
<string name="markall_dialog_message">This will mark all the items as read.</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
|
||||
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
|
||||
</resources>
|
||||
|
@ -158,5 +158,13 @@
|
||||
<string name="reader_action_more">Read more</string>
|
||||
<string name="reader_action_open">Open in browser</string>
|
||||
<string name="reader_action_share">Share</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark articles as read when scrolling between articles.</string>
|
||||
<string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
|
||||
<string name="add_to_favs_reader">Add to favorites</string>
|
||||
<string name="remove_to_favs_reader">Remove from favorites</string>
|
||||
<string name="pref_content_reader_font_size">Article reader content font size</string>
|
||||
<string name="pref_header_viewer">Article viewer</string>
|
||||
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
|
||||
<string name="markall_dialog_message">This will mark all the items as read.</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
|
||||
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
|
||||
</resources>
|
||||
|
@ -158,5 +158,13 @@
|
||||
<string name="reader_action_more">Read more</string>
|
||||
<string name="reader_action_open">Open in browser</string>
|
||||
<string name="reader_action_share">Share</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark articles as read when scrolling between articles.</string>
|
||||
<string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
|
||||
<string name="add_to_favs_reader">Add to favorites</string>
|
||||
<string name="remove_to_favs_reader">Remove from favorites</string>
|
||||
<string name="pref_content_reader_font_size">Article reader content font size</string>
|
||||
<string name="pref_header_viewer">Article viewer</string>
|
||||
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
|
||||
<string name="markall_dialog_message">This will mark all the items as read.</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
|
||||
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
|
||||
</resources>
|
||||
|
@ -158,5 +158,13 @@
|
||||
<string name="reader_action_more">阅读更多</string>
|
||||
<string name="reader_action_open">在浏览器中打开</string>
|
||||
<string name="reader_action_share">分享</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark articles as read when scrolling between articles.</string>
|
||||
<string name="pref_switch_actions_pager_scroll_on">切换文章时将文章标记为已读。</string>
|
||||
<string name="add_to_favs_reader">添加到收藏</string>
|
||||
<string name="remove_to_favs_reader">从收藏中移除</string>
|
||||
<string name="pref_content_reader_font_size">Article reader content font size</string>
|
||||
<string name="pref_header_viewer">Article viewer</string>
|
||||
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
|
||||
<string name="markall_dialog_message">This will mark all the items as read.</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
|
||||
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
|
||||
</resources>
|
||||
|
@ -158,5 +158,13 @@
|
||||
<string name="reader_action_more">阅读更多</string>
|
||||
<string name="reader_action_open">在浏览器中打开</string>
|
||||
<string name="reader_action_share">分享</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark articles as read when scrolling between articles.</string>
|
||||
<string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
|
||||
<string name="add_to_favs_reader">Add to favorites</string>
|
||||
<string name="remove_to_favs_reader">Remove from favorites</string>
|
||||
<string name="pref_content_reader_font_size">Article reader content font size</string>
|
||||
<string name="pref_header_viewer">Article viewer</string>
|
||||
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
|
||||
<string name="markall_dialog_message">This will mark all the items as read.</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
|
||||
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
|
||||
</resources>
|
||||
|
@ -11,4 +11,13 @@
|
||||
<color name="refresh_progress_2">@color/colorAccent</color>
|
||||
<color name="refresh_progress_3">@color/pink</color>
|
||||
<color name="background_grey">#FFe4e4e4</color>
|
||||
|
||||
<color name="dark_webview">#FF303030</color>
|
||||
<color name="dark_webview_text">@color/md_white_1000</color>
|
||||
<color name="light_webview">@color/md_grey_50</color>
|
||||
<color name="light_webview_text">@color/md_grey_900</color>
|
||||
|
||||
<color name="cardBackgroundColor">#FFFFFFFF</color>
|
||||
<color name="materialDrawerHeaderSelectionText">@color/md_grey_900</color>
|
||||
<color name="darkBackground">#FF303030</color>
|
||||
</resources>
|
||||
|
@ -161,5 +161,13 @@
|
||||
<string name="reader_action_more">Read more</string>
|
||||
<string name="reader_action_open">Open in browser</string>
|
||||
<string name="reader_action_share">Share</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark articles as read when scrolling between articles.</string>
|
||||
</resources>
|
||||
<string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
|
||||
<string name="add_to_favs_reader">Add to favorites</string>
|
||||
<string name="remove_to_favs_reader">Remove from favorites</string>
|
||||
<string name="pref_content_reader_font_size">Article reader content font size</string>
|
||||
<string name="pref_header_viewer">Article viewer</string>
|
||||
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
|
||||
<string name="markall_dialog_message">This will mark all the items as read.</string>
|
||||
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
|
||||
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
|
||||
</resources>
|
||||
|