Compare commits
124 Commits
Author | SHA1 | Date | |
---|---|---|---|
bc96b314c2 | |||
8dcf749b4e | |||
6a56ec6442 | |||
30e46d7eae | |||
9458b1834b | |||
297f797b97 | |||
c70e80758c | |||
3bf1d7c4f9 | |||
173247041a | |||
3a28772096 | |||
bd08b8aba3 | |||
2ceb0f988b | |||
4ef3b155b8 | |||
350e24cded | |||
1bf8a578bc | |||
4818a101cc | |||
baebf938ef | |||
fea57c7b1e | |||
113dfa68be | |||
60c6514fa1 | |||
114485afc3 | |||
d6a51381b9 | |||
620f13fd7c | |||
6577b2c3d7 | |||
caef522c8b | |||
40ea07de2e | |||
7905e4aa12 | |||
64f4fd708a | |||
b46e4a018f | |||
3e999a9be2 | |||
f656d621e6 | |||
951cc1e6bd | |||
d8d4264f1b | |||
014eeec2b9 | |||
83837bddc3 | |||
f97666db92 | |||
ee08ea41a1 | |||
4ca64610cb | |||
4980145e46 | |||
10cbc19a0c | |||
15fba2b29b | |||
096952f88c | |||
0ea70c1922 | |||
69ac2e2b44 | |||
68098f4d84 | |||
080d52893e | |||
b02334a8d4 | |||
27118add22 | |||
2a6f98a1e8 | |||
1f67f2fdee | |||
ebf4d294a8 | |||
4a4dbacc95 | |||
687839b5f8 | |||
8fb339034f | |||
8e9fd9c985 | |||
72400f71c0 | |||
1151587951 | |||
abcd500045 | |||
beda24e736 | |||
37b2c5c2df | |||
7b5246ebf1 | |||
d6d5e72f48 | |||
fa8e88d489 | |||
1ef2da9f76 | |||
1ebd894be7 | |||
a9c493d105 | |||
f833d73fab | |||
9e6602f114 | |||
3bdfef9f8b | |||
6f7f475a6b | |||
8fc5fab67b | |||
6927e92396 | |||
c7470396d7 | |||
f21570e2e4 | |||
51f406e20c | |||
9e3fde744e | |||
ccf406ae68 | |||
bc78d1e079 | |||
d151eb261e | |||
0856598cd9 | |||
f0563efc62 | |||
84dfa9a8a5 | |||
8e25489cca | |||
198f95e1ca | |||
7e02fe89ea | |||
819356412c | |||
deb789bc1b | |||
133ba74548 | |||
1461e32643 | |||
f400c3d9ac | |||
7e595a4f74 | |||
18c9c499b2 | |||
24ae115ed4 | |||
7f345558cd | |||
57177cc910 | |||
cea258bc21 | |||
ed9b1c8ba7 | |||
5a79fd89e9 | |||
42a130db08 | |||
320a8d19de | |||
5721506007 | |||
803e8cb2f4 | |||
98492fd0c0 | |||
0b07178577 | |||
07e545079c | |||
95d64dc5e8 | |||
abe546dcda | |||
e6f367acaf | |||
a9b61853b9 | |||
5afc04a630 | |||
1da4cc2782 | |||
c5ebc89e4f | |||
dfc1719cce | |||
0812259470 | |||
e1476c5840 | |||
e30ea28e3f | |||
4a6d3aab7f | |||
8157146498 | |||
94d23888b1 | |||
737fe9bb4a | |||
0051ed2e73 | |||
e0595957e2 | |||
8d09ff7fdb | |||
04feb66b07 |
25
.github/CONTRIBUTING.md
vendored
@ -10,7 +10,7 @@ Please read the guidelines before contributing, and follow them (or try to) when
|
|||||||
|
|
||||||
There are many ways to contribute to this project, you could report bugs, request missing features, suggest enhancements and changes to existing ones. You also can improve the README with useful tips that could help the other users.
|
There are many ways to contribute to this project, you could report bugs, request missing features, suggest enhancements and changes to existing ones. You also can improve the README with useful tips that could help the other users.
|
||||||
|
|
||||||
You can fork the repository, and [help me solve some issues](https://github.com/aminecmi/ReaderforSelfoss/labels/help%20wanted) or [develop new things](https://github.com/aminecmi/ReaderforSelfoss/issues)
|
You can fork the repository, and [help me solve some issues](https://github.com/aminecmi/ReaderforSelfoss/issues?q=is%3Aissue+is%3Aopen+label%3A%22Up+For+Grabs%22) or [develop new things](https://github.com/aminecmi/ReaderforSelfoss/issues)
|
||||||
|
|
||||||
### What I can't help you with.
|
### What I can't help you with.
|
||||||
|
|
||||||
@ -31,7 +31,7 @@ Always check if the web version of your instance is working.
|
|||||||
* Please ask before starting to work on an issue. I may be working on it, or someone else could be doing so.
|
* 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.
|
* 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.
|
* Your code must be simple and clear enough to avoid using comments to explain what it does.
|
||||||
* Follow the used coding style [the official one](https://kotlinlang.org/docs/reference/coding-conventions.html) ([some idoms for reference](http://kotlinlang.org/docs/reference/idioms.html)) with more to come.
|
* Follow the used coding style [the android koding style](https://android.github.io/kotlin-guides/style.html) ([some idoms for reference](http://kotlinlang.org/docs/reference/idioms.html)) with more to come.
|
||||||
* Try as much as possible to write a test for your feature, and if you do so, run it, and make it work.
|
* Try as much as possible to write a test for your feature, and if you do so, run it, and make it work.
|
||||||
* Always check your changes and discard the ones that are irrelevant to your feature or bugfix.
|
* Always check your changes and discard the ones that are irrelevant to your feature or bugfix.
|
||||||
* Have meaningful commit messages.
|
* Have meaningful commit messages.
|
||||||
@ -48,28 +48,31 @@ You'll have to:
|
|||||||
|
|
||||||
- Configure fabric and add your `apiKey` and `apiSecret` in the `fabric.properties` file.
|
- Configure fabric and add your `apiKey` and `apiSecret` in the `fabric.properties` file.
|
||||||
- Create a firebase project and add the `google-services.json` to the `app/` folder.
|
- Create a firebase project and add the `google-services.json` to the `app/` folder.
|
||||||
- Define the following some parameters either in `~/.gradle/gradle.properties` or as gradle parameters (see the examples)
|
- Define some parameters either in `~/.gradle/gradle.properties` or as gradle parameters (see the examples)
|
||||||
|
|
||||||
- mercuryApiKey: A [Mercury](https://mercury.postlight.com/web-parser/) web parser api key for the internal browser
|
- mercuryApiKey: A [Mercury](https://mercury.postlight.com/web-parser/) web parser api key for the internal browser
|
||||||
- feedbackEmail: An email to receive users feedback.
|
- feedbackEmail: An email to receive users feedback.
|
||||||
- sourceUrl: an url to the source code, used in the settings
|
- sourceUrl: an url to the source code, used in the settings. **It can be empty.**
|
||||||
- trackerUrl: an url to the tracker, used in the settings
|
- trackerUrl: an url to the tracker, used in the settings. **It can be empty.**
|
||||||
|
- githubToken: a github token used to report issues from within the app. [Details here](https://github.com/heinrichreimer/android-issue-reporter#how-to-create-a-bot-key). **It can be empty.**
|
||||||
|
- appLoginUrl, appLoginUsername and appLoginPassword: url, username and password of a selfoss instance. **These are only used for tests. They can be empty if you don't test API calls.**
|
||||||
|
|
||||||
### Examples:
|
### Examples:
|
||||||
#### Inside ~/.gradle/gradle.properties
|
#### Inside ~/.gradle/gradle.properties
|
||||||
|
|
||||||
```
|
```
|
||||||
appLoginUrl="URL"
|
appLoginUrl="URL" # It can be empty.
|
||||||
appLoginUsername="LOGIN"
|
appLoginUsername="LOGIN" # It can be empty.
|
||||||
appLoginPassword="PASS"
|
appLoginPassword="PASS" # It can be empty.
|
||||||
mercuryApiKey="LONGAPIKEY"
|
mercuryApiKey="LONGAPIKEY"
|
||||||
feedbackEmail="EMAIL"
|
feedbackEmail="EMAIL"
|
||||||
sourceUrl="URLSOURCE"
|
sourceUrl="URLSOURCE" # It can be empty.
|
||||||
trackerUrl="URLTRACKER"
|
trackerUrl="URLTRACKER" # It can be empty.
|
||||||
|
githubToken="GITHUBTOKEN" # It can be empty or use https://github.com/heinrichreimer/android-issue-reporter#how-to-create-a-bot-key to generate one
|
||||||
```
|
```
|
||||||
|
|
||||||
#### As gradle parameters
|
#### As gradle parameters
|
||||||
|
|
||||||
```
|
```
|
||||||
./gradlew .... -P appLoginUrl="URL" -P appLoginUsername="LOGIN" -P appLoginPassword="PASS" -P mercuryApiKey="LONGAPIKEY" -P feedbackEmail="EMAIL" -P sourceUrl="URLSOURCE" -P trackerUrl="URLTRACKER"
|
./gradlew .... -P appLoginUrl="URL" -P appLoginUsername="LOGIN" -P appLoginPassword="PASS" -P mercuryApiKey="LONGAPIKEY" -P feedbackEmail="EMAIL" -P sourceUrl="URLSOURCE" -P trackerUrl="URLTRACKER" -P githubToken="GITHUBTOKEN"
|
||||||
```
|
```
|
||||||
|
4
.gitignore
vendored
@ -214,4 +214,6 @@ gradle-app.setting
|
|||||||
|
|
||||||
# End of https://www.gitignore.io/api/java,gradle,android,androidstudio
|
# End of https://www.gitignore.io/api/java,gradle,android,androidstudio
|
||||||
|
|
||||||
release/
|
release/
|
||||||
|
|
||||||
|
crowdin.properties
|
177
CHANGELOG.md
@ -1,6 +1,181 @@
|
|||||||
|
**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.
|
||||||
|
|
||||||
|
**1.5.4.22**
|
||||||
|
|
||||||
|
- You can now scroll through the loaded articles !
|
||||||
|
|
||||||
|
**1.5.4.21**
|
||||||
|
|
||||||
|
- Spanish translation and some Indonesian !
|
||||||
|
|
||||||
|
**1.5.4.20**
|
||||||
|
|
||||||
|
- Turkish translation !
|
||||||
|
|
||||||
|
**1.5.4.19**
|
||||||
|
|
||||||
|
- Fixed an issue with crowdin configuration (and its translations)
|
||||||
|
|
||||||
|
**1.5.4.18**
|
||||||
|
|
||||||
|
- Typo fix.
|
||||||
|
|
||||||
|
- The real last infinite scroll bug fix.
|
||||||
|
|
||||||
|
- Simplified Chinese translation !
|
||||||
|
|
||||||
|
**1.5.4.17**
|
||||||
|
|
||||||
|
- Fixed the last bug with infinite scroll.
|
||||||
|
|
||||||
|
**1.5.4.16**
|
||||||
|
|
||||||
|
- Fixing list view displaying issues.
|
||||||
|
|
||||||
|
- Endless scroll is not in beta anymore.
|
||||||
|
|
||||||
|
**1.5.4.15**
|
||||||
|
|
||||||
|
- Fixed an issue with the sources list.
|
||||||
|
|
||||||
|
**1.5.4.14**
|
||||||
|
|
||||||
|
- Fixing infinite scroll trying to load more items when there are no more.
|
||||||
|
|
||||||
|
**1.5.4.13**
|
||||||
|
|
||||||
|
- Displaying the right number of items.
|
||||||
|
|
||||||
|
- Fixing infinite scroll remaining issues. Should be stable enough.
|
||||||
|
|
||||||
|
**1.5.4.12**
|
||||||
|
|
||||||
|
- Fixed fab and toolbar issue (#113)
|
||||||
|
|
||||||
|
- Fixed links clickable (#114)
|
||||||
|
|
||||||
|
- Changed the link colors in the article viewer
|
||||||
|
|
||||||
|
**1.5.4.11**
|
||||||
|
|
||||||
|
- Hiding FABs on scroll.
|
||||||
|
|
||||||
|
- Closing #109 (code cleaning)
|
||||||
|
|
||||||
|
- Hiding fabs on scroll (#101)
|
||||||
|
|
||||||
|
**1.5.4.10**
|
||||||
|
|
||||||
|
- Displaying a loader when "reading more" in the article viewer.
|
||||||
|
|
||||||
|
- Displaying the thumbnail instead of icon on the article viewer.
|
||||||
|
|
||||||
|
- Scrolling to top when loading content with the "read more" button.
|
||||||
|
|
||||||
|
**1.5.4.09**
|
||||||
|
|
||||||
|
- Using the kotlin wrapper for the material drawer (see #98 for more details).
|
||||||
|
|
||||||
|
- Updated support libraries
|
||||||
|
|
||||||
|
- Changed the Floating Action Button to the support library version.
|
||||||
|
|
||||||
|
- New reader activity action bar #103.
|
||||||
|
|
||||||
|
**1.5.4.08**
|
||||||
|
|
||||||
|
- Thanks @jrafaelsantana for translating the whole app in Brazilian Portuguese.
|
||||||
|
|
||||||
|
**1.5.4.07**
|
||||||
|
|
||||||
|
- Loading more items on swipe too.
|
||||||
|
|
||||||
|
- Fixed popup menu style. User may need to reselect the theme.
|
||||||
|
|
||||||
|
- Disabled reporting marking items as read if there isn't an issue.
|
||||||
|
|
||||||
|
**1.5.4.05/06**
|
||||||
|
|
||||||
|
- Translation fix.
|
||||||
|
|
||||||
|
**1.5.4.04**
|
||||||
|
|
||||||
|
- Fixing an issue with marking items as read (something related to an old version of selfoss).
|
||||||
|
|
||||||
|
**1.5.4.03**
|
||||||
|
|
||||||
|
- Trying to fix some issue with pre-launch reports. Reverted because it seems to be related to the dev console side.
|
||||||
|
|
||||||
|
**1.5.4.02**
|
||||||
|
|
||||||
|
- Fixing full height cards issue.
|
||||||
|
|
||||||
|
**1.5.4.01**
|
||||||
|
|
||||||
|
- Removed the "apk downloaded from outside of playstore" message.
|
||||||
|
|
||||||
|
- Versions update.
|
||||||
|
|
||||||
|
- HTML viewer version update. It should fix an issue with images.
|
||||||
|
|
||||||
|
- Some code cleaning.
|
||||||
|
|
||||||
|
**1.5.4.00**
|
||||||
|
|
||||||
|
- Added issue reporting from within the app.
|
||||||
|
|
||||||
|
**1.5.3.06**
|
||||||
|
|
||||||
|
- Fixed infinite scroll not working.
|
||||||
|
|
||||||
|
- Fixed logs not working.
|
||||||
|
|
||||||
|
- Temporary workaround handling opening invalid urls. Waiting to solve #83.
|
||||||
|
|
||||||
|
**1.5.3.05**
|
||||||
|
|
||||||
|
- Fixed an issue on older versions of Android.
|
||||||
|
|
||||||
|
- Libs update.
|
||||||
|
|
||||||
|
**1.5.3.04**
|
||||||
|
|
||||||
|
- Crowdin translations
|
||||||
|
|
||||||
|
**1.5.3.03**
|
||||||
|
|
||||||
|
- Libs updates.
|
||||||
|
|
||||||
|
- Translation fix.
|
||||||
|
|
||||||
|
**1.5.3.01/02**
|
||||||
|
|
||||||
|
- Added translation link to the settings page.
|
||||||
|
|
||||||
|
- Added the translation link to the README.
|
||||||
|
|
||||||
|
**1.5.3.00**
|
||||||
|
|
||||||
|
- (BETA) Added pull from bottom to load more pages of results. May be buggy.
|
||||||
|
|
||||||
**1.5.2.18/19**
|
**1.5.2.18/19**
|
||||||
|
|
||||||
- APK minification finally working. That means less space taken !
|
- APK minification finally working. That means less space taken !
|
||||||
|
- Added an option to log every API call.
|
||||||
|
|
||||||
**1.5.2.17**
|
**1.5.2.17**
|
||||||
|
|
||||||
@ -278,4 +453,4 @@ _Updates_
|
|||||||
|
|
||||||
**1.3.3.4**
|
**1.3.3.4**
|
||||||
|
|
||||||
...
|
...
|
||||||
|
10
README.md
@ -1,17 +1,17 @@
|
|||||||
# ReaderForSelfoss
|
# ReaderForSelfoss
|
||||||
|
|
||||||
|
[](https://crowdin.com/project/readerforselfoss) [](https://gitter.im/amine-bou/ReaderForSelfoss)
|
||||||
|
|
||||||
[](http://jenkins.amine-bou.fr/job/ReaderForSelfoss/)
|
[](http://jenkins.amine-bou.fr/job/ReaderForSelfoss/)
|
||||||
|
|
||||||
[](https://gitter.im/amine-bou/ReaderForSelfoss)
|
|
||||||
|
|
||||||
[](https://codebeat.co/projects/github-com-aminecmi-readerforselfoss-master)
|
|
||||||
|
|
||||||
[](https://www.codetriage.com/aminecmi/readerforselfoss)
|
[](https://www.codetriage.com/aminecmi/readerforselfoss)
|
||||||
|
|
||||||
This is the repo of [Reader For Selfoss](https://play.google.com/store/apps/details?id=apps.amine.bou.readerforselfoss&hl=en).
|
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/)
|
It's an RSS Reader for Android, that **only** works with [Selfoss](https://selfoss.aditu.de/)
|
||||||
|
|
||||||
|
The last APK built from source is available [here](https://jenkins.amine-bou.fr/job/ReaderForSelfoss/lastSuccessfulBuild/artifact/SignApksBuilder-out/selfoss-key/selfoss/app-githubConfig-release-unsigned.apk/app-githubConfig-release.apk).
|
||||||
|
|
||||||
|
|
||||||
## Want to help ?
|
## Want to help ?
|
||||||
|
|
||||||
@ -22,3 +22,5 @@ Check the [Contribution guide](https://github.com/aminecmi/ReaderforSelfoss/blob
|
|||||||
- [Check what changed](https://github.com/aminecmi/ReaderforSelfoss/blob/master/CHANGELOG.md)
|
- [Check what changed](https://github.com/aminecmi/ReaderforSelfoss/blob/master/CHANGELOG.md)
|
||||||
- [See what I'm doing](https://github.com/aminecmi/ReaderforSelfoss/projects/1)
|
- [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)
|
- [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)
|
||||||
|
@ -8,38 +8,52 @@ buildscript {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ext {
|
||||||
|
configuration = [
|
||||||
|
buildDate: new Date()
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
def gitVersion() {
|
def gitVersion() {
|
||||||
def process = "git describe --abbrev=0 --tags".execute()
|
def process = "git describe --abbrev=0 --tags".execute()
|
||||||
return process.text.substring(1).replaceAll("\\.", "")
|
return process.text.substring(1).replaceAll("\\.", "").trim()
|
||||||
}
|
}
|
||||||
|
|
||||||
def versionCodeFromGit() {
|
def versionCodeFromGit() {
|
||||||
println "version code " + gitVersion().toInteger()
|
def versionCode = gitVersion() + (ext.configuration.buildDate.format("yyMd")).toInteger()
|
||||||
return gitVersion().toInteger()
|
println "version code " + versionCode
|
||||||
|
return versionCode.toInteger()
|
||||||
}
|
}
|
||||||
|
|
||||||
def versionNameFromGit() {
|
def versionNameFromGit() {
|
||||||
println "version code " + gitVersion().trim()
|
def versionName = gitVersion() + ext.configuration.buildDate.format('yyyyMMddHHmm')
|
||||||
return gitVersion().trim()
|
println "version name " + versionName
|
||||||
|
return versionName
|
||||||
}
|
}
|
||||||
|
|
||||||
|
apply plugin: 'org.sonarqube'
|
||||||
|
|
||||||
apply plugin: 'com.android.application'
|
apply plugin: 'com.android.application'
|
||||||
|
|
||||||
apply plugin: 'io.fabric'
|
apply plugin: 'io.fabric'
|
||||||
|
|
||||||
apply plugin: 'kotlin-android'
|
apply plugin: 'kotlin-android'
|
||||||
|
|
||||||
|
apply plugin: 'kotlin-android-extensions'
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
maven { url 'https://maven.fabric.io/public' }
|
maven {
|
||||||
|
url 'https://maven.fabric.io/public'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 26
|
compileSdkVersion 27
|
||||||
buildToolsVersion "26.0.1"
|
buildToolsVersion '27.0.0'
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "apps.amine.bou.readerforselfoss"
|
applicationId "apps.amine.bou.readerforselfoss"
|
||||||
minSdkVersion 16
|
minSdkVersion 16
|
||||||
targetSdkVersion 26
|
targetSdkVersion 27
|
||||||
versionCode versionCodeFromGit()
|
versionCode versionCodeFromGit()
|
||||||
versionName versionNameFromGit()
|
versionName versionNameFromGit()
|
||||||
|
|
||||||
@ -58,6 +72,8 @@ android {
|
|||||||
buildConfigField "String", "FEEDBACK_EMAIL", feedbackEmail
|
buildConfigField "String", "FEEDBACK_EMAIL", feedbackEmail
|
||||||
buildConfigField "String", "SOURCE_URL", sourceUrl
|
buildConfigField "String", "SOURCE_URL", sourceUrl
|
||||||
buildConfigField "String", "TRACKER_URL", trackerUrl
|
buildConfigField "String", "TRACKER_URL", trackerUrl
|
||||||
|
buildConfigField "String", "TRANSLATION_URL", translationUrl
|
||||||
|
buildConfigField "String", "GITHUB_TOKEN", githubToken
|
||||||
}
|
}
|
||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
release {
|
||||||
@ -89,33 +105,33 @@ android {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
// Testing
|
// Testing
|
||||||
androidTestCompile 'com.android.support.test.espresso:espresso-core:3.0.0'
|
androidTestCompile 'com.android.support.test.espresso:espresso-core:3.0.1'
|
||||||
androidTestCompile 'com.android.support.test:runner:1.0.0'
|
androidTestCompile 'com.android.support.test:runner:1.0.1'
|
||||||
// Espresso-contrib for DatePicker, RecyclerView, Drawer actions, Accessibility checks, CountingIdlingResource
|
// Espresso-contrib for DatePicker, RecyclerView, Drawer actions, Accessibility checks, CountingIdlingResource
|
||||||
androidTestCompile 'com.android.support.test.espresso:espresso-contrib:3.0.0'
|
androidTestCompile 'com.android.support.test.espresso:espresso-contrib:3.0.1'
|
||||||
// Espresso-intents for validation and stubbing of Intents
|
// Espresso-intents for validation and stubbing of Intents
|
||||||
androidTestCompile 'com.android.support.test.espresso:espresso-intents:3.0.0'
|
androidTestCompile 'com.android.support.test.espresso:espresso-intents:3.0.1'
|
||||||
|
|
||||||
|
|
||||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
|
compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
|
||||||
|
|
||||||
// Android Support
|
// Android Support
|
||||||
compile 'com.android.support:appcompat-v7:26.0.1'
|
compile 'com.android.support:appcompat-v7:27.0.0'
|
||||||
compile 'com.android.support:design:26.0.1'
|
compile 'com.android.support:design:27.0.0'
|
||||||
compile 'com.android.support:recyclerview-v7:26.0.1'
|
compile 'com.android.support:recyclerview-v7:27.0.0'
|
||||||
compile 'com.android.support:support-v4:26.0.1'
|
compile 'com.android.support:support-v4:27.0.0'
|
||||||
compile 'com.android.support:support-vector-drawable:26.0.1'
|
compile 'com.android.support:support-vector-drawable:27.0.0'
|
||||||
compile 'com.android.support:customtabs:26.0.1'
|
compile 'com.android.support:customtabs:27.0.0'
|
||||||
compile 'com.android.support:cardview-v7:26.0.1'
|
compile 'com.android.support:cardview-v7:27.0.0'
|
||||||
compile 'com.android.support.constraint:constraint-layout:1.0.2'
|
compile 'com.android.support.constraint:constraint-layout:1.0.2'
|
||||||
|
|
||||||
// Firebase + crashlytics
|
// Firebase + crashlytics
|
||||||
compile 'com.google.firebase:firebase-core:11.2.0'
|
compile 'com.google.firebase:firebase-core:11.4.2'
|
||||||
compile 'com.google.firebase:firebase-config:11.2.0'
|
compile 'com.google.firebase:firebase-config:11.4.2'
|
||||||
compile 'com.google.firebase:firebase-invites:11.2.0'
|
compile 'com.google.firebase:firebase-invites:11.4.2'
|
||||||
compile('com.crashlytics.sdk.android:crashlytics:2.6.8@aar') {
|
compile('com.crashlytics.sdk.android:crashlytics:2.8.0@aar') {
|
||||||
transitive = true
|
transitive = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//multidex
|
//multidex
|
||||||
@ -125,44 +141,46 @@ dependencies {
|
|||||||
compile 'agency.tango.android:material-intro-screen:0.0.5'
|
compile 'agency.tango.android:material-intro-screen:0.0.5'
|
||||||
|
|
||||||
// About
|
// About
|
||||||
compile('com.mikepenz:aboutlibraries:5.9.7@aar') {
|
compile('com.mikepenz:aboutlibraries:6.0.0@aar') {
|
||||||
transitive = true
|
transitive = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrofit + http logging + okhttp
|
// Retrofit + http logging + okhttp
|
||||||
compile 'com.squareup.retrofit2:retrofit:2.3.0'
|
compile 'com.squareup.retrofit2:retrofit:2.3.0'
|
||||||
compile 'com.squareup.okhttp3:logging-interceptor:3.8.0'
|
compile 'com.squareup.okhttp3:logging-interceptor:3.9.0'
|
||||||
compile 'com.squareup.retrofit2:converter-gson:2.3.0'
|
compile 'com.squareup.retrofit2:converter-gson:2.3.0'
|
||||||
compile 'com.burgstaller:okhttp-digest:1.12'
|
compile 'com.burgstaller:okhttp-digest:1.12'
|
||||||
|
|
||||||
// Material-ish things
|
// Material-ish things
|
||||||
compile 'com.ashokvarma.android:bottom-navigation-bar:2.0.2'
|
compile 'com.ashokvarma.android:bottom-navigation-bar:2.0.3'
|
||||||
compile 'com.melnykov:floatingactionbutton:1.3.0'
|
|
||||||
compile 'com.github.jd-alexander:LikeButton:0.2.1'
|
compile 'com.github.jd-alexander:LikeButton:0.2.1'
|
||||||
compile 'com.amulyakhare:com.amulyakhare.textdrawable:1.0.1'
|
compile 'com.amulyakhare:com.amulyakhare.textdrawable:1.0.1'
|
||||||
compile 'org.sufficientlysecure:html-textview:3.3'
|
compile 'org.sufficientlysecure:html-textview:3.5'
|
||||||
|
|
||||||
// glide
|
// glide
|
||||||
compile('com.github.bumptech.glide:glide:4.1.0@aar') {
|
compile 'com.github.bumptech.glide:glide:4.1.1'
|
||||||
transitive = true;
|
compile 'com.github.bumptech.glide:okhttp3-integration:4.1.1'
|
||||||
}
|
|
||||||
compile('com.github.bumptech.glide:okhttp3-integration:4.1.0@aar')
|
|
||||||
|
|
||||||
// Asking politely users to rate the app
|
// Asking politely users to rate the app
|
||||||
compile 'com.github.stkent:amplify:2.1.0'
|
compile 'com.github.stkent:amplify:2.1.0'
|
||||||
|
|
||||||
// For the article reader
|
// For the article reader
|
||||||
compile 'com.klinkerapps:drag-dismiss-activity:1.4.3'
|
compile 'com.klinkerapps:drag-dismiss-activity:1.5.0'
|
||||||
|
|
||||||
// Drawer
|
// Drawer
|
||||||
compile('com.mikepenz:materialdrawer:5.9.5@aar') {
|
implementation 'co.zsmb:materialdrawer-kt:1.2.1'
|
||||||
transitive = true
|
|
||||||
}
|
|
||||||
compile 'com.anupcowkur:reservoir:3.1.0'
|
compile 'com.anupcowkur:reservoir:3.1.0'
|
||||||
|
|
||||||
// Themes
|
// Themes
|
||||||
compile 'com.52inc:scoops:1.0.0'
|
compile 'com.52inc:scoops:1.0.0'
|
||||||
|
|
||||||
|
// Github issues reporter
|
||||||
|
compile 'com.heinrichreimersoftware:android-issue-reporter:1.3.1'
|
||||||
|
|
||||||
|
compile 'com.github.rubensousa:floatingtoolbar:1.5.1'
|
||||||
|
|
||||||
|
// Pager
|
||||||
|
compile 'me.relex:circleindicator:1.2.2@aar'
|
||||||
}
|
}
|
||||||
|
|
||||||
apply plugin: 'com.google.gms.google-services'
|
apply plugin: 'com.google.gms.google-services'
|
||||||
@ -206,6 +224,8 @@ def initAppForSecretPropertiesIfNeeded() {
|
|||||||
entry(key: "feedbackEmail", value: System.getProperty("feedbackEmail"))
|
entry(key: "feedbackEmail", value: System.getProperty("feedbackEmail"))
|
||||||
entry(key: "sourceUrl", value: System.getProperty("sourceUrl"))
|
entry(key: "sourceUrl", value: System.getProperty("sourceUrl"))
|
||||||
entry(key: "trackerUrl", value: System.getProperty("trackerUrl"))
|
entry(key: "trackerUrl", value: System.getProperty("trackerUrl"))
|
||||||
|
entry(key: "translationUrl", value: System.getProperty("translationUrl"))
|
||||||
|
entry(key: "githubToken", value: System.getProperty("githubToken"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
5
app/proguard-rules.pro
vendored
@ -61,6 +61,11 @@
|
|||||||
|
|
||||||
# self signed glidemodule
|
# self signed glidemodule
|
||||||
-keep public class * implements com.bumptech.glide.module.GlideModule
|
-keep public class * implements com.bumptech.glide.module.GlideModule
|
||||||
|
-keep public class * extends com.bumptech.glide.AppGlideModule
|
||||||
|
-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
|
||||||
|
**[] $VALUES;
|
||||||
|
public *;
|
||||||
|
}
|
||||||
|
|
||||||
-dontwarn com.anupcowkur.reservoir.**
|
-dontwarn com.anupcowkur.reservoir.**
|
||||||
|
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
package apps.amine.bou.readerforselfoss
|
package apps.amine.bou.readerforselfoss
|
||||||
|
|
||||||
|
|
||||||
// TODO: test source adding
|
// TODO: test source adding
|
@ -5,29 +5,33 @@ import android.content.Intent
|
|||||||
import android.support.test.InstrumentationRegistry
|
import android.support.test.InstrumentationRegistry
|
||||||
import android.support.test.espresso.Espresso.onView
|
import android.support.test.espresso.Espresso.onView
|
||||||
import android.support.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu
|
import android.support.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu
|
||||||
import android.support.test.espresso.action.ViewActions.*
|
import android.support.test.espresso.action.ViewActions.click
|
||||||
|
import android.support.test.espresso.action.ViewActions.closeSoftKeyboard
|
||||||
|
import android.support.test.espresso.action.ViewActions.pressBack
|
||||||
|
import android.support.test.espresso.action.ViewActions.pressKey
|
||||||
|
import android.support.test.espresso.action.ViewActions.typeText
|
||||||
import android.support.test.espresso.assertion.ViewAssertions.matches
|
import android.support.test.espresso.assertion.ViewAssertions.matches
|
||||||
import android.support.test.espresso.contrib.DrawerActions
|
import android.support.test.espresso.contrib.DrawerActions
|
||||||
import android.support.test.espresso.intent.Intents
|
import android.support.test.espresso.intent.Intents
|
||||||
import android.support.test.espresso.intent.Intents.intended
|
import android.support.test.espresso.intent.Intents.intended
|
||||||
import android.support.test.espresso.intent.Intents.times
|
import android.support.test.espresso.intent.Intents.times
|
||||||
import android.support.test.espresso.intent.matcher.IntentMatchers.hasComponent
|
import android.support.test.espresso.intent.matcher.IntentMatchers.hasComponent
|
||||||
import android.support.test.espresso.matcher.ViewMatchers.*
|
import android.support.test.espresso.matcher.ViewMatchers.isDisplayed
|
||||||
|
import android.support.test.espresso.matcher.ViewMatchers.isRoot
|
||||||
|
import android.support.test.espresso.matcher.ViewMatchers.withContentDescription
|
||||||
|
import android.support.test.espresso.matcher.ViewMatchers.withId
|
||||||
|
import android.support.test.espresso.matcher.ViewMatchers.withText
|
||||||
import android.support.test.rule.ActivityTestRule
|
import android.support.test.rule.ActivityTestRule
|
||||||
import android.support.test.runner.AndroidJUnit4
|
import android.support.test.runner.AndroidJUnit4
|
||||||
import android.view.KeyEvent
|
import android.view.KeyEvent
|
||||||
|
import apps.amine.bou.readerforselfoss.utils.Config
|
||||||
import com.mikepenz.aboutlibraries.ui.LibsActivity
|
import com.heinrichreimersoftware.androidissuereporter.IssueReporterLauncher
|
||||||
|
import org.junit.After
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
|
|
||||||
import apps.amine.bou.readerforselfoss.settings.SettingsActivity
|
|
||||||
import apps.amine.bou.readerforselfoss.utils.Config
|
|
||||||
import org.junit.After
|
|
||||||
|
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
class HomeActivityEspressoTest {
|
class HomeActivityEspressoTest {
|
||||||
lateinit var context: Context
|
lateinit var context: Context
|
||||||
@ -40,9 +44,9 @@ class HomeActivityEspressoTest {
|
|||||||
context = InstrumentationRegistry.getInstrumentation().targetContext
|
context = InstrumentationRegistry.getInstrumentation().targetContext
|
||||||
|
|
||||||
val editor =
|
val editor =
|
||||||
context
|
context
|
||||||
.getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE)
|
.getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE)
|
||||||
.edit()
|
.edit()
|
||||||
editor.clear()
|
editor.clear()
|
||||||
|
|
||||||
editor.putString("url", BuildConfig.LOGIN_URL)
|
editor.putString("url", BuildConfig.LOGIN_URL)
|
||||||
@ -60,35 +64,32 @@ class HomeActivityEspressoTest {
|
|||||||
rule.launchActivity(Intent())
|
rule.launchActivity(Intent())
|
||||||
|
|
||||||
onView(
|
onView(
|
||||||
withMenu(
|
withMenu(
|
||||||
id = R.id.action_search,
|
id = R.id.action_search,
|
||||||
titleId = R.string.menu_home_search
|
titleId = R.string.menu_home_search
|
||||||
)
|
)
|
||||||
).perform(click())
|
).perform(click())
|
||||||
|
|
||||||
onView(withId(R.id.search_bar)).check(matches(isDisplayed()))
|
onView(withId(R.id.search_bar)).check(matches(isDisplayed()))
|
||||||
|
|
||||||
onView(withId(R.id.search_src_text)).perform(typeText("android"), pressKey(KeyEvent.KEYCODE_SEARCH), closeSoftKeyboard())
|
onView(withId(R.id.search_src_text)).perform(
|
||||||
|
typeText("android"),
|
||||||
|
pressKey(KeyEvent.KEYCODE_SEARCH),
|
||||||
|
closeSoftKeyboard()
|
||||||
|
)
|
||||||
|
|
||||||
onView(withContentDescription(R.string.abc_toolbar_collapse_description)).perform(click())
|
onView(withContentDescription(R.string.abc_toolbar_collapse_description)).perform(click())
|
||||||
|
|
||||||
|
|
||||||
onView(withMenu(id = R.id.readAll, titleId = R.string.readAll)).perform(click())
|
|
||||||
|
|
||||||
openActionBarOverflowOrOptionsMenu(context)
|
openActionBarOverflowOrOptionsMenu(context)
|
||||||
|
|
||||||
onView(withMenu(id = R.id.refresh, titleId = R.string.menu_home_refresh))
|
onView(withMenu(id = R.id.refresh, titleId = R.string.menu_home_refresh))
|
||||||
.perform(click())
|
.perform(click())
|
||||||
|
|
||||||
openActionBarOverflowOrOptionsMenu(context)
|
openActionBarOverflowOrOptionsMenu(context)
|
||||||
|
|
||||||
onView(withText(R.string.action_disconnect)).perform(click())
|
onView(withText(R.string.action_disconnect)).perform(click())
|
||||||
|
|
||||||
intended(hasComponent(LoginActivity::class.java.name), times(1))
|
intended(hasComponent(LoginActivity::class.java.name), times(1))
|
||||||
|
|
||||||
//onView(isRoot()).perform(pressBack())
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -98,8 +99,9 @@ class HomeActivityEspressoTest {
|
|||||||
|
|
||||||
onView(withId(R.id.material_drawer_layout)).perform(DrawerActions.open())
|
onView(withId(R.id.material_drawer_layout)).perform(DrawerActions.open())
|
||||||
|
|
||||||
onView(withText(R.string.action_about)).perform(click())
|
onView(withText(R.string.drawer_report_bug)).perform(click())
|
||||||
intended(hasComponent(LibsActivity::class.java.name))
|
intended(hasComponent(IssueReporterLauncher.Activity::class.java.name))
|
||||||
|
onView(isRoot()).perform(pressBack())
|
||||||
onView(isRoot()).perform(pressBack())
|
onView(isRoot()).perform(pressBack())
|
||||||
intended(hasComponent(HomeActivity::class.java.name))
|
intended(hasComponent(HomeActivity::class.java.name))
|
||||||
|
|
||||||
@ -107,11 +109,6 @@ class HomeActivityEspressoTest {
|
|||||||
|
|
||||||
onView(withId(R.id.material_drawer_layout)).perform(DrawerActions.open())
|
onView(withId(R.id.material_drawer_layout)).perform(DrawerActions.open())
|
||||||
onView(withText(R.string.drawer_action_clear)).perform(click())
|
onView(withText(R.string.drawer_action_clear)).perform(click())
|
||||||
|
|
||||||
// bug
|
|
||||||
//onView(withText(R.string.title_activity_settings)).perform(scrollTo(), click())
|
|
||||||
//intended(hasComponent(SettingsActivity::class.java.name))
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: test articles opening and actions for cards and lists
|
// TODO: test articles opening and actions for cards and lists
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
package apps.amine.bou.readerforselfoss
|
package apps.amine.bou.readerforselfoss
|
||||||
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.support.test.InstrumentationRegistry.getInstrumentation
|
import android.support.test.InstrumentationRegistry.getInstrumentation
|
||||||
@ -11,22 +9,19 @@ import android.support.test.espresso.assertion.ViewAssertions.matches
|
|||||||
import android.support.test.espresso.intent.Intents
|
import android.support.test.espresso.intent.Intents
|
||||||
import android.support.test.espresso.intent.Intents.intended
|
import android.support.test.espresso.intent.Intents.intended
|
||||||
import android.support.test.espresso.intent.Intents.times
|
import android.support.test.espresso.intent.Intents.times
|
||||||
import android.support.test.espresso.intent.matcher.IntentMatchers.*
|
import android.support.test.espresso.intent.matcher.IntentMatchers.hasComponent
|
||||||
import android.support.test.espresso.intent.matcher.UriMatchers.hasHost
|
import android.support.test.espresso.matcher.ViewMatchers.isDisplayed
|
||||||
import android.support.test.espresso.matcher.ViewMatchers.*
|
import android.support.test.espresso.matcher.ViewMatchers.withId
|
||||||
|
import android.support.test.espresso.matcher.ViewMatchers.withText
|
||||||
import android.support.test.rule.ActivityTestRule
|
import android.support.test.rule.ActivityTestRule
|
||||||
import android.support.test.runner.AndroidJUnit4
|
import android.support.test.runner.AndroidJUnit4
|
||||||
|
import apps.amine.bou.readerforselfoss.utils.Config
|
||||||
import org.hamcrest.Matchers.allOf
|
import org.junit.After
|
||||||
import org.hamcrest.Matchers.equalTo
|
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
|
import java.util.*
|
||||||
import apps.amine.bou.readerforselfoss.utils.Config
|
|
||||||
import org.junit.After
|
|
||||||
|
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
class IntroActivityEspressoTest {
|
class IntroActivityEspressoTest {
|
||||||
@ -37,16 +32,16 @@ class IntroActivityEspressoTest {
|
|||||||
@Before
|
@Before
|
||||||
fun clearData() {
|
fun clearData() {
|
||||||
val editor =
|
val editor =
|
||||||
getInstrumentation().targetContext
|
getInstrumentation().targetContext
|
||||||
.getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE)
|
.getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE)
|
||||||
.edit()
|
.edit()
|
||||||
editor.clear()
|
editor.clear()
|
||||||
editor.commit()
|
editor.commit()
|
||||||
|
|
||||||
Intents.init()
|
Intents.init()
|
||||||
}
|
}
|
||||||
|
|
||||||
/*@Test
|
@Test
|
||||||
fun nextEachTimes() {
|
fun nextEachTimes() {
|
||||||
|
|
||||||
rule.launchActivity(Intent())
|
rule.launchActivity(Intent())
|
||||||
@ -60,8 +55,7 @@ class IntroActivityEspressoTest {
|
|||||||
|
|
||||||
intended(hasComponent(IntroActivity::class.java.name), times(1))
|
intended(hasComponent(IntroActivity::class.java.name), times(1))
|
||||||
intended(hasComponent(LoginActivity::class.java.name), times(1))
|
intended(hasComponent(LoginActivity::class.java.name), times(1))
|
||||||
|
}
|
||||||
}*/
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun nextBackRandomTimes() {
|
fun nextBackRandomTimes() {
|
||||||
@ -75,7 +69,7 @@ class IntroActivityEspressoTest {
|
|||||||
onView(withText(R.string.intro_hello_title)).check(matches(isDisplayed()))
|
onView(withText(R.string.intro_hello_title)).check(matches(isDisplayed()))
|
||||||
onView(withId(R.id.button_next)).perform(click())
|
onView(withId(R.id.button_next)).perform(click())
|
||||||
|
|
||||||
repeat(random) {_ ->
|
repeat(random) { _ ->
|
||||||
onView(withText(R.string.intro_needs_selfoss_message)).check(matches(isDisplayed()))
|
onView(withText(R.string.intro_needs_selfoss_message)).check(matches(isDisplayed()))
|
||||||
onView(withId(R.id.button_next)).perform(click())
|
onView(withId(R.id.button_next)).perform(click())
|
||||||
onView(withText(R.string.intro_all_set_message)).check(matches(isDisplayed()))
|
onView(withText(R.string.intro_all_set_message)).check(matches(isDisplayed()))
|
||||||
@ -88,30 +82,6 @@ class IntroActivityEspressoTest {
|
|||||||
|
|
||||||
intended(hasComponent(IntroActivity::class.java.name), times(1))
|
intended(hasComponent(IntroActivity::class.java.name), times(1))
|
||||||
intended(hasComponent(LoginActivity::class.java.name), times(1))
|
intended(hasComponent(LoginActivity::class.java.name), times(1))
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun clickSelfossUrl() {
|
|
||||||
rule.launchActivity(Intent())
|
|
||||||
|
|
||||||
onView(withText(R.string.intro_hello_title)).check(matches(isDisplayed()))
|
|
||||||
|
|
||||||
onView(withId(R.id.button_next)).perform(click())
|
|
||||||
|
|
||||||
onView(withId(R.id.button_message)).perform(click())
|
|
||||||
|
|
||||||
intended(
|
|
||||||
allOf(
|
|
||||||
hasData(
|
|
||||||
hasHost(
|
|
||||||
equalTo("selfoss.aditu.de")
|
|
||||||
)
|
|
||||||
),
|
|
||||||
hasAction(Intent.ACTION_VIEW)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
|
@ -5,45 +5,48 @@ import android.content.Intent
|
|||||||
import android.support.test.InstrumentationRegistry
|
import android.support.test.InstrumentationRegistry
|
||||||
import android.support.test.espresso.Espresso.onView
|
import android.support.test.espresso.Espresso.onView
|
||||||
import android.support.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu
|
import android.support.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu
|
||||||
import android.support.test.espresso.action.ViewActions.*
|
import android.support.test.espresso.action.ViewActions.click
|
||||||
|
import android.support.test.espresso.action.ViewActions.closeSoftKeyboard
|
||||||
|
import android.support.test.espresso.action.ViewActions.pressBack
|
||||||
|
import android.support.test.espresso.action.ViewActions.typeText
|
||||||
import android.support.test.espresso.assertion.ViewAssertions.matches
|
import android.support.test.espresso.assertion.ViewAssertions.matches
|
||||||
import android.support.test.espresso.intent.Intents
|
import android.support.test.espresso.intent.Intents
|
||||||
import android.support.test.espresso.intent.Intents.intended
|
import android.support.test.espresso.intent.Intents.intended
|
||||||
import android.support.test.espresso.intent.Intents.times
|
import android.support.test.espresso.intent.Intents.times
|
||||||
import android.support.test.espresso.intent.matcher.IntentMatchers.hasComponent
|
import android.support.test.espresso.intent.matcher.IntentMatchers.hasComponent
|
||||||
import android.support.test.espresso.matcher.ViewMatchers
|
import android.support.test.espresso.matcher.ViewMatchers
|
||||||
import android.support.test.espresso.matcher.ViewMatchers.*
|
import android.support.test.espresso.matcher.ViewMatchers.isRoot
|
||||||
|
import android.support.test.espresso.matcher.ViewMatchers.withEffectiveVisibility
|
||||||
|
import android.support.test.espresso.matcher.ViewMatchers.withId
|
||||||
|
import android.support.test.espresso.matcher.ViewMatchers.withText
|
||||||
import android.support.test.rule.ActivityTestRule
|
import android.support.test.rule.ActivityTestRule
|
||||||
import android.support.test.runner.AndroidJUnit4
|
import android.support.test.runner.AndroidJUnit4
|
||||||
|
import apps.amine.bou.readerforselfoss.utils.Config
|
||||||
import com.mikepenz.aboutlibraries.ui.LibsActivity
|
import com.mikepenz.aboutlibraries.ui.LibsActivity
|
||||||
|
import org.junit.After
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
|
|
||||||
import apps.amine.bou.readerforselfoss.utils.Config
|
|
||||||
import org.junit.After
|
|
||||||
|
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
class LoginActivityEspressoTest {
|
class LoginActivityEspressoTest {
|
||||||
|
|
||||||
@Rule @JvmField
|
@Rule @JvmField
|
||||||
val rule = ActivityTestRule(LoginActivity::class.java, true, false)
|
val rule = ActivityTestRule(LoginActivity::class.java, true, false)
|
||||||
|
|
||||||
lateinit var context: Context
|
private lateinit var context: Context
|
||||||
lateinit var url: String
|
private lateinit var url: String
|
||||||
lateinit var username: String
|
private lateinit var username: String
|
||||||
lateinit var password: String
|
private lateinit var password: String
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
context = InstrumentationRegistry.getInstrumentation().targetContext
|
context = InstrumentationRegistry.getInstrumentation().targetContext
|
||||||
val editor =
|
val editor =
|
||||||
context
|
context
|
||||||
.getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE)
|
.getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE)
|
||||||
.edit()
|
.edit()
|
||||||
editor.clear()
|
editor.clear()
|
||||||
editor.commit()
|
editor.commit()
|
||||||
|
|
||||||
@ -69,20 +72,18 @@ class LoginActivityEspressoTest {
|
|||||||
onView(isRoot()).perform(pressBack())
|
onView(isRoot()).perform(pressBack())
|
||||||
|
|
||||||
intended(hasComponent(LoginActivity::class.java.name))
|
intended(hasComponent(LoginActivity::class.java.name))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun wrongLoginUrl() {
|
fun wrongLoginUrl() {
|
||||||
rule.launchActivity(Intent())
|
rule.launchActivity(Intent())
|
||||||
|
|
||||||
onView(withId(R.id.login_progress))
|
onView(withId(R.id.loginProgress))
|
||||||
.check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE)))
|
.check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE)))
|
||||||
|
|
||||||
onView(withId(R.id.url)).perform(click()).perform(typeText("WRONGURL"))
|
onView(withId(R.id.urlView)).perform(click()).perform(typeText("WRONGURL"))
|
||||||
|
|
||||||
onView(withId(R.id.email_sign_in_button)).perform(click())
|
onView(withId(R.id.signInButton)).perform(click())
|
||||||
|
|
||||||
onView(withId(R.id.urlLayout)).check(matches(isHintOrErrorEnabled()))
|
onView(withId(R.id.urlLayout)).check(matches(isHintOrErrorEnabled()))
|
||||||
}
|
}
|
||||||
@ -94,26 +95,29 @@ class LoginActivityEspressoTest {
|
|||||||
|
|
||||||
rule.launchActivity(Intent())
|
rule.launchActivity(Intent())
|
||||||
|
|
||||||
onView(withId(R.id.url)).perform(click()).perform(typeText(url), closeSoftKeyboard())
|
onView(withId(R.id.urlView)).perform(click()).perform(typeText(url), closeSoftKeyboard())
|
||||||
|
|
||||||
onView(withId(R.id.withLogin)).perform(click())
|
onView(withId(R.id.withLogin)).perform(click())
|
||||||
|
|
||||||
onView(withId(R.id.email_sign_in_button)).perform(click())
|
onView(withId(R.id.signInButton)).perform(click())
|
||||||
|
|
||||||
onView(withId(R.id.loginLayout)).check(matches(isHintOrErrorEnabled()))
|
onView(withId(R.id.loginLayout)).check(matches(isHintOrErrorEnabled()))
|
||||||
onView(withId(R.id.passwordLayout)).check(matches(isHintOrErrorEnabled()))
|
onView(withId(R.id.passwordLayout)).check(matches(isHintOrErrorEnabled()))
|
||||||
|
|
||||||
onView(withId(R.id.login)).perform(click()).perform(typeText(username), closeSoftKeyboard())
|
onView(withId(R.id.loginView)).perform(click()).perform(
|
||||||
|
typeText(username),
|
||||||
|
closeSoftKeyboard()
|
||||||
|
)
|
||||||
|
|
||||||
onView(withId(R.id.passwordLayout)).check(matches(isHintOrErrorEnabled()))
|
onView(withId(R.id.passwordLayout)).check(matches(isHintOrErrorEnabled()))
|
||||||
|
|
||||||
onView(withId(R.id.email_sign_in_button)).perform(click())
|
onView(withId(R.id.signInButton)).perform(click())
|
||||||
|
|
||||||
onView(withId(R.id.passwordLayout)).check(
|
onView(withId(R.id.passwordLayout)).check(
|
||||||
matches(
|
matches(
|
||||||
isHintOrErrorEnabled())
|
isHintOrErrorEnabled()
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -121,20 +125,25 @@ class LoginActivityEspressoTest {
|
|||||||
|
|
||||||
rule.launchActivity(Intent())
|
rule.launchActivity(Intent())
|
||||||
|
|
||||||
onView(withId(R.id.url)).perform(click()).perform(typeText(url), closeSoftKeyboard())
|
onView(withId(R.id.urlView)).perform(click()).perform(typeText(url), closeSoftKeyboard())
|
||||||
|
|
||||||
onView(withId(R.id.withLogin)).perform(click())
|
onView(withId(R.id.withLogin)).perform(click())
|
||||||
|
|
||||||
onView(withId(R.id.login)).perform(click()).perform(typeText(username), closeSoftKeyboard())
|
onView(withId(R.id.loginView)).perform(click()).perform(
|
||||||
|
typeText(username),
|
||||||
|
closeSoftKeyboard()
|
||||||
|
)
|
||||||
|
|
||||||
onView(withId(R.id.password)).perform(click()).perform(typeText("WRONGPASS"), closeSoftKeyboard())
|
onView(withId(R.id.passwordView)).perform(click()).perform(
|
||||||
|
typeText("WRONGPASS"),
|
||||||
|
closeSoftKeyboard()
|
||||||
|
)
|
||||||
|
|
||||||
onView(withId(R.id.email_sign_in_button)).perform(click())
|
onView(withId(R.id.signInButton)).perform(click())
|
||||||
|
|
||||||
onView(withId(R.id.urlLayout)).check(matches(isHintOrErrorEnabled()))
|
onView(withId(R.id.urlLayout)).check(matches(isHintOrErrorEnabled()))
|
||||||
onView(withId(R.id.loginLayout)).check(matches(isHintOrErrorEnabled()))
|
onView(withId(R.id.loginLayout)).check(matches(isHintOrErrorEnabled()))
|
||||||
onView(withId(R.id.passwordLayout)).check(matches(isHintOrErrorEnabled()))
|
onView(withId(R.id.passwordLayout)).check(matches(isHintOrErrorEnabled()))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -142,23 +151,27 @@ class LoginActivityEspressoTest {
|
|||||||
|
|
||||||
rule.launchActivity(Intent())
|
rule.launchActivity(Intent())
|
||||||
|
|
||||||
onView(withId(R.id.url)).perform(click()).perform(typeText(url), closeSoftKeyboard())
|
onView(withId(R.id.urlView)).perform(click()).perform(typeText(url), closeSoftKeyboard())
|
||||||
|
|
||||||
onView(withId(R.id.withLogin)).perform(click())
|
onView(withId(R.id.withLogin)).perform(click())
|
||||||
|
|
||||||
onView(withId(R.id.login)).perform(click()).perform(typeText(username), closeSoftKeyboard())
|
onView(withId(R.id.loginView)).perform(click()).perform(
|
||||||
|
typeText(username),
|
||||||
|
closeSoftKeyboard()
|
||||||
|
)
|
||||||
|
|
||||||
onView(withId(R.id.password)).perform(click()).perform(typeText(password), closeSoftKeyboard())
|
onView(withId(R.id.passwordView)).perform(click()).perform(
|
||||||
|
typeText(password),
|
||||||
|
closeSoftKeyboard()
|
||||||
|
)
|
||||||
|
|
||||||
onView(withId(R.id.email_sign_in_button)).perform(click())
|
onView(withId(R.id.signInButton)).perform(click())
|
||||||
|
|
||||||
intended(hasComponent(HomeActivity::class.java.name))
|
intended(hasComponent(HomeActivity::class.java.name))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
fun releaseIntents() {
|
fun releaseIntents() {
|
||||||
Intents.release()
|
Intents.release()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -17,7 +17,6 @@ import org.junit.Rule
|
|||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
|
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
class MainActivityEspressoTest {
|
class MainActivityEspressoTest {
|
||||||
|
|
||||||
@ -48,7 +47,6 @@ class MainActivityEspressoTest {
|
|||||||
intended(hasComponent(MainActivity::class.java.name))
|
intended(hasComponent(MainActivity::class.java.name))
|
||||||
intended(hasComponent(IntroActivity::class.java.name))
|
intended(hasComponent(IntroActivity::class.java.name))
|
||||||
intended(hasComponent(LoginActivity::class.java.name), times(0))
|
intended(hasComponent(LoginActivity::class.java.name), times(0))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -61,13 +59,10 @@ class MainActivityEspressoTest {
|
|||||||
intended(hasComponent(MainActivity::class.java.name))
|
intended(hasComponent(MainActivity::class.java.name))
|
||||||
intended(hasComponent(LoginActivity::class.java.name))
|
intended(hasComponent(LoginActivity::class.java.name))
|
||||||
intended(hasComponent(IntroActivity::class.java.name), times(0))
|
intended(hasComponent(IntroActivity::class.java.name), times(0))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
fun releaseIntents() {
|
fun releaseIntents() {
|
||||||
Intents.release()
|
Intents.release()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -1,31 +1,29 @@
|
|||||||
package apps.amine.bou.readerforselfoss
|
package apps.amine.bou.readerforselfoss
|
||||||
|
|
||||||
import android.view.View
|
|
||||||
import android.support.design.widget.TextInputLayout
|
import android.support.design.widget.TextInputLayout
|
||||||
import android.support.test.espresso.matcher.ViewMatchers
|
import android.support.test.espresso.matcher.ViewMatchers
|
||||||
|
import android.view.View
|
||||||
import org.hamcrest.Description
|
import org.hamcrest.Description
|
||||||
import org.hamcrest.Matcher
|
import org.hamcrest.Matcher
|
||||||
import org.hamcrest.TypeSafeMatcher
|
|
||||||
import org.hamcrest.Matchers
|
import org.hamcrest.Matchers
|
||||||
|
import org.hamcrest.TypeSafeMatcher
|
||||||
|
|
||||||
|
|
||||||
fun isHintOrErrorEnabled(): Matcher<View> =
|
fun isHintOrErrorEnabled(): Matcher<View> =
|
||||||
object : TypeSafeMatcher<View>() {
|
object : TypeSafeMatcher<View>() {
|
||||||
override fun describeTo(description: Description?) {}
|
override fun describeTo(description: Description?) {
|
||||||
|
|
||||||
override fun matchesSafely(item: View?): Boolean {
|
|
||||||
if (item !is TextInputLayout) {
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return item.isHintEnabled || item.isErrorEnabled
|
override fun matchesSafely(item: View?): Boolean {
|
||||||
|
if (item !is TextInputLayout) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return item.isHintEnabled || item.isErrorEnabled
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fun withMenu(id: Int, titleId: Int): Matcher<View> =
|
fun withMenu(id: Int, titleId: Int): Matcher<View> =
|
||||||
Matchers.anyOf(
|
Matchers.anyOf(
|
||||||
ViewMatchers.withId(id),
|
ViewMatchers.withId(id),
|
||||||
ViewMatchers.withText(titleId)
|
ViewMatchers.withText(titleId)
|
||||||
)
|
)
|
||||||
|
@ -28,7 +28,8 @@
|
|||||||
android:name=".IntroActivity"
|
android:name=".IntroActivity"
|
||||||
android:theme="@style/Theme.Intro">
|
android:theme="@style/Theme.Intro">
|
||||||
</activity>
|
</activity>
|
||||||
<activity android:name=".LoginActivity"
|
<activity
|
||||||
|
android:name=".LoginActivity"
|
||||||
android:label="@string/title_activity_login">
|
android:label="@string/title_activity_login">
|
||||||
</activity>
|
</activity>
|
||||||
<activity android:name=".HomeActivity">
|
<activity android:name=".HomeActivity">
|
||||||
@ -41,13 +42,15 @@
|
|||||||
android:name="android.support.PARENT_ACTIVITY"
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
android:value="apps.amine.bou.readerforselfoss.HomeActivity" />
|
android:value="apps.amine.bou.readerforselfoss.HomeActivity" />
|
||||||
</activity>
|
</activity>
|
||||||
<activity android:name=".SourcesActivity"
|
<activity
|
||||||
|
android:name=".SourcesActivity"
|
||||||
android:parentActivityName=".HomeActivity">
|
android:parentActivityName=".HomeActivity">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.support.PARENT_ACTIVITY"
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
android:value=".HomeActivity" />
|
android:value=".HomeActivity" />
|
||||||
</activity>
|
</activity>
|
||||||
<activity android:name=".AddSourceActivity"
|
<activity
|
||||||
|
android:name=".AddSourceActivity"
|
||||||
android:parentActivityName=".SourcesActivity">
|
android:parentActivityName=".SourcesActivity">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.support.PARENT_ACTIVITY"
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
@ -61,9 +64,10 @@
|
|||||||
<data android:mimeType="text/plain" />
|
<data android:mimeType="text/plain" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<activity android:name=".ReaderActivity"
|
<activity
|
||||||
android:theme="@style/DragDismissTheme">
|
android:name=".ReaderActivity">
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="apps.amine.bou.readerforselfoss.utils.glide.SelfSignedGlideModule"
|
android:name="apps.amine.bou.readerforselfoss.utils.glide.SelfSignedGlideModule"
|
||||||
android:value="GlideModule" />
|
android:value="GlideModule" />
|
||||||
|
@ -5,21 +5,24 @@ import android.os.Bundle
|
|||||||
import android.preference.PreferenceManager
|
import android.preference.PreferenceManager
|
||||||
import android.support.constraint.ConstraintLayout
|
import android.support.constraint.ConstraintLayout
|
||||||
import android.support.v7.app.AppCompatActivity
|
import android.support.v7.app.AppCompatActivity
|
||||||
import android.support.v7.widget.Toolbar
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.*
|
import android.widget.AdapterView
|
||||||
|
import android.widget.ArrayAdapter
|
||||||
import retrofit2.Call
|
import android.widget.EditText
|
||||||
import retrofit2.Callback
|
import android.widget.ProgressBar
|
||||||
import retrofit2.Response
|
import android.widget.Spinner
|
||||||
|
import android.widget.TextView
|
||||||
|
import android.widget.Toast
|
||||||
import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi
|
import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi
|
||||||
import apps.amine.bou.readerforselfoss.api.selfoss.Spout
|
import apps.amine.bou.readerforselfoss.api.selfoss.Spout
|
||||||
import apps.amine.bou.readerforselfoss.api.selfoss.SuccessResponse
|
import apps.amine.bou.readerforselfoss.api.selfoss.SuccessResponse
|
||||||
import apps.amine.bou.readerforselfoss.utils.Config
|
import apps.amine.bou.readerforselfoss.utils.Config
|
||||||
import apps.amine.bou.readerforselfoss.utils.isBaseUrlValid
|
import apps.amine.bou.readerforselfoss.utils.isBaseUrlValid
|
||||||
import com.ftinc.scoop.Scoop
|
import com.ftinc.scoop.Scoop
|
||||||
|
import kotlinx.android.synthetic.main.activity_add_source.*
|
||||||
|
import retrofit2.Call
|
||||||
|
import retrofit2.Callback
|
||||||
|
import retrofit2.Response
|
||||||
|
|
||||||
class AddSourceActivity : AppCompatActivity() {
|
class AddSourceActivity : AppCompatActivity() {
|
||||||
|
|
||||||
@ -29,40 +32,48 @@ class AddSourceActivity : AppCompatActivity() {
|
|||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
Scoop.getInstance().apply(this)
|
Scoop.getInstance().apply(this)
|
||||||
setContentView(R.layout.activity_add_source)
|
setContentView(R.layout.activity_add_source)
|
||||||
val toolbar: Toolbar = findViewById(R.id.toolbar)
|
|
||||||
setSupportActionBar(toolbar)
|
setSupportActionBar(toolbar)
|
||||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||||
supportActionBar?.setDisplayShowHomeEnabled(true)
|
supportActionBar?.setDisplayShowHomeEnabled(true)
|
||||||
|
|
||||||
val mProgress: ProgressBar = findViewById(R.id.progress)
|
|
||||||
val mForm: ConstraintLayout = findViewById(R.id.formContainer)
|
|
||||||
val mNameInput: EditText = findViewById(R.id.nameInput)
|
|
||||||
val mSourceUri: EditText = findViewById(R.id.sourceUri)
|
|
||||||
val mTags: EditText = findViewById(R.id.tags)
|
|
||||||
val mSpoutsSpinner: Spinner = findViewById(R.id.spoutsSpinner)
|
|
||||||
val mSaveBtn: Button = findViewById(R.id.saveBtn)
|
|
||||||
var api: SelfossApi? = null
|
var api: SelfossApi? = null
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val prefs = PreferenceManager.getDefaultSharedPreferences(this)
|
val prefs = PreferenceManager.getDefaultSharedPreferences(this)
|
||||||
api = SelfossApi(this, this@AddSourceActivity, prefs.getBoolean("isSelfSignedCert", false), prefs.getBoolean("should_log_everything", false))
|
api = SelfossApi(
|
||||||
|
this,
|
||||||
|
this@AddSourceActivity,
|
||||||
|
prefs.getBoolean("isSelfSignedCert", false),
|
||||||
|
prefs.getBoolean("should_log_everything", false)
|
||||||
|
)
|
||||||
} catch (e: IllegalArgumentException) {
|
} catch (e: IllegalArgumentException) {
|
||||||
mustLoginToAddSource()
|
mustLoginToAddSource()
|
||||||
}
|
}
|
||||||
|
|
||||||
val intent = intent
|
maybeGetDetailsFromIntentSharing(intent, sourceUri, nameInput)
|
||||||
if (Intent.ACTION_SEND == intent.action && "text/plain" == intent.type) {
|
|
||||||
mSourceUri.setText(intent.getStringExtra(Intent.EXTRA_TEXT))
|
saveBtn.setOnClickListener {
|
||||||
mNameInput.setText(intent.getStringExtra(Intent.EXTRA_TITLE))
|
handleSaveSource(tags, nameInput.text.toString(), sourceUri.text.toString(), api!!)
|
||||||
}
|
}
|
||||||
|
|
||||||
mSaveBtn.setOnClickListener {
|
val config = Config(this)
|
||||||
handleSaveSource(mTags, mNameInput.text.toString(), mSourceUri.text.toString(), api!!)
|
|
||||||
|
if (config.baseUrl.isEmpty() || !config.baseUrl.isBaseUrlValid()) {
|
||||||
|
mustLoginToAddSource()
|
||||||
|
} else {
|
||||||
|
handleSpoutsSpinner(spoutsSpinner, api, progress, formContainer)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleSpoutsSpinner(
|
||||||
|
spoutsSpinner: Spinner,
|
||||||
|
api: SelfossApi?,
|
||||||
|
mProgress: ProgressBar,
|
||||||
|
formContainer: ConstraintLayout
|
||||||
|
) {
|
||||||
val spoutsKV = HashMap<String, String>()
|
val spoutsKV = HashMap<String, String>()
|
||||||
mSpoutsSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
spoutsSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||||
override fun onItemSelected(adapterView: AdapterView<*>, view: View, i: Int, l: Long) {
|
override fun onItemSelected(adapterView: AdapterView<*>, view: View, i: Int, l: Long) {
|
||||||
val spoutName = (view as TextView).text.toString()
|
val spoutName = (view as TextView).text.toString()
|
||||||
mSpoutsValue = spoutsKV[spoutName]
|
mSpoutsValue = spoutsKV[spoutName]
|
||||||
@ -73,48 +84,59 @@ class AddSourceActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val config = Config(this)
|
var items: Map<String, Spout>
|
||||||
|
api!!.spouts().enqueue(object : Callback<Map<String, Spout>> {
|
||||||
|
override fun onResponse(
|
||||||
|
call: Call<Map<String, Spout>>,
|
||||||
|
response: Response<Map<String, Spout>>
|
||||||
|
) {
|
||||||
|
if (response.body() != null) {
|
||||||
|
items = response.body()!!
|
||||||
|
|
||||||
if (config.baseUrl.isEmpty() || !config.baseUrl.isBaseUrlValid()) {
|
val itemsStrings = items.map { it.value.name }
|
||||||
mustLoginToAddSource()
|
for ((key, value) in items) {
|
||||||
} else {
|
spoutsKV.put(value.name, key)
|
||||||
|
|
||||||
var items: Map<String, Spout>
|
|
||||||
api!!.spouts().enqueue(object : Callback<Map<String, Spout>> {
|
|
||||||
override fun onResponse(call: Call<Map<String, Spout>>, response: Response<Map<String, Spout>>) {
|
|
||||||
if (response.body() != null) {
|
|
||||||
items = response.body()!!
|
|
||||||
|
|
||||||
val itemsStrings = items.map { it.value.name }
|
|
||||||
for ((key, value) in items) {
|
|
||||||
spoutsKV.put(value.name, key)
|
|
||||||
}
|
|
||||||
|
|
||||||
mProgress.visibility = View.GONE
|
|
||||||
mForm.visibility = View.VISIBLE
|
|
||||||
|
|
||||||
val spinnerArrayAdapter =
|
|
||||||
ArrayAdapter(
|
|
||||||
this@AddSourceActivity,
|
|
||||||
android.R.layout.simple_spinner_item,
|
|
||||||
itemsStrings)
|
|
||||||
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
|
||||||
mSpoutsSpinner.adapter = spinnerArrayAdapter
|
|
||||||
|
|
||||||
} else {
|
|
||||||
handleProblemWithSpouts()
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
override fun onFailure(call: Call<Map<String, Spout>>, t: Throwable) {
|
mProgress.visibility = View.GONE
|
||||||
|
formContainer.visibility = View.VISIBLE
|
||||||
|
|
||||||
|
val spinnerArrayAdapter =
|
||||||
|
ArrayAdapter(
|
||||||
|
this@AddSourceActivity,
|
||||||
|
android.R.layout.simple_spinner_item,
|
||||||
|
itemsStrings
|
||||||
|
)
|
||||||
|
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||||
|
spoutsSpinner.adapter = spinnerArrayAdapter
|
||||||
|
} else {
|
||||||
handleProblemWithSpouts()
|
handleProblemWithSpouts()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun handleProblemWithSpouts() {
|
override fun onFailure(call: Call<Map<String, Spout>>, t: Throwable) {
|
||||||
Toast.makeText(this@AddSourceActivity, R.string.cant_get_spouts, Toast.LENGTH_SHORT).show()
|
handleProblemWithSpouts()
|
||||||
mProgress.visibility = View.GONE
|
}
|
||||||
}
|
|
||||||
})
|
private fun handleProblemWithSpouts() {
|
||||||
|
Toast.makeText(
|
||||||
|
this@AddSourceActivity,
|
||||||
|
R.string.cant_get_spouts,
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
mProgress.visibility = View.GONE
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun maybeGetDetailsFromIntentSharing(
|
||||||
|
intent: Intent,
|
||||||
|
sourceUri: EditText,
|
||||||
|
nameInput: EditText
|
||||||
|
) {
|
||||||
|
if (Intent.ACTION_SEND == intent.action && "text/plain" == intent.type) {
|
||||||
|
sourceUri.setText(intent.getStringExtra(Intent.EXTRA_TEXT))
|
||||||
|
nameInput.setText(intent.getStringExtra(Intent.EXTRA_TITLE))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,28 +147,41 @@ class AddSourceActivity : AppCompatActivity() {
|
|||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleSaveSource(mTags: EditText, title: String, url: String, api: SelfossApi) {
|
private fun handleSaveSource(tags: EditText, title: String, url: String, api: SelfossApi) {
|
||||||
|
|
||||||
if (title.isEmpty() || url.isEmpty() || mSpoutsValue == null || mSpoutsValue!!.isEmpty()) {
|
val sourceDetailsAvailable = title.isEmpty() || url.isEmpty() || mSpoutsValue == null || mSpoutsValue!!.isEmpty()
|
||||||
|
|
||||||
|
if (sourceDetailsAvailable) {
|
||||||
Toast.makeText(this, R.string.form_not_complete, Toast.LENGTH_SHORT).show()
|
Toast.makeText(this, R.string.form_not_complete, Toast.LENGTH_SHORT).show()
|
||||||
} else {
|
} else {
|
||||||
api.createSource(
|
api.createSource(
|
||||||
title,
|
title,
|
||||||
url,
|
url,
|
||||||
mSpoutsValue!!,
|
mSpoutsValue!!,
|
||||||
mTags.text.toString(),
|
tags.text.toString(),
|
||||||
""
|
""
|
||||||
).enqueue(object : Callback<SuccessResponse> {
|
).enqueue(object : Callback<SuccessResponse> {
|
||||||
override fun onResponse(call: Call<SuccessResponse>, response: Response<SuccessResponse>) {
|
override fun onResponse(
|
||||||
|
call: Call<SuccessResponse>,
|
||||||
|
response: Response<SuccessResponse>
|
||||||
|
) {
|
||||||
if (response.body() != null && response.body()!!.isSuccess) {
|
if (response.body() != null && response.body()!!.isSuccess) {
|
||||||
finish()
|
finish()
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(this@AddSourceActivity, R.string.cant_create_source, Toast.LENGTH_SHORT).show()
|
Toast.makeText(
|
||||||
|
this@AddSourceActivity,
|
||||||
|
R.string.cant_create_source,
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onFailure(call: Call<SuccessResponse>, t: Throwable) {
|
override fun onFailure(call: Call<SuccessResponse>, t: Throwable) {
|
||||||
Toast.makeText(this@AddSourceActivity, R.string.cant_create_source, Toast.LENGTH_SHORT).show()
|
Toast.makeText(
|
||||||
|
this@AddSourceActivity,
|
||||||
|
R.string.cant_create_source,
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1,51 +1,60 @@
|
|||||||
package apps.amine.bou.readerforselfoss
|
package apps.amine.bou.readerforselfoss
|
||||||
|
|
||||||
import android.content.Intent
|
|
||||||
import android.net.Uri
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.preference.PreferenceManager
|
|
||||||
import android.view.View
|
|
||||||
|
|
||||||
import agency.tango.materialintroscreen.MaterialIntroActivity
|
import agency.tango.materialintroscreen.MaterialIntroActivity
|
||||||
import agency.tango.materialintroscreen.MessageButtonBehaviour
|
import agency.tango.materialintroscreen.MessageButtonBehaviour
|
||||||
import agency.tango.materialintroscreen.SlideFragmentBuilder
|
import agency.tango.materialintroscreen.SlideFragmentBuilder
|
||||||
|
import android.content.Intent
|
||||||
|
import android.net.Uri
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.preference.PreferenceManager
|
||||||
import android.support.v7.app.AppCompatDelegate
|
import android.support.v7.app.AppCompatDelegate
|
||||||
|
import android.view.View
|
||||||
|
|
||||||
class IntroActivity : MaterialIntroActivity() {
|
class IntroActivity : MaterialIntroActivity() {
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
|
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
|
||||||
|
|
||||||
addSlide(SlideFragmentBuilder()
|
addSlide(
|
||||||
.backgroundColor(R.color.colorPrimary)
|
SlideFragmentBuilder()
|
||||||
.buttonsColor(R.color.colorAccent)
|
.backgroundColor(R.color.colorPrimary)
|
||||||
.image(R.drawable.web_hi_res_512)
|
.buttonsColor(R.color.colorAccent)
|
||||||
.title(getString(R.string.intro_hello_title))
|
.image(R.drawable.web_hi_res_512)
|
||||||
.description(getString(R.string.intro_hello_message))
|
.title(getString(R.string.intro_hello_title))
|
||||||
.build())
|
.description(getString(R.string.intro_hello_message))
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
|
||||||
addSlide(SlideFragmentBuilder()
|
addSlide(
|
||||||
.backgroundColor(R.color.colorAccent)
|
SlideFragmentBuilder()
|
||||||
.buttonsColor(R.color.colorPrimary)
|
.backgroundColor(R.color.colorAccent)
|
||||||
.image(R.drawable.ic_info_outline_white_48px)
|
.buttonsColor(R.color.colorPrimary)
|
||||||
.title(getString(R.string.intro_needs_selfoss_title))
|
.image(R.drawable.ic_info_outline_white_48px)
|
||||||
.description(getString(R.string.intro_needs_selfoss_message))
|
.title(getString(R.string.intro_needs_selfoss_title))
|
||||||
.build(),
|
.description(getString(R.string.intro_needs_selfoss_message))
|
||||||
MessageButtonBehaviour(View.OnClickListener {
|
.build(),
|
||||||
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse("https://selfoss.aditu.de"))
|
MessageButtonBehaviour(
|
||||||
startActivity(browserIntent)
|
View.OnClickListener {
|
||||||
}, getString(R.string.intro_needs_selfoss_link)))
|
val browserIntent = Intent(
|
||||||
|
Intent.ACTION_VIEW,
|
||||||
|
Uri.parse("https://selfoss.aditu.de")
|
||||||
|
)
|
||||||
|
startActivity(browserIntent)
|
||||||
|
}, getString(R.string.intro_needs_selfoss_link)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
addSlide(SlideFragmentBuilder()
|
addSlide(
|
||||||
.backgroundColor(R.color.colorPrimaryDark)
|
SlideFragmentBuilder()
|
||||||
.buttonsColor(R.color.colorAccentDark)
|
.backgroundColor(R.color.colorPrimaryDark)
|
||||||
.image(R.drawable.ic_thumb_up_white_48px)
|
.buttonsColor(R.color.colorAccentDark)
|
||||||
.title(getString(R.string.intro_all_set_title))
|
.image(R.drawable.ic_thumb_up_white_48px)
|
||||||
.description(getString(R.string.intro_all_set_message))
|
.title(getString(R.string.intro_all_set_title))
|
||||||
.build())
|
.description(getString(R.string.intro_all_set_message))
|
||||||
|
.build()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onFinish() {
|
override fun onFinish() {
|
||||||
|
@ -6,33 +6,28 @@ import android.content.Context
|
|||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.support.design.widget.TextInputLayout
|
|
||||||
import android.support.v7.app.AlertDialog
|
import android.support.v7.app.AlertDialog
|
||||||
import android.support.v7.app.AppCompatActivity
|
import android.support.v7.app.AppCompatActivity
|
||||||
import android.support.v7.widget.Toolbar
|
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.inputmethod.EditorInfo
|
import android.view.inputmethod.EditorInfo
|
||||||
import android.widget.*
|
import android.widget.TextView
|
||||||
|
import android.widget.Toast
|
||||||
import com.google.firebase.analytics.FirebaseAnalytics
|
|
||||||
import com.mikepenz.aboutlibraries.Libs
|
|
||||||
import com.mikepenz.aboutlibraries.LibsBuilder
|
|
||||||
import retrofit2.Call
|
|
||||||
import retrofit2.Callback
|
|
||||||
import retrofit2.Response
|
|
||||||
|
|
||||||
import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi
|
import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi
|
||||||
import apps.amine.bou.readerforselfoss.api.selfoss.SuccessResponse
|
import apps.amine.bou.readerforselfoss.api.selfoss.SuccessResponse
|
||||||
import apps.amine.bou.readerforselfoss.utils.Config
|
import apps.amine.bou.readerforselfoss.utils.Config
|
||||||
import apps.amine.bou.readerforselfoss.utils.checkAndDisplayStoreApk
|
|
||||||
import apps.amine.bou.readerforselfoss.utils.isBaseUrlValid
|
import apps.amine.bou.readerforselfoss.utils.isBaseUrlValid
|
||||||
import com.crashlytics.android.Crashlytics
|
import com.crashlytics.android.Crashlytics
|
||||||
import com.ftinc.scoop.Scoop
|
import com.ftinc.scoop.Scoop
|
||||||
import io.fabric.sdk.android.Fabric
|
import com.google.firebase.analytics.FirebaseAnalytics
|
||||||
|
import com.mikepenz.aboutlibraries.Libs
|
||||||
|
import com.mikepenz.aboutlibraries.LibsBuilder
|
||||||
|
import kotlinx.android.synthetic.main.activity_login.*
|
||||||
|
import retrofit2.Call
|
||||||
|
import retrofit2.Callback
|
||||||
|
import retrofit2.Response
|
||||||
|
|
||||||
class LoginActivity : AppCompatActivity() {
|
class LoginActivity : AppCompatActivity() {
|
||||||
|
|
||||||
@ -43,101 +38,84 @@ class LoginActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
private lateinit var settings: SharedPreferences
|
private lateinit var settings: SharedPreferences
|
||||||
private lateinit var editor: SharedPreferences.Editor
|
private lateinit var editor: SharedPreferences.Editor
|
||||||
private lateinit var mFirebaseAnalytics: FirebaseAnalytics
|
private lateinit var firebaseAnalytics: FirebaseAnalytics
|
||||||
private lateinit var mUrlView: EditText
|
|
||||||
private lateinit var mLoginView: TextView
|
|
||||||
private lateinit var mHTTPLoginView: TextView
|
|
||||||
private lateinit var mProgressView: View
|
|
||||||
private lateinit var mPasswordView: EditText
|
|
||||||
private lateinit var mHTTPPasswordView: EditText
|
|
||||||
private lateinit var mLoginFormView: View
|
|
||||||
private lateinit var userIdentifier: String
|
private lateinit var userIdentifier: String
|
||||||
private var logErrors: Boolean = false
|
private var logErrors: Boolean = false
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
Scoop.getInstance().apply(this)
|
Scoop.getInstance().apply(this)
|
||||||
setContentView(R.layout.activity_login)
|
setContentView(R.layout.activity_login)
|
||||||
|
|
||||||
val toolbar: Toolbar = findViewById(R.id.toolbar)
|
|
||||||
setSupportActionBar(toolbar)
|
setSupportActionBar(toolbar)
|
||||||
|
|
||||||
if (intent.getBooleanExtra("baseUrlFail", false)) {
|
handleBaseUrlFail()
|
||||||
val alertDialog = AlertDialog.Builder(this).create()
|
|
||||||
alertDialog.setTitle(getString(R.string.warning_wrong_url))
|
|
||||||
alertDialog.setMessage(getString(R.string.base_url_error))
|
|
||||||
alertDialog.setButton(
|
|
||||||
AlertDialog.BUTTON_NEUTRAL,
|
|
||||||
"OK",
|
|
||||||
{ dialog, _ -> dialog.dismiss() })
|
|
||||||
alertDialog.show()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
settings = getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE)
|
settings = getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE)
|
||||||
userIdentifier = settings.getString("unique_id", "")
|
userIdentifier = settings.getString("unique_id", "")
|
||||||
logErrors = settings.getBoolean("loging_debug", false)
|
logErrors = settings.getBoolean("login_debug", false)
|
||||||
|
|
||||||
editor = settings.edit()
|
editor = settings.edit()
|
||||||
|
|
||||||
if (settings.getString("url", "").isNotEmpty()) {
|
if (settings.getString("url", "").isNotEmpty()) {
|
||||||
goToMain()
|
goToMain()
|
||||||
} else {
|
|
||||||
this@LoginActivity.checkAndDisplayStoreApk()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mFirebaseAnalytics = FirebaseAnalytics.getInstance(this)
|
firebaseAnalytics = FirebaseAnalytics.getInstance(this)
|
||||||
mUrlView = findViewById(R.id.url)
|
|
||||||
mLoginView = findViewById(R.id.login)
|
|
||||||
mHTTPLoginView = findViewById(R.id.httpLogin)
|
|
||||||
mPasswordView = findViewById(R.id.password)
|
|
||||||
mHTTPPasswordView = findViewById(R.id.httpPassword)
|
|
||||||
mLoginFormView = findViewById(R.id.login_form)
|
|
||||||
mProgressView = findViewById(R.id.login_progress)
|
|
||||||
|
|
||||||
val mSwitch: Switch = findViewById(R.id.withLogin)
|
handleActions()
|
||||||
val mHTTPSwitch: Switch = findViewById(R.id.withHttpLogin)
|
}
|
||||||
val mLoginLayout: TextInputLayout = findViewById(R.id.loginLayout)
|
|
||||||
val mHTTPLoginLayout: TextInputLayout = findViewById(R.id.httpLoginInput)
|
|
||||||
val mPasswordLayout: TextInputLayout = findViewById(R.id.passwordLayout)
|
|
||||||
val mHTTPPasswordLayout: TextInputLayout = findViewById(R.id.httpPasswordInput)
|
|
||||||
val mEmailSignInButton: Button = findViewById(R.id.email_sign_in_button)
|
|
||||||
val selfHostedSwitch: Switch = findViewById(R.id.withSelfhostedCert)
|
|
||||||
val warningTextview: TextView = findViewById(R.id.warningText)
|
|
||||||
|
|
||||||
selfHostedSwitch.setOnCheckedChangeListener {_, b ->
|
private fun handleActions() {
|
||||||
|
|
||||||
|
withSelfhostedCert.setOnCheckedChangeListener { _, b ->
|
||||||
isWithSelfSignedCert = !isWithSelfSignedCert
|
isWithSelfSignedCert = !isWithSelfSignedCert
|
||||||
val visi: Int = if (b) View.VISIBLE else View.GONE
|
val visi: Int = if (b) View.VISIBLE else View.GONE
|
||||||
|
|
||||||
warningTextview.visibility = visi
|
warningText.visibility = visi
|
||||||
}
|
}
|
||||||
|
|
||||||
mPasswordView.setOnEditorActionListener(TextView.OnEditorActionListener { _, id, _ ->
|
passwordView.setOnEditorActionListener(
|
||||||
if (id == R.id.login || id == EditorInfo.IME_NULL) {
|
TextView.OnEditorActionListener { _, id, _ ->
|
||||||
attemptLogin()
|
if (id == R.id.loginView || id == EditorInfo.IME_NULL) {
|
||||||
return@OnEditorActionListener true
|
attemptLogin()
|
||||||
}
|
return@OnEditorActionListener true
|
||||||
false
|
}
|
||||||
})
|
false
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
mEmailSignInButton.setOnClickListener { attemptLogin() }
|
signInButton.setOnClickListener { attemptLogin() }
|
||||||
|
|
||||||
mSwitch.setOnCheckedChangeListener { _, b ->
|
withLogin.setOnCheckedChangeListener { _, b ->
|
||||||
isWithLogin = !isWithLogin
|
isWithLogin = !isWithLogin
|
||||||
val visi: Int = if (b) View.VISIBLE else View.GONE
|
val visi: Int = if (b) View.VISIBLE else View.GONE
|
||||||
|
|
||||||
mLoginLayout.visibility = visi
|
loginLayout.visibility = visi
|
||||||
mPasswordLayout.visibility = visi
|
passwordLayout.visibility = visi
|
||||||
}
|
}
|
||||||
|
|
||||||
mHTTPSwitch.setOnCheckedChangeListener { _, b ->
|
withHttpLogin.setOnCheckedChangeListener { _, b ->
|
||||||
isWithHTTPLogin = !isWithHTTPLogin
|
isWithHTTPLogin = !isWithHTTPLogin
|
||||||
val visi: Int = if (b) View.VISIBLE else View.GONE
|
val visi: Int = if (b) View.VISIBLE else View.GONE
|
||||||
|
|
||||||
mHTTPLoginLayout.visibility = visi
|
httpLoginInput.visibility = visi
|
||||||
mHTTPPasswordLayout.visibility = visi
|
httpPasswordInput.visibility = visi
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleBaseUrlFail() {
|
||||||
|
if (intent.getBooleanExtra("baseUrlFail", false)) {
|
||||||
|
val alertDialog = AlertDialog.Builder(this).create()
|
||||||
|
alertDialog.setTitle(getString(R.string.warning_wrong_url))
|
||||||
|
alertDialog.setMessage(getString(R.string.base_url_error))
|
||||||
|
alertDialog.setButton(
|
||||||
|
AlertDialog.BUTTON_NEUTRAL,
|
||||||
|
"OK",
|
||||||
|
{ dialog, _ -> dialog.dismiss() }
|
||||||
|
)
|
||||||
|
alertDialog.show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,25 +128,25 @@ class LoginActivity : AppCompatActivity() {
|
|||||||
private fun attemptLogin() {
|
private fun attemptLogin() {
|
||||||
|
|
||||||
// Reset errors.
|
// Reset errors.
|
||||||
mUrlView.error = null
|
urlView.error = null
|
||||||
mLoginView.error = null
|
loginView.error = null
|
||||||
mHTTPLoginView.error = null
|
httpLoginView.error = null
|
||||||
mPasswordView.error = null
|
passwordView.error = null
|
||||||
mHTTPPasswordView.error = null
|
httpPasswordView.error = null
|
||||||
|
|
||||||
// Store values at the time of the login attempt.
|
// Store values at the time of the login attempt.
|
||||||
val url = mUrlView.text.toString()
|
val url = urlView.text.toString()
|
||||||
val login = mLoginView.text.toString()
|
val login = loginView.text.toString()
|
||||||
val httpLogin = mHTTPLoginView.text.toString()
|
val httpLogin = httpLoginView.text.toString()
|
||||||
val password = mPasswordView.text.toString()
|
val password = passwordView.text.toString()
|
||||||
val httpPassword = mHTTPPasswordView.text.toString()
|
val httpPassword = httpPasswordView.text.toString()
|
||||||
|
|
||||||
var cancel = false
|
var cancel = false
|
||||||
var focusView: View? = null
|
var focusView: View? = null
|
||||||
|
|
||||||
if (!url.isBaseUrlValid()) {
|
if (!url.isBaseUrlValid()) {
|
||||||
mUrlView.error = getString(R.string.login_url_problem)
|
urlView.error = getString(R.string.login_url_problem)
|
||||||
focusView = mUrlView
|
focusView = urlView
|
||||||
cancel = true
|
cancel = true
|
||||||
inValidCount++
|
inValidCount++
|
||||||
if (inValidCount == 3) {
|
if (inValidCount == 3) {
|
||||||
@ -176,9 +154,10 @@ class LoginActivity : AppCompatActivity() {
|
|||||||
alertDialog.setTitle(getString(R.string.warning_wrong_url))
|
alertDialog.setTitle(getString(R.string.warning_wrong_url))
|
||||||
alertDialog.setMessage(getString(R.string.text_wrong_url))
|
alertDialog.setMessage(getString(R.string.text_wrong_url))
|
||||||
alertDialog.setButton(
|
alertDialog.setButton(
|
||||||
AlertDialog.BUTTON_NEUTRAL,
|
AlertDialog.BUTTON_NEUTRAL,
|
||||||
"OK",
|
"OK",
|
||||||
{ dialog, _ -> dialog.dismiss() })
|
{ dialog, _ -> dialog.dismiss() }
|
||||||
|
)
|
||||||
alertDialog.show()
|
alertDialog.show()
|
||||||
inValidCount = 0
|
inValidCount = 0
|
||||||
}
|
}
|
||||||
@ -186,14 +165,14 @@ class LoginActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
if (isWithLogin || isWithHTTPLogin) {
|
if (isWithLogin || isWithHTTPLogin) {
|
||||||
if (TextUtils.isEmpty(password)) {
|
if (TextUtils.isEmpty(password)) {
|
||||||
mPasswordView.error = getString(R.string.error_invalid_password)
|
passwordView.error = getString(R.string.error_invalid_password)
|
||||||
focusView = mPasswordView
|
focusView = passwordView
|
||||||
cancel = true
|
cancel = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TextUtils.isEmpty(login)) {
|
if (TextUtils.isEmpty(login)) {
|
||||||
mLoginView.error = getString(R.string.error_field_required)
|
loginView.error = getString(R.string.error_field_required)
|
||||||
focusView = mLoginView
|
focusView = loginView
|
||||||
cancel = true
|
cancel = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -211,7 +190,12 @@ class LoginActivity : AppCompatActivity() {
|
|||||||
editor.putBoolean("isSelfSignedCert", isWithSelfSignedCert)
|
editor.putBoolean("isSelfSignedCert", isWithSelfSignedCert)
|
||||||
editor.apply()
|
editor.apply()
|
||||||
|
|
||||||
val api = SelfossApi(this, this@LoginActivity, isWithSelfSignedCert, isWithSelfSignedCert)
|
val api = SelfossApi(
|
||||||
|
this,
|
||||||
|
this@LoginActivity,
|
||||||
|
isWithSelfSignedCert,
|
||||||
|
isWithSelfSignedCert
|
||||||
|
)
|
||||||
api.login().enqueue(object : Callback<SuccessResponse> {
|
api.login().enqueue(object : Callback<SuccessResponse> {
|
||||||
private fun preferenceError(t: Throwable) {
|
private fun preferenceError(t: Throwable) {
|
||||||
editor.remove("url")
|
editor.remove("url")
|
||||||
@ -220,23 +204,30 @@ class LoginActivity : AppCompatActivity() {
|
|||||||
editor.remove("password")
|
editor.remove("password")
|
||||||
editor.remove("httpPassword")
|
editor.remove("httpPassword")
|
||||||
editor.apply()
|
editor.apply()
|
||||||
mUrlView.error = getString(R.string.wrong_infos)
|
urlView.error = getString(R.string.wrong_infos)
|
||||||
mLoginView.error = getString(R.string.wrong_infos)
|
loginView.error = getString(R.string.wrong_infos)
|
||||||
mPasswordView.error = getString(R.string.wrong_infos)
|
passwordView.error = getString(R.string.wrong_infos)
|
||||||
mHTTPLoginView.error = getString(R.string.wrong_infos)
|
httpLoginView.error = getString(R.string.wrong_infos)
|
||||||
mHTTPPasswordView.error = getString(R.string.wrong_infos)
|
httpPasswordView.error = getString(R.string.wrong_infos)
|
||||||
if (logErrors) {
|
if (logErrors) {
|
||||||
Crashlytics.setUserIdentifier(userIdentifier)
|
Crashlytics.setUserIdentifier(userIdentifier)
|
||||||
Crashlytics.log(100, "LOGIN_DEBUG_ERRROR", t.message)
|
Crashlytics.log(100, "LOGIN_DEBUG_ERRROR", t.message)
|
||||||
Crashlytics.logException(t)
|
Crashlytics.logException(t)
|
||||||
Toast.makeText(this@LoginActivity, t.message, Toast.LENGTH_LONG).show()
|
Toast.makeText(
|
||||||
|
this@LoginActivity,
|
||||||
|
t.message,
|
||||||
|
Toast.LENGTH_LONG
|
||||||
|
).show()
|
||||||
}
|
}
|
||||||
showProgress(false)
|
showProgress(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResponse(call: Call<SuccessResponse>, response: Response<SuccessResponse>) {
|
override fun onResponse(
|
||||||
|
call: Call<SuccessResponse>,
|
||||||
|
response: Response<SuccessResponse>
|
||||||
|
) {
|
||||||
if (response.body() != null && response.body()!!.isSuccess) {
|
if (response.body() != null && response.body()!!.isSuccess) {
|
||||||
mFirebaseAnalytics.logEvent(FirebaseAnalytics.Event.LOGIN, Bundle())
|
firebaseAnalytics.logEvent(FirebaseAnalytics.Event.LOGIN, Bundle())
|
||||||
goToMain()
|
goToMain()
|
||||||
} else {
|
} else {
|
||||||
preferenceError(Exception("No response body..."))
|
preferenceError(Exception("No response body..."))
|
||||||
@ -250,40 +241,39 @@ class LoginActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Shows the progress UI and hides the login form.
|
|
||||||
*/
|
|
||||||
private fun showProgress(show: Boolean) {
|
private fun showProgress(show: Boolean) {
|
||||||
val shortAnimTime = resources.getInteger(android.R.integer.config_shortAnimTime)
|
val shortAnimTime = resources.getInteger(android.R.integer.config_shortAnimTime)
|
||||||
|
|
||||||
mLoginFormView.visibility = if (show) View.GONE else View.VISIBLE
|
loginForm.visibility = if (show) View.GONE else View.VISIBLE
|
||||||
mLoginFormView
|
loginForm
|
||||||
.animate()
|
.animate()
|
||||||
.setDuration(shortAnimTime.toLong())
|
.setDuration(shortAnimTime.toLong())
|
||||||
.alpha(
|
.alpha(
|
||||||
if (show) 0F else 1F
|
if (show) 0F else 1F
|
||||||
).setListener(object : AnimatorListenerAdapter() {
|
).setListener(object : AnimatorListenerAdapter() {
|
||||||
override fun onAnimationEnd(animation: Animator) {
|
override fun onAnimationEnd(animation: Animator) {
|
||||||
mLoginFormView.visibility = if (show) View.GONE else View.VISIBLE
|
loginForm.visibility = if (show) View.GONE else View.VISIBLE
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
)
|
||||||
|
|
||||||
mProgressView.visibility = if (show) View.VISIBLE else View.GONE
|
loginProgress.visibility = if (show) View.VISIBLE else View.GONE
|
||||||
mProgressView
|
loginProgress
|
||||||
.animate()
|
.animate()
|
||||||
.setDuration(shortAnimTime.toLong())
|
.setDuration(shortAnimTime.toLong())
|
||||||
.alpha(
|
.alpha(
|
||||||
if (show) 1F else 0F
|
if (show) 1F else 0F
|
||||||
).setListener(object : AnimatorListenerAdapter() {
|
).setListener(object : AnimatorListenerAdapter() {
|
||||||
override fun onAnimationEnd(animation: Animator) {
|
override fun onAnimationEnd(animation: Animator) {
|
||||||
mProgressView.visibility = if (show) View.VISIBLE else View.GONE
|
loginProgress.visibility = if (show) View.VISIBLE else View.GONE
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||||
menuInflater.inflate(R.menu.login_menu, menu)
|
menuInflater.inflate(R.menu.login_menu, menu)
|
||||||
menu.findItem(R.id.loging_debug).isChecked = logErrors
|
menu.findItem(R.id.login_debug).isChecked = logErrors
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -291,17 +281,17 @@ class LoginActivity : AppCompatActivity() {
|
|||||||
when (item.itemId) {
|
when (item.itemId) {
|
||||||
R.id.about -> {
|
R.id.about -> {
|
||||||
LibsBuilder()
|
LibsBuilder()
|
||||||
.withActivityStyle(Libs.ActivityStyle.LIGHT_DARK_TOOLBAR)
|
.withActivityStyle(Libs.ActivityStyle.LIGHT_DARK_TOOLBAR)
|
||||||
.withAboutIconShown(true)
|
.withAboutIconShown(true)
|
||||||
.withAboutVersionShown(true)
|
.withAboutVersionShown(true)
|
||||||
.start(this)
|
.start(this)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
R.id.loging_debug -> {
|
R.id.login_debug -> {
|
||||||
val newState = !item.isChecked
|
val newState = !item.isChecked
|
||||||
item.isChecked = newState
|
item.isChecked = newState
|
||||||
logErrors = newState
|
logErrors = newState
|
||||||
editor.putBoolean("loging_debug", newState)
|
editor.putBoolean("login_debug", newState)
|
||||||
editor.apply()
|
editor.apply()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -5,15 +5,16 @@ import android.os.Bundle
|
|||||||
import android.preference.PreferenceManager
|
import android.preference.PreferenceManager
|
||||||
import android.support.v7.app.AppCompatActivity
|
import android.support.v7.app.AppCompatActivity
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class MainActivity : AppCompatActivity() {
|
class MainActivity : AppCompatActivity() {
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(R.layout.activity_main)
|
setContentView(R.layout.activity_main)
|
||||||
|
|
||||||
if (PreferenceManager.getDefaultSharedPreferences(baseContext).getBoolean("firstStart", true)) {
|
if (PreferenceManager.getDefaultSharedPreferences(baseContext).getBoolean(
|
||||||
|
"firstStart",
|
||||||
|
true
|
||||||
|
)) {
|
||||||
val i = Intent(this@MainActivity, IntroActivity::class.java)
|
val i = Intent(this@MainActivity, IntroActivity::class.java)
|
||||||
startActivity(i)
|
startActivity(i)
|
||||||
} else {
|
} else {
|
||||||
@ -22,6 +23,5 @@ class MainActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
finish()
|
finish()
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,9 +21,6 @@ import io.fabric.sdk.android.Fabric
|
|||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.util.UUID.randomUUID
|
import java.util.UUID.randomUUID
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class MyApp : MultiDexApplication() {
|
class MyApp : MultiDexApplication() {
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
@ -46,14 +43,13 @@ class MyApp : MultiDexApplication() {
|
|||||||
initTheme()
|
initTheme()
|
||||||
|
|
||||||
tryToHandleBug()
|
tryToHandleBug()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initAmplify() {
|
private fun initAmplify() {
|
||||||
Amplify.initSharedInstance(this)
|
Amplify.initSharedInstance(this)
|
||||||
.setPositiveFeedbackCollectors(GooglePlayStoreFeedbackCollector())
|
.setPositiveFeedbackCollectors(GooglePlayStoreFeedbackCollector())
|
||||||
.setCriticalFeedbackCollectors(DefaultEmailFeedbackCollector(BuildConfig.FEEDBACK_EMAIL))
|
.setCriticalFeedbackCollectors(DefaultEmailFeedbackCollector(BuildConfig.FEEDBACK_EMAIL))
|
||||||
.applyAllDefaultRules()
|
.applyAllDefaultRules()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initCache() {
|
private fun initCache() {
|
||||||
@ -66,12 +62,16 @@ class MyApp : MultiDexApplication() {
|
|||||||
|
|
||||||
private fun initDrawerImageLoader() {
|
private fun initDrawerImageLoader() {
|
||||||
DrawerImageLoader.init(object : AbstractDrawerImageLoader() {
|
DrawerImageLoader.init(object : AbstractDrawerImageLoader() {
|
||||||
override fun set(imageView: ImageView?, uri: Uri?, placeholder: Drawable?, tag: String?) {
|
override fun set(
|
||||||
|
imageView: ImageView?,
|
||||||
|
uri: Uri?,
|
||||||
|
placeholder: Drawable?,
|
||||||
|
tag: String?
|
||||||
|
) {
|
||||||
Glide.with(imageView?.context)
|
Glide.with(imageView?.context)
|
||||||
.load(uri)
|
.load(uri)
|
||||||
.apply(RequestOptions.fitCenterTransform()
|
.apply(RequestOptions.fitCenterTransform().placeholder(placeholder))
|
||||||
.placeholder(placeholder))
|
.into(imageView)
|
||||||
.into(imageView)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun cancel(imageView: ImageView?) {
|
override fun cancel(imageView: ImageView?) {
|
||||||
@ -86,33 +86,35 @@ class MyApp : MultiDexApplication() {
|
|||||||
|
|
||||||
private fun initTheme() {
|
private fun initTheme() {
|
||||||
Scoop.waffleCone()
|
Scoop.waffleCone()
|
||||||
.addFlavor(getString(R.string.default_theme), R.style.NoBar, true)
|
.addFlavor(getString(R.string.default_theme), R.style.NoBar, true)
|
||||||
.addFlavor(getString(R.string.default_dark_theme), R.style.NoBarDark)
|
.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_theme), R.style.NoBarTealOrange)
|
||||||
.addFlavor(getString(R.string.teal_orange_dark_theme), R.style.NoBarTealOrangeDark)
|
.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_theme), R.style.NoBarCyanPink)
|
||||||
.addFlavor(getString(R.string.cyan_pink_dark_theme), R.style.NoBarCyanPinkDark)
|
.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_theme), R.style.NoBarGreyOrange)
|
||||||
.addFlavor(getString(R.string.grey_orange_dark_theme), R.style.NoBarGreyOrangeDark)
|
.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_theme), R.style.NoBarBlueAmber)
|
||||||
.addFlavor(getString(R.string.blue_amber_dark_theme), R.style.NoBarBlueAmberDark)
|
.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_theme), R.style.NoBarIndigoPink)
|
||||||
.addFlavor(getString(R.string.indigo_pink_dark_theme), R.style.NoBarIndigoPinkDark)
|
.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_theme), R.style.NoBarRedTeal)
|
||||||
.addFlavor(getString(R.string.red_teal_dark_theme), R.style.NoBarRedTealDark)
|
.addFlavor(getString(R.string.red_teal_dark_theme), R.style.NoBarRedTealDark)
|
||||||
.setSharedPreferences(PreferenceManager.getDefaultSharedPreferences(this))
|
.setSharedPreferences(PreferenceManager.getDefaultSharedPreferences(this))
|
||||||
.initialize()
|
.initialize()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun tryToHandleBug() {
|
private fun tryToHandleBug() {
|
||||||
val oldHandler = Thread.getDefaultUncaughtExceptionHandler()
|
val oldHandler = Thread.getDefaultUncaughtExceptionHandler()
|
||||||
|
|
||||||
Thread.setDefaultUncaughtExceptionHandler { thread, e ->
|
Thread.setDefaultUncaughtExceptionHandler { thread, e ->
|
||||||
if (e is java.lang.NoClassDefFoundError && e.stackTrace.asList().any { it.toString().contains("android.view.ViewDebug") })
|
if (e is java.lang.NoClassDefFoundError && e.stackTrace.asList().any {
|
||||||
|
it.toString().contains("android.view.ViewDebug")
|
||||||
|
}) {
|
||||||
Unit
|
Unit
|
||||||
else
|
} else {
|
||||||
oldHandler.uncaughtException(thread, e)
|
oldHandler.uncaughtException(thread, e)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,116 +1,133 @@
|
|||||||
package apps.amine.bou.readerforselfoss
|
package apps.amine.bou.readerforselfoss
|
||||||
|
|
||||||
import android.content.Intent
|
import android.content.Context
|
||||||
import android.net.Uri
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.preference.PreferenceManager
|
||||||
import android.view.View
|
import android.support.v4.app.FragmentManager
|
||||||
import android.view.ViewGroup
|
import android.support.v4.app.FragmentStatePagerAdapter
|
||||||
import android.widget.ImageButton
|
import android.support.v4.view.ViewPager
|
||||||
import android.widget.ImageView
|
import android.support.v7.app.AppCompatActivity
|
||||||
import android.widget.TextView
|
import android.view.MenuItem
|
||||||
|
import apps.amine.bou.readerforselfoss.api.selfoss.Item
|
||||||
import com.bumptech.glide.Glide
|
import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi
|
||||||
import org.sufficientlysecure.htmltextview.HtmlHttpImageGetter
|
import apps.amine.bou.readerforselfoss.api.selfoss.SuccessResponse
|
||||||
import org.sufficientlysecure.htmltextview.HtmlTextView
|
import apps.amine.bou.readerforselfoss.fragments.ArticleFragment
|
||||||
|
import apps.amine.bou.readerforselfoss.transformers.DepthPageTransformer
|
||||||
|
import apps.amine.bou.readerforselfoss.utils.Config
|
||||||
|
import apps.amine.bou.readerforselfoss.utils.succeeded
|
||||||
|
import com.crashlytics.android.Crashlytics
|
||||||
|
import com.ftinc.scoop.Scoop
|
||||||
|
import kotlinx.android.synthetic.main.activity_reader.*
|
||||||
|
import me.relex.circleindicator.CircleIndicator
|
||||||
import retrofit2.Call
|
import retrofit2.Call
|
||||||
import retrofit2.Callback
|
import retrofit2.Callback
|
||||||
import retrofit2.Response
|
import retrofit2.Response
|
||||||
import xyz.klinker.android.drag_dismiss.activity.DragDismissActivity
|
|
||||||
|
|
||||||
import apps.amine.bou.readerforselfoss.api.mercury.MercuryApi
|
class ReaderActivity : AppCompatActivity() {
|
||||||
import apps.amine.bou.readerforselfoss.api.mercury.ParsedContent
|
|
||||||
import apps.amine.bou.readerforselfoss.utils.buildCustomTabsIntent
|
|
||||||
import apps.amine.bou.readerforselfoss.utils.customtabs.CustomTabActivityHelper
|
|
||||||
import apps.amine.bou.readerforselfoss.utils.openItemUrl
|
|
||||||
import apps.amine.bou.readerforselfoss.utils.shareLink
|
|
||||||
import com.bumptech.glide.request.RequestOptions
|
|
||||||
import com.ftinc.scoop.Scoop
|
|
||||||
|
|
||||||
|
private lateinit var allItems: ArrayList<Item>
|
||||||
|
|
||||||
class ReaderActivity : DragDismissActivity() {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
private lateinit var mCustomTabActivityHelper: CustomTabActivityHelper
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
override fun onStart() {
|
|
||||||
super.onStart()
|
|
||||||
mCustomTabActivityHelper.bindCustomTabsService(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onStop() {
|
|
||||||
super.onStop()
|
|
||||||
mCustomTabActivityHelper.unbindCustomTabsService(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateContent(inflater: LayoutInflater, parent: ViewGroup, savedInstanceState: Bundle?): View {
|
|
||||||
Scoop.getInstance().apply(this)
|
Scoop.getInstance().apply(this)
|
||||||
val v = inflater.inflate(R.layout.activity_reader, parent, false)
|
setContentView(R.layout.activity_reader)
|
||||||
showProgressBar()
|
|
||||||
|
|
||||||
val image: ImageView = v.findViewById(R.id.imageView)
|
setSupportActionBar(toolBar)
|
||||||
val source: TextView = v.findViewById(R.id.source)
|
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||||
val title: TextView = v.findViewById(R.id.title)
|
supportActionBar?.setDisplayShowHomeEnabled(true)
|
||||||
val content: HtmlTextView = v.findViewById(R.id.content)
|
|
||||||
val url = intent.getStringExtra("url")
|
|
||||||
val parser = MercuryApi(BuildConfig.MERCURY_KEY)
|
|
||||||
val browserBtn: ImageButton = v.findViewById(R.id.browserBtn)
|
|
||||||
val shareBtn: ImageButton = v.findViewById(R.id.shareBtn)
|
|
||||||
|
|
||||||
|
val settings = getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE)
|
||||||
|
val sharedPref = PreferenceManager.getDefaultSharedPreferences(this)
|
||||||
|
|
||||||
val customTabsIntent = this@ReaderActivity.buildCustomTabsIntent()
|
val debugReadingItems = sharedPref.getBoolean("read_debug", false)
|
||||||
mCustomTabActivityHelper = CustomTabActivityHelper()
|
val userIdentifier = sharedPref.getString("unique_id", "")
|
||||||
mCustomTabActivityHelper.bindCustomTabsService(this)
|
val markOnScroll = sharedPref.getBoolean("mark_on_scroll", false)
|
||||||
|
|
||||||
|
val api = SelfossApi(
|
||||||
|
this,
|
||||||
|
this@ReaderActivity,
|
||||||
|
settings.getBoolean("isSelfSignedCert", false),
|
||||||
|
sharedPref.getBoolean("should_log_everything", false)
|
||||||
|
)
|
||||||
|
|
||||||
parser.parseUrl(url).enqueue(object : Callback<ParsedContent> {
|
allItems = intent.getParcelableArrayListExtra<Item>("allItems")
|
||||||
override fun onResponse(call: Call<ParsedContent>, response: Response<ParsedContent>) {
|
val currentItem = intent.getIntExtra("currentItem", 0)
|
||||||
if (response.body() != null && response.body()!!.content != null && response.body()!!.content.isNotEmpty()) {
|
|
||||||
source.text = response.body()!!.domain
|
var adapter = ScreenSlidePagerAdapter(supportFragmentManager)
|
||||||
title.text = response.body()!!.title
|
pager.adapter = adapter
|
||||||
if (response.body()!!.content != null && !response.body()!!.content.isEmpty()) {
|
pager.currentItem = currentItem
|
||||||
try {
|
|
||||||
content.setHtml(response.body()!!.content, HtmlHttpImageGetter(content, null, true))
|
pager.setPageTransformer(true, DepthPageTransformer())
|
||||||
} catch (e: IndexOutOfBoundsException) {
|
(indicator as CircleIndicator).setViewPager(pager)
|
||||||
openInBrowserAfterFailing()
|
|
||||||
}
|
if (markOnScroll) {
|
||||||
|
pager.addOnPageChangeListener(object : ViewPager.SimpleOnPageChangeListener() {
|
||||||
|
var isLastItem = false
|
||||||
|
|
||||||
|
override fun onPageSelected(position: Int) {
|
||||||
|
isLastItem = (position === (allItems.size - 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPageScrollStateChanged(state: Int) {
|
||||||
|
if (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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
if (response.body()!!.lead_image_url != null && !response.body()!!.lead_image_url.isEmpty())
|
}
|
||||||
Glide
|
})
|
||||||
.with(baseContext)
|
}
|
||||||
.asBitmap()
|
}
|
||||||
.load(response.body()!!.lead_image_url)
|
|
||||||
.apply(RequestOptions.fitCenterTransform())
|
|
||||||
.into(image)
|
|
||||||
|
|
||||||
shareBtn.setOnClickListener {
|
override fun onPause() {
|
||||||
this@ReaderActivity.shareLink(response.body()!!.url)
|
super.onPause()
|
||||||
}
|
pager.clearOnPageChangeListeners()
|
||||||
|
}
|
||||||
|
|
||||||
browserBtn.setOnClickListener {
|
private inner class ScreenSlidePagerAdapter(fm: FragmentManager) : FragmentStatePagerAdapter(fm) {
|
||||||
this@ReaderActivity.openItemUrl(
|
override fun getCount(): Int {
|
||||||
response.body()!!.url,
|
return allItems.size
|
||||||
customTabsIntent,
|
}
|
||||||
false,
|
|
||||||
false,
|
|
||||||
this@ReaderActivity)
|
|
||||||
}
|
|
||||||
|
|
||||||
hideProgressBar()
|
override fun getItem(position: Int): ArticleFragment {
|
||||||
} else openInBrowserAfterFailing()
|
return ArticleFragment.newInstance(position, allItems)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
|
when (item.itemId) {
|
||||||
|
android.R.id.home -> {
|
||||||
|
onBackPressed()
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
}
|
||||||
override fun onFailure(call: Call<ParsedContent>, t: Throwable) = openInBrowserAfterFailing()
|
return super.onOptionsItemSelected(item)
|
||||||
|
|
||||||
private fun openInBrowserAfterFailing() {
|
|
||||||
this@ReaderActivity.openItemUrl(
|
|
||||||
url,
|
|
||||||
customTabsIntent,
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
this@ReaderActivity
|
|
||||||
)
|
|
||||||
finish()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return v
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,20 +5,15 @@ import android.os.Bundle
|
|||||||
import android.preference.PreferenceManager
|
import android.preference.PreferenceManager
|
||||||
import android.support.v7.app.AppCompatActivity
|
import android.support.v7.app.AppCompatActivity
|
||||||
import android.support.v7.widget.LinearLayoutManager
|
import android.support.v7.widget.LinearLayoutManager
|
||||||
import android.support.v7.widget.RecyclerView
|
|
||||||
import android.support.v7.widget.Toolbar
|
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
|
|
||||||
import com.melnykov.fab.FloatingActionButton
|
|
||||||
import retrofit2.Call
|
|
||||||
import retrofit2.Callback
|
|
||||||
import retrofit2.Response
|
|
||||||
|
|
||||||
import apps.amine.bou.readerforselfoss.adapters.SourcesListAdapter
|
import apps.amine.bou.readerforselfoss.adapters.SourcesListAdapter
|
||||||
import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi
|
import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi
|
||||||
import apps.amine.bou.readerforselfoss.api.selfoss.Sources
|
import apps.amine.bou.readerforselfoss.api.selfoss.Sources
|
||||||
import com.ftinc.scoop.Scoop
|
import com.ftinc.scoop.Scoop
|
||||||
|
import kotlinx.android.synthetic.main.activity_sources.*
|
||||||
|
import retrofit2.Call
|
||||||
|
import retrofit2.Callback
|
||||||
|
import retrofit2.Response
|
||||||
|
|
||||||
class SourcesActivity : AppCompatActivity() {
|
class SourcesActivity : AppCompatActivity() {
|
||||||
|
|
||||||
@ -26,44 +21,64 @@ class SourcesActivity : AppCompatActivity() {
|
|||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
Scoop.getInstance().apply(this)
|
Scoop.getInstance().apply(this)
|
||||||
setContentView(R.layout.activity_sources)
|
setContentView(R.layout.activity_sources)
|
||||||
val toolbar: Toolbar = findViewById(R.id.toolbar)
|
|
||||||
setSupportActionBar(toolbar)
|
setSupportActionBar(toolbar)
|
||||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||||
supportActionBar?.setDisplayShowHomeEnabled(true)
|
supportActionBar?.setDisplayShowHomeEnabled(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onStop() {
|
||||||
|
super.onStop()
|
||||||
|
recyclerView.clearOnScrollListeners()
|
||||||
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
val mFab: FloatingActionButton = findViewById(R.id.fab)
|
|
||||||
val mRecyclerView: RecyclerView = findViewById(R.id.activity_sources)
|
|
||||||
val mLayoutManager = LinearLayoutManager(this)
|
val mLayoutManager = LinearLayoutManager(this)
|
||||||
|
|
||||||
val prefs = PreferenceManager.getDefaultSharedPreferences(this)
|
val prefs = PreferenceManager.getDefaultSharedPreferences(this)
|
||||||
|
|
||||||
val api = SelfossApi(this, this@SourcesActivity, prefs.getBoolean("isSelfSignedCert", false), prefs.getBoolean("should_log_everything", false))
|
val api = SelfossApi(
|
||||||
|
this,
|
||||||
|
this@SourcesActivity,
|
||||||
|
prefs.getBoolean("isSelfSignedCert", false),
|
||||||
|
prefs.getBoolean("should_log_everything", false)
|
||||||
|
)
|
||||||
var items: ArrayList<Sources> = ArrayList()
|
var items: ArrayList<Sources> = ArrayList()
|
||||||
|
|
||||||
mFab.attachToRecyclerView(mRecyclerView)
|
recyclerView.setHasFixedSize(true)
|
||||||
mRecyclerView.setHasFixedSize(true)
|
recyclerView.layoutManager = mLayoutManager
|
||||||
mRecyclerView.layoutManager = mLayoutManager
|
|
||||||
|
|
||||||
api.sources.enqueue(object : Callback<List<Sources>> {
|
api.sources.enqueue(object : Callback<List<Sources>> {
|
||||||
override fun onResponse(call: Call<List<Sources>>, response: Response<List<Sources>>) {
|
override fun onResponse(
|
||||||
|
call: Call<List<Sources>>,
|
||||||
|
response: Response<List<Sources>>
|
||||||
|
) {
|
||||||
if (response.body() != null && response.body()!!.isNotEmpty()) {
|
if (response.body() != null && response.body()!!.isNotEmpty()) {
|
||||||
items = response.body() as ArrayList<Sources>
|
items = response.body() as ArrayList<Sources>
|
||||||
}
|
}
|
||||||
val mAdapter = SourcesListAdapter(this@SourcesActivity, items, api)
|
val mAdapter = SourcesListAdapter(this@SourcesActivity, items, api)
|
||||||
mRecyclerView.adapter = mAdapter
|
recyclerView.adapter = mAdapter
|
||||||
mAdapter.notifyDataSetChanged()
|
mAdapter.notifyDataSetChanged()
|
||||||
if (items.isEmpty()) Toast.makeText(this@SourcesActivity, R.string.nothing_here, Toast.LENGTH_SHORT).show()
|
if (items.isEmpty()) {
|
||||||
|
Toast.makeText(
|
||||||
|
this@SourcesActivity,
|
||||||
|
R.string.nothing_here,
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onFailure(call: Call<List<Sources>>, t: Throwable) {
|
override fun onFailure(call: Call<List<Sources>>, t: Throwable) {
|
||||||
Toast.makeText(this@SourcesActivity, R.string.cant_get_sources, Toast.LENGTH_SHORT).show()
|
Toast.makeText(
|
||||||
|
this@SourcesActivity,
|
||||||
|
R.string.cant_get_sources,
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
mFab.setOnClickListener {
|
fab.setOnClickListener {
|
||||||
startActivity(Intent(this@SourcesActivity, AddSourceActivity::class.java))
|
startActivity(Intent(this@SourcesActivity, AddSourceActivity::class.java))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,56 +3,60 @@ package apps.amine.bou.readerforselfoss.adapters
|
|||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.support.constraint.ConstraintLayout
|
|
||||||
import android.support.design.widget.Snackbar
|
import android.support.design.widget.Snackbar
|
||||||
import android.support.v7.widget.CardView
|
import android.support.v7.widget.CardView
|
||||||
import android.support.v7.widget.RecyclerView
|
import android.support.v7.widget.RecyclerView
|
||||||
import android.text.Html
|
import android.text.Html
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.ImageButton
|
|
||||||
import android.widget.ImageView
|
|
||||||
import android.widget.ImageView.ScaleType
|
import android.widget.ImageView.ScaleType
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
|
|
||||||
import com.amulyakhare.textdrawable.TextDrawable
|
|
||||||
import com.amulyakhare.textdrawable.util.ColorGenerator
|
|
||||||
import com.bumptech.glide.Glide
|
|
||||||
import com.like.LikeButton
|
|
||||||
import com.like.OnLikeListener
|
|
||||||
import retrofit2.Call
|
|
||||||
import retrofit2.Callback
|
|
||||||
import retrofit2.Response
|
|
||||||
|
|
||||||
import apps.amine.bou.readerforselfoss.R
|
import apps.amine.bou.readerforselfoss.R
|
||||||
import apps.amine.bou.readerforselfoss.api.selfoss.Item
|
import apps.amine.bou.readerforselfoss.api.selfoss.Item
|
||||||
import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi
|
import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi
|
||||||
import apps.amine.bou.readerforselfoss.api.selfoss.SuccessResponse
|
import apps.amine.bou.readerforselfoss.api.selfoss.SuccessResponse
|
||||||
import apps.amine.bou.readerforselfoss.themes.AppColors
|
import apps.amine.bou.readerforselfoss.themes.AppColors
|
||||||
import apps.amine.bou.readerforselfoss.utils.*
|
import apps.amine.bou.readerforselfoss.utils.buildCustomTabsIntent
|
||||||
import apps.amine.bou.readerforselfoss.utils.customtabs.CustomTabActivityHelper
|
import apps.amine.bou.readerforselfoss.utils.customtabs.CustomTabActivityHelper
|
||||||
import apps.amine.bou.readerforselfoss.utils.glide.bitmapCenterCrop
|
import apps.amine.bou.readerforselfoss.utils.glide.bitmapCenterCrop
|
||||||
import apps.amine.bou.readerforselfoss.utils.glide.bitmapFitCenter
|
|
||||||
import apps.amine.bou.readerforselfoss.utils.glide.circularBitmapDrawable
|
import apps.amine.bou.readerforselfoss.utils.glide.circularBitmapDrawable
|
||||||
|
import apps.amine.bou.readerforselfoss.utils.openInBrowserAsNewTask
|
||||||
|
import apps.amine.bou.readerforselfoss.utils.openItemUrl
|
||||||
|
import apps.amine.bou.readerforselfoss.utils.shareLink
|
||||||
|
import apps.amine.bou.readerforselfoss.utils.sourceAndDateText
|
||||||
|
import apps.amine.bou.readerforselfoss.utils.succeeded
|
||||||
|
import apps.amine.bou.readerforselfoss.utils.toTextDrawableString
|
||||||
|
import com.amulyakhare.textdrawable.TextDrawable
|
||||||
|
import com.amulyakhare.textdrawable.util.ColorGenerator
|
||||||
|
import com.bumptech.glide.Glide
|
||||||
import com.crashlytics.android.Crashlytics
|
import com.crashlytics.android.Crashlytics
|
||||||
import kotlin.collections.ArrayList
|
import com.like.LikeButton
|
||||||
|
import com.like.OnLikeListener
|
||||||
|
import kotlinx.android.synthetic.main.card_item.view.*
|
||||||
|
import retrofit2.Call
|
||||||
|
import retrofit2.Callback
|
||||||
|
import retrofit2.Response
|
||||||
|
|
||||||
class ItemCardAdapter(private val app: Activity,
|
class ItemCardAdapter(
|
||||||
private val items: ArrayList<Item>,
|
private val app: Activity,
|
||||||
private val api: SelfossApi,
|
private val items: ArrayList<Item>,
|
||||||
private val helper: CustomTabActivityHelper,
|
private val api: SelfossApi,
|
||||||
private val internalBrowser: Boolean,
|
private val helper: CustomTabActivityHelper,
|
||||||
private val articleViewer: Boolean,
|
private val internalBrowser: Boolean,
|
||||||
private val fullHeightCards: Boolean,
|
private val articleViewer: Boolean,
|
||||||
private val appColors: AppColors,
|
private val fullHeightCards: Boolean,
|
||||||
val debugReadingItems: Boolean,
|
private val appColors: AppColors,
|
||||||
val userIdentifier: String) : RecyclerView.Adapter<ItemCardAdapter.ViewHolder>() {
|
val debugReadingItems: Boolean,
|
||||||
|
val userIdentifier: String
|
||||||
|
) : RecyclerView.Adapter<ItemCardAdapter.ViewHolder>() {
|
||||||
private val c: Context = app.baseContext
|
private val c: Context = app.baseContext
|
||||||
private val generator: ColorGenerator = ColorGenerator.MATERIAL
|
private val generator: ColorGenerator = ColorGenerator.MATERIAL
|
||||||
|
private val imageMaxHeight: Int = c.resources.getDimension(R.dimen.card_image_max_height).toInt()
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||||
val v = LayoutInflater.from(c).inflate(R.layout.card_item, parent, false) as ConstraintLayout
|
val v = LayoutInflater.from(c).inflate(R.layout.card_item, parent, false) as CardView
|
||||||
return ViewHolder(v)
|
return ViewHolder(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,37 +64,39 @@ class ItemCardAdapter(private val app: Activity,
|
|||||||
val itm = items[position]
|
val itm = items[position]
|
||||||
|
|
||||||
|
|
||||||
holder.saveBtn.isLiked = itm.starred
|
holder.mView.favButton.isLiked = itm.starred
|
||||||
holder.title.text = Html.fromHtml(itm.title)
|
holder.mView.title.text = Html.fromHtml(itm.title)
|
||||||
|
|
||||||
holder.sourceTitleAndDate.text = itm.sourceAndDateText()
|
holder.mView.sourceTitleAndDate.text = itm.sourceAndDateText()
|
||||||
|
|
||||||
if (itm.getThumbnail(c).isEmpty()) {
|
if (!fullHeightCards) {
|
||||||
Glide.with(c).clear(holder.itemImage)
|
holder.mView.itemImage.maxHeight = imageMaxHeight
|
||||||
holder.itemImage.setImageDrawable(null)
|
holder.mView.itemImage.scaleType = ScaleType.CENTER_CROP
|
||||||
} else {
|
}
|
||||||
if (fullHeightCards) {
|
|
||||||
c.bitmapFitCenter(itm.getThumbnail(c), holder.itemImage)
|
if (itm.getThumbnail(c).isEmpty()) {
|
||||||
} else {
|
holder.mView.itemImage.visibility = View.GONE
|
||||||
c.bitmapCenterCrop(itm.getThumbnail(c), holder.itemImage)
|
Glide.with(c).clear(holder.mView.itemImage)
|
||||||
}
|
holder.mView.itemImage.setImageDrawable(null)
|
||||||
|
} else {
|
||||||
|
holder.mView.itemImage.visibility = View.VISIBLE
|
||||||
|
c.bitmapCenterCrop(itm.getThumbnail(c), holder.mView.itemImage)
|
||||||
}
|
}
|
||||||
|
|
||||||
val fHolder = holder
|
|
||||||
if (itm.getIcon(c).isEmpty()) {
|
if (itm.getIcon(c).isEmpty()) {
|
||||||
val color = generator.getColor(itm.sourcetitle)
|
val color = generator.getColor(itm.sourcetitle)
|
||||||
|
|
||||||
val drawable =
|
val drawable =
|
||||||
TextDrawable
|
TextDrawable
|
||||||
.builder()
|
.builder()
|
||||||
.round()
|
.round()
|
||||||
.build(itm.sourcetitle.toTextDrawableString(), color)
|
.build(itm.sourcetitle.toTextDrawableString(), color)
|
||||||
holder.sourceImage.setImageDrawable(drawable)
|
holder.mView.sourceImage.setImageDrawable(drawable)
|
||||||
} else {
|
} else {
|
||||||
c.circularBitmapDrawable(itm.getIcon(c), holder.sourceImage)
|
c.circularBitmapDrawable(itm.getIcon(c), holder.mView.sourceImage)
|
||||||
}
|
}
|
||||||
|
|
||||||
holder.saveBtn.isLiked = itm.starred
|
holder.mView.favButton.isLiked = itm.starred
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getItemCount(): Int {
|
override fun getItemCount(): Int {
|
||||||
@ -99,13 +105,21 @@ class ItemCardAdapter(private val app: Activity,
|
|||||||
|
|
||||||
private fun doUnmark(i: Item, position: Int) {
|
private fun doUnmark(i: Item, position: Int) {
|
||||||
val s = Snackbar
|
val s = Snackbar
|
||||||
.make(app.findViewById(R.id.coordLayout), R.string.marked_as_read, Snackbar.LENGTH_LONG)
|
.make(
|
||||||
|
app.findViewById(R.id.coordLayout),
|
||||||
|
R.string.marked_as_read,
|
||||||
|
Snackbar.LENGTH_LONG
|
||||||
|
)
|
||||||
.setAction(R.string.undo_string) {
|
.setAction(R.string.undo_string) {
|
||||||
items.add(position, i)
|
items.add(position, i)
|
||||||
notifyItemInserted(position)
|
notifyItemInserted(position)
|
||||||
|
|
||||||
api.unmarkItem(i.id).enqueue(object : Callback<SuccessResponse> {
|
api.unmarkItem(i.id).enqueue(object : Callback<SuccessResponse> {
|
||||||
override fun onResponse(call: Call<SuccessResponse>, response: Response<SuccessResponse>) {}
|
override fun onResponse(
|
||||||
|
call: Call<SuccessResponse>,
|
||||||
|
response: Response<SuccessResponse>
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
override fun onFailure(call: Call<SuccessResponse>, t: Throwable) {
|
override fun onFailure(call: Call<SuccessResponse>, t: Throwable) {
|
||||||
items.remove(i)
|
items.remove(i)
|
||||||
@ -129,16 +143,19 @@ class ItemCardAdapter(private val app: Activity,
|
|||||||
notifyItemRemoved(position)
|
notifyItemRemoved(position)
|
||||||
|
|
||||||
api.markItem(i.id).enqueue(object : Callback<SuccessResponse> {
|
api.markItem(i.id).enqueue(object : Callback<SuccessResponse> {
|
||||||
override fun onResponse(call: Call<SuccessResponse>, response: Response<SuccessResponse>) {
|
override fun onResponse(
|
||||||
if (debugReadingItems) {
|
call: Call<SuccessResponse>,
|
||||||
|
response: Response<SuccessResponse>
|
||||||
|
) {
|
||||||
|
if (!response.succeeded() && debugReadingItems) {
|
||||||
val message =
|
val message =
|
||||||
"message: ${response.message()} " +
|
"message: ${response.message()} " +
|
||||||
"response isSuccess: ${response.isSuccessful} " +
|
"response isSuccess: ${response.isSuccessful} " +
|
||||||
"response code: ${response.code()} " +
|
"response code: ${response.code()} " +
|
||||||
"response message: ${response.message()} " +
|
"response message: ${response.message()} " +
|
||||||
"response errorBody: ${response.errorBody()?.string()} " +
|
"response errorBody: ${response.errorBody()?.string()} " +
|
||||||
"body success: ${response.body()?.success} " +
|
"body success: ${response.body()?.success} " +
|
||||||
"body isSuccess: ${response.body()?.isSuccess}"
|
"body isSuccess: ${response.body()?.isSuccess}"
|
||||||
Crashlytics.setUserIdentifier(userIdentifier)
|
Crashlytics.setUserIdentifier(userIdentifier)
|
||||||
Crashlytics.log(100, "READ_DEBUG_SUCCESS", message)
|
Crashlytics.log(100, "READ_DEBUG_SUCCESS", message)
|
||||||
Crashlytics.logException(Exception("Was success, but did it work ?"))
|
Crashlytics.logException(Exception("Was success, but did it work ?"))
|
||||||
@ -155,52 +172,46 @@ class ItemCardAdapter(private val app: Activity,
|
|||||||
Crashlytics.logException(t)
|
Crashlytics.logException(t)
|
||||||
Toast.makeText(c, t.message, Toast.LENGTH_LONG).show()
|
Toast.makeText(c, t.message, Toast.LENGTH_LONG).show()
|
||||||
}
|
}
|
||||||
Toast.makeText(app, app.getString(R.string.cant_mark_read), Toast.LENGTH_SHORT).show()
|
Toast.makeText(
|
||||||
|
app,
|
||||||
|
app.getString(R.string.cant_mark_read),
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
items.add(i)
|
items.add(i)
|
||||||
notifyItemInserted(position)
|
notifyItemInserted(position)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inner class ViewHolder(val mView: ConstraintLayout) : RecyclerView.ViewHolder(mView) {
|
inner class ViewHolder(val mView: CardView) : RecyclerView.ViewHolder(mView) {
|
||||||
lateinit var saveBtn: LikeButton
|
|
||||||
lateinit var browserBtn: ImageButton
|
|
||||||
lateinit var shareBtn: ImageButton
|
|
||||||
lateinit var itemImage: ImageView
|
|
||||||
lateinit var sourceImage: ImageView
|
|
||||||
lateinit var title: TextView
|
|
||||||
lateinit var sourceTitleAndDate: TextView
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
(mView.findViewById<CardView>(R.id.card)).setCardBackgroundColor(appColors.cardBackground)
|
mView.setCardBackgroundColor(appColors.cardBackground)
|
||||||
handleClickListeners()
|
handleClickListeners()
|
||||||
handleCustomTabActions()
|
handleCustomTabActions()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleClickListeners() {
|
private fun handleClickListeners() {
|
||||||
sourceImage = mView.findViewById(R.id.sourceImage)
|
|
||||||
itemImage = mView.findViewById(R.id.itemImage)
|
|
||||||
title = mView.findViewById(R.id.title)
|
|
||||||
sourceTitleAndDate = mView.findViewById(R.id.sourceTitleAndDate)
|
|
||||||
saveBtn = mView.findViewById(R.id.favButton)
|
|
||||||
shareBtn = mView.findViewById(R.id.shareBtn)
|
|
||||||
browserBtn = mView.findViewById(R.id.browserBtn)
|
|
||||||
|
|
||||||
if (!fullHeightCards) {
|
mView.favButton.setOnLikeListener(object : OnLikeListener {
|
||||||
itemImage.maxHeight = c.resources.getDimension(R.dimen.card_image_max_height).toInt()
|
|
||||||
itemImage.scaleType = ScaleType.CENTER_CROP
|
|
||||||
}
|
|
||||||
|
|
||||||
saveBtn.setOnLikeListener(object : OnLikeListener {
|
|
||||||
override fun liked(likeButton: LikeButton) {
|
override fun liked(likeButton: LikeButton) {
|
||||||
val (id) = items[adapterPosition]
|
val (id) = items[adapterPosition]
|
||||||
api.starrItem(id).enqueue(object : Callback<SuccessResponse> {
|
api.starrItem(id).enqueue(object : Callback<SuccessResponse> {
|
||||||
override fun onResponse(call: Call<SuccessResponse>, response: Response<SuccessResponse>) {}
|
override fun onResponse(
|
||||||
|
call: Call<SuccessResponse>,
|
||||||
|
response: Response<SuccessResponse>
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
override fun onFailure(call: Call<SuccessResponse>, t: Throwable) {
|
override fun onFailure(
|
||||||
saveBtn.isLiked = false
|
call: Call<SuccessResponse>,
|
||||||
Toast.makeText(c, R.string.cant_mark_favortie, Toast.LENGTH_SHORT).show()
|
t: Throwable
|
||||||
|
) {
|
||||||
|
mView.favButton.isLiked = false
|
||||||
|
Toast.makeText(
|
||||||
|
c,
|
||||||
|
R.string.cant_mark_favortie,
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -208,22 +219,33 @@ class ItemCardAdapter(private val app: Activity,
|
|||||||
override fun unLiked(likeButton: LikeButton) {
|
override fun unLiked(likeButton: LikeButton) {
|
||||||
val (id) = items[adapterPosition]
|
val (id) = items[adapterPosition]
|
||||||
api.unstarrItem(id).enqueue(object : Callback<SuccessResponse> {
|
api.unstarrItem(id).enqueue(object : Callback<SuccessResponse> {
|
||||||
override fun onResponse(call: Call<SuccessResponse>, response: Response<SuccessResponse>) {}
|
override fun onResponse(
|
||||||
|
call: Call<SuccessResponse>,
|
||||||
|
response: Response<SuccessResponse>
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
override fun onFailure(call: Call<SuccessResponse>, t: Throwable) {
|
override fun onFailure(
|
||||||
saveBtn.isLiked = true
|
call: Call<SuccessResponse>,
|
||||||
Toast.makeText(c, R.string.cant_unmark_favortie, Toast.LENGTH_SHORT).show()
|
t: Throwable
|
||||||
|
) {
|
||||||
|
mView.favButton.isLiked = true
|
||||||
|
Toast.makeText(
|
||||||
|
c,
|
||||||
|
R.string.cant_unmark_favortie,
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
shareBtn.setOnClickListener {
|
mView.shareBtn.setOnClickListener {
|
||||||
c.shareLink(items[adapterPosition].getLinkDecoded())
|
c.shareLink(items[adapterPosition].getLinkDecoded())
|
||||||
}
|
}
|
||||||
|
|
||||||
browserBtn.setOnClickListener {
|
mView.browserBtn.setOnClickListener {
|
||||||
c.openInBrowser(items[adapterPosition])
|
c.openInBrowserAsNewTask(items[adapterPosition])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,11 +254,15 @@ class ItemCardAdapter(private val app: Activity,
|
|||||||
helper.bindCustomTabsService(app)
|
helper.bindCustomTabsService(app)
|
||||||
|
|
||||||
mView.setOnClickListener {
|
mView.setOnClickListener {
|
||||||
c.openItemUrl(items[adapterPosition].getLinkDecoded(),
|
c.openItemUrl(
|
||||||
customTabsIntent,
|
items,
|
||||||
internalBrowser,
|
adapterPosition,
|
||||||
articleViewer,
|
items[adapterPosition].getLinkDecoded(),
|
||||||
app)
|
customTabsIntent,
|
||||||
|
internalBrowser,
|
||||||
|
articleViewer,
|
||||||
|
app
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package apps.amine.bou.readerforselfoss.adapters
|
package apps.amine.bou.readerforselfoss.adapters
|
||||||
|
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
@ -12,44 +11,54 @@ import android.util.TypedValue
|
|||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.*
|
import android.widget.TextView
|
||||||
|
import android.widget.Toast
|
||||||
import com.amulyakhare.textdrawable.TextDrawable
|
|
||||||
import com.amulyakhare.textdrawable.util.ColorGenerator
|
|
||||||
import com.like.LikeButton
|
|
||||||
import com.like.OnLikeListener
|
|
||||||
import retrofit2.Call
|
|
||||||
import retrofit2.Callback
|
|
||||||
import retrofit2.Response
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
import apps.amine.bou.readerforselfoss.R
|
import apps.amine.bou.readerforselfoss.R
|
||||||
import apps.amine.bou.readerforselfoss.api.selfoss.Item
|
import apps.amine.bou.readerforselfoss.api.selfoss.Item
|
||||||
import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi
|
import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi
|
||||||
import apps.amine.bou.readerforselfoss.api.selfoss.SuccessResponse
|
import apps.amine.bou.readerforselfoss.api.selfoss.SuccessResponse
|
||||||
import apps.amine.bou.readerforselfoss.utils.*
|
import apps.amine.bou.readerforselfoss.utils.buildCustomTabsIntent
|
||||||
import apps.amine.bou.readerforselfoss.utils.customtabs.CustomTabActivityHelper
|
import apps.amine.bou.readerforselfoss.utils.customtabs.CustomTabActivityHelper
|
||||||
import apps.amine.bou.readerforselfoss.utils.glide.bitmapCenterCrop
|
import apps.amine.bou.readerforselfoss.utils.glide.bitmapCenterCrop
|
||||||
import apps.amine.bou.readerforselfoss.utils.glide.circularBitmapDrawable
|
import apps.amine.bou.readerforselfoss.utils.glide.circularBitmapDrawable
|
||||||
|
import apps.amine.bou.readerforselfoss.utils.openInBrowserAsNewTask
|
||||||
|
import apps.amine.bou.readerforselfoss.utils.openItemUrl
|
||||||
|
import apps.amine.bou.readerforselfoss.utils.shareLink
|
||||||
|
import apps.amine.bou.readerforselfoss.utils.sourceAndDateText
|
||||||
|
import apps.amine.bou.readerforselfoss.utils.succeeded
|
||||||
|
import com.amulyakhare.textdrawable.TextDrawable
|
||||||
|
import com.amulyakhare.textdrawable.util.ColorGenerator
|
||||||
import com.crashlytics.android.Crashlytics
|
import com.crashlytics.android.Crashlytics
|
||||||
|
import com.like.LikeButton
|
||||||
|
import com.like.OnLikeListener
|
||||||
|
import kotlinx.android.synthetic.main.list_item.view.*
|
||||||
|
import retrofit2.Call
|
||||||
|
import retrofit2.Callback
|
||||||
|
import retrofit2.Response
|
||||||
|
import java.util.*
|
||||||
import kotlin.collections.ArrayList
|
import kotlin.collections.ArrayList
|
||||||
|
|
||||||
|
class ItemListAdapter(
|
||||||
class ItemListAdapter(private val app: Activity,
|
private val app: Activity,
|
||||||
private val items: ArrayList<Item>,
|
private val items: ArrayList<Item>,
|
||||||
private val api: SelfossApi,
|
private val api: SelfossApi,
|
||||||
private val helper: CustomTabActivityHelper,
|
private val helper: CustomTabActivityHelper,
|
||||||
private val clickBehavior: Boolean,
|
private val clickBehavior: Boolean,
|
||||||
private val internalBrowser: Boolean,
|
private val internalBrowser: Boolean,
|
||||||
private val articleViewer: Boolean,
|
private val articleViewer: Boolean,
|
||||||
val debugReadingItems: Boolean,
|
val debugReadingItems: Boolean,
|
||||||
val userIdentifier: String) : RecyclerView.Adapter<ItemListAdapter.ViewHolder>() {
|
val userIdentifier: String
|
||||||
|
) : RecyclerView.Adapter<ItemListAdapter.ViewHolder>() {
|
||||||
private val generator: ColorGenerator = ColorGenerator.MATERIAL
|
private val generator: ColorGenerator = ColorGenerator.MATERIAL
|
||||||
private val c: Context = app.baseContext
|
private val c: Context = app.baseContext
|
||||||
private val bars: ArrayList<Boolean> = ArrayList(Collections.nCopies(items.size + 1, false))
|
private val bars: ArrayList<Boolean> = ArrayList(Collections.nCopies(items.size + 1, false))
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||||
val v = LayoutInflater.from(c).inflate(R.layout.list_item, parent, false) as ConstraintLayout
|
val v = LayoutInflater.from(c).inflate(
|
||||||
|
R.layout.list_item,
|
||||||
|
parent,
|
||||||
|
false
|
||||||
|
) as ConstraintLayout
|
||||||
return ViewHolder(v)
|
return ViewHolder(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,27 +66,29 @@ class ItemListAdapter(private val app: Activity,
|
|||||||
val itm = items[position]
|
val itm = items[position]
|
||||||
|
|
||||||
|
|
||||||
holder.saveBtn.isLiked = itm.starred
|
holder.mView.favButton.isLiked = itm.starred
|
||||||
holder.title.text = Html.fromHtml(itm.title)
|
holder.mView.title.text = Html.fromHtml(itm.title)
|
||||||
|
|
||||||
holder.sourceTitleAndDate.text = itm.sourceAndDateText()
|
holder.mView.sourceTitleAndDate.text = itm.sourceAndDateText()
|
||||||
|
|
||||||
if (itm.getThumbnail(c).isEmpty()) {
|
if (itm.getThumbnail(c).isEmpty()) {
|
||||||
val sizeInInt = 46
|
val sizeInInt = 46
|
||||||
val sizeInDp = TypedValue.applyDimension(
|
val sizeInDp = TypedValue.applyDimension(
|
||||||
TypedValue.COMPLEX_UNIT_DIP, sizeInInt.toFloat(), c.resources
|
TypedValue.COMPLEX_UNIT_DIP, sizeInInt.toFloat(), c.resources
|
||||||
.displayMetrics).toInt()
|
.displayMetrics
|
||||||
|
).toInt()
|
||||||
|
|
||||||
val marginInInt = 16
|
val marginInInt = 16
|
||||||
val marginInDp = TypedValue.applyDimension(
|
val marginInDp = TypedValue.applyDimension(
|
||||||
TypedValue.COMPLEX_UNIT_DIP, marginInInt.toFloat(), c.resources
|
TypedValue.COMPLEX_UNIT_DIP, marginInInt.toFloat(), c.resources
|
||||||
.displayMetrics).toInt()
|
.displayMetrics
|
||||||
|
).toInt()
|
||||||
|
|
||||||
val params = holder.sourceImage.layoutParams as ViewGroup.MarginLayoutParams
|
val params = holder.mView.itemImage.layoutParams as ViewGroup.MarginLayoutParams
|
||||||
params.height = sizeInDp
|
params.height = sizeInDp
|
||||||
params.width = sizeInDp
|
params.width = sizeInDp
|
||||||
params.setMargins(marginInDp, 0, 0, 0)
|
params.setMargins(marginInDp, 0, 0, 0)
|
||||||
holder.sourceImage.layoutParams = params
|
holder.mView.itemImage.layoutParams = params
|
||||||
|
|
||||||
if (itm.getIcon(c).isEmpty()) {
|
if (itm.getIcon(c).isEmpty()) {
|
||||||
val color = generator.getColor(itm.sourcetitle)
|
val color = generator.getColor(itm.sourcetitle)
|
||||||
@ -89,31 +100,42 @@ class ItemListAdapter(private val app: Activity,
|
|||||||
val builder = TextDrawable.builder().round()
|
val builder = TextDrawable.builder().round()
|
||||||
|
|
||||||
val drawable = builder.build(textDrawable.toString(), color)
|
val drawable = builder.build(textDrawable.toString(), color)
|
||||||
holder.sourceImage.setImageDrawable(drawable)
|
holder.mView.itemImage.setImageDrawable(drawable)
|
||||||
} else {
|
} else {
|
||||||
c.circularBitmapDrawable(itm.getIcon(c), holder.sourceImage)
|
c.circularBitmapDrawable(itm.getIcon(c), holder.mView.itemImage)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
c.bitmapCenterCrop(itm.getThumbnail(c), holder.sourceImage)
|
c.bitmapCenterCrop(itm.getThumbnail(c), holder.mView.itemImage)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bars[position]) holder.actionBar.visibility = View.VISIBLE else holder.actionBar.visibility = View.GONE
|
if (bars[position]) {
|
||||||
|
holder.mView.actionBar.visibility = View.VISIBLE
|
||||||
|
} else {
|
||||||
|
holder.mView.actionBar.visibility = View.GONE
|
||||||
|
}
|
||||||
|
|
||||||
holder.saveBtn.isLiked = itm.starred
|
holder.mView.favButton.isLiked = itm.starred
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getItemCount(): Int = items.size
|
override fun getItemCount(): Int = items.size
|
||||||
|
|
||||||
|
|
||||||
private fun doUnmark(i: Item, position: Int) {
|
private fun doUnmark(i: Item, position: Int) {
|
||||||
val s = Snackbar
|
val s = Snackbar
|
||||||
.make(app.findViewById(R.id.coordLayout), R.string.marked_as_read, Snackbar.LENGTH_LONG)
|
.make(
|
||||||
|
app.findViewById(R.id.coordLayout),
|
||||||
|
R.string.marked_as_read,
|
||||||
|
Snackbar.LENGTH_LONG
|
||||||
|
)
|
||||||
.setAction(R.string.undo_string) {
|
.setAction(R.string.undo_string) {
|
||||||
items.add(position, i)
|
items.add(position, i)
|
||||||
notifyItemInserted(position)
|
notifyItemInserted(position)
|
||||||
|
|
||||||
api.unmarkItem(i.id).enqueue(object : Callback<SuccessResponse> {
|
api.unmarkItem(i.id).enqueue(object : Callback<SuccessResponse> {
|
||||||
override fun onResponse(call: Call<SuccessResponse>, response: Response<SuccessResponse>) {}
|
override fun onResponse(
|
||||||
|
call: Call<SuccessResponse>,
|
||||||
|
response: Response<SuccessResponse>
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
override fun onFailure(call: Call<SuccessResponse>, t: Throwable) {
|
override fun onFailure(call: Call<SuccessResponse>, t: Throwable) {
|
||||||
items.remove(i)
|
items.remove(i)
|
||||||
@ -137,23 +159,25 @@ class ItemListAdapter(private val app: Activity,
|
|||||||
notifyItemRemoved(position)
|
notifyItemRemoved(position)
|
||||||
|
|
||||||
api.markItem(i.id).enqueue(object : Callback<SuccessResponse> {
|
api.markItem(i.id).enqueue(object : Callback<SuccessResponse> {
|
||||||
override fun onResponse(call: Call<SuccessResponse>, response: Response<SuccessResponse>) {
|
override fun onResponse(
|
||||||
if (debugReadingItems) {
|
call: Call<SuccessResponse>,
|
||||||
|
response: Response<SuccessResponse>
|
||||||
|
) {
|
||||||
|
if (!response.succeeded() && debugReadingItems) {
|
||||||
val message =
|
val message =
|
||||||
"message: ${response.message()} " +
|
"message: ${response.message()} " +
|
||||||
"response isSuccess: ${response.isSuccessful} " +
|
"response isSuccess: ${response.isSuccessful} " +
|
||||||
"response code: ${response.code()} " +
|
"response code: ${response.code()} " +
|
||||||
"response message: ${response.message()} " +
|
"response message: ${response.message()} " +
|
||||||
"response errorBody: ${response.errorBody()?.string()} " +
|
"response errorBody: ${response.errorBody()?.string()} " +
|
||||||
"body success: ${response.body()?.success} " +
|
"body success: ${response.body()?.success} " +
|
||||||
"body isSuccess: ${response.body()?.isSuccess}"
|
"body isSuccess: ${response.body()?.isSuccess}"
|
||||||
Crashlytics.setUserIdentifier(userIdentifier)
|
Crashlytics.setUserIdentifier(userIdentifier)
|
||||||
Crashlytics.log(100, "READ_DEBUG_SUCCESS", message)
|
Crashlytics.log(100, "READ_DEBUG_SUCCESS", message)
|
||||||
Crashlytics.logException(Exception("Was success, but did it work ?"))
|
Crashlytics.logException(Exception("Was success, but did it work ?"))
|
||||||
Toast.makeText(c, message, Toast.LENGTH_LONG).show()
|
Toast.makeText(c, message, Toast.LENGTH_LONG).show()
|
||||||
}
|
}
|
||||||
doUnmark(i, position)
|
doUnmark(i, position)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onFailure(call: Call<SuccessResponse>, t: Throwable) {
|
override fun onFailure(call: Call<SuccessResponse>, t: Throwable) {
|
||||||
@ -163,22 +187,18 @@ class ItemListAdapter(private val app: Activity,
|
|||||||
Crashlytics.logException(t)
|
Crashlytics.logException(t)
|
||||||
Toast.makeText(c, t.message, Toast.LENGTH_LONG).show()
|
Toast.makeText(c, t.message, Toast.LENGTH_LONG).show()
|
||||||
}
|
}
|
||||||
Toast.makeText(app, app.getString(R.string.cant_mark_read), Toast.LENGTH_SHORT).show()
|
Toast.makeText(
|
||||||
|
app,
|
||||||
|
app.getString(R.string.cant_mark_read),
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
items.add(i)
|
items.add(i)
|
||||||
notifyItemInserted(position)
|
notifyItemInserted(position)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inner class ViewHolder(val mView: ConstraintLayout) : RecyclerView.ViewHolder(mView) {
|
inner class ViewHolder(val mView: ConstraintLayout) : RecyclerView.ViewHolder(mView) {
|
||||||
lateinit var saveBtn: LikeButton
|
|
||||||
lateinit var browserBtn: ImageButton
|
|
||||||
lateinit var shareBtn: ImageButton
|
|
||||||
lateinit var actionBar: RelativeLayout
|
|
||||||
lateinit var sourceImage: ImageView
|
|
||||||
lateinit var title: TextView
|
|
||||||
lateinit var sourceTitleAndDate: TextView
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
handleClickListeners()
|
handleClickListeners()
|
||||||
@ -186,24 +206,27 @@ class ItemListAdapter(private val app: Activity,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun handleClickListeners() {
|
private fun handleClickListeners() {
|
||||||
actionBar = mView.findViewById(R.id.actionBar)
|
|
||||||
sourceImage = mView.findViewById(R.id.itemImage)
|
|
||||||
title = mView.findViewById(R.id.title)
|
|
||||||
sourceTitleAndDate = mView.findViewById(R.id.sourceTitleAndDate)
|
|
||||||
saveBtn = mView.findViewById(R.id.favButton)
|
|
||||||
shareBtn = mView.findViewById(R.id.shareBtn)
|
|
||||||
browserBtn = mView.findViewById(R.id.browserBtn)
|
|
||||||
|
|
||||||
|
mView.favButton.setOnLikeListener(object : OnLikeListener {
|
||||||
saveBtn.setOnLikeListener(object : OnLikeListener {
|
|
||||||
override fun liked(likeButton: LikeButton) {
|
override fun liked(likeButton: LikeButton) {
|
||||||
val (id) = items[adapterPosition]
|
val (id) = items[adapterPosition]
|
||||||
api.starrItem(id).enqueue(object : Callback<SuccessResponse> {
|
api.starrItem(id).enqueue(object : Callback<SuccessResponse> {
|
||||||
override fun onResponse(call: Call<SuccessResponse>, response: Response<SuccessResponse>) {}
|
override fun onResponse(
|
||||||
|
call: Call<SuccessResponse>,
|
||||||
|
response: Response<SuccessResponse>
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
override fun onFailure(call: Call<SuccessResponse>, t: Throwable) {
|
override fun onFailure(
|
||||||
saveBtn.isLiked = false
|
call: Call<SuccessResponse>,
|
||||||
Toast.makeText(c, R.string.cant_mark_favortie, Toast.LENGTH_SHORT).show()
|
t: Throwable
|
||||||
|
) {
|
||||||
|
mView.favButton.isLiked = false
|
||||||
|
Toast.makeText(
|
||||||
|
c,
|
||||||
|
R.string.cant_mark_favortie,
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -211,27 +234,37 @@ class ItemListAdapter(private val app: Activity,
|
|||||||
override fun unLiked(likeButton: LikeButton) {
|
override fun unLiked(likeButton: LikeButton) {
|
||||||
val (id) = items[adapterPosition]
|
val (id) = items[adapterPosition]
|
||||||
api.unstarrItem(id).enqueue(object : Callback<SuccessResponse> {
|
api.unstarrItem(id).enqueue(object : Callback<SuccessResponse> {
|
||||||
override fun onResponse(call: Call<SuccessResponse>, response: Response<SuccessResponse>) {}
|
override fun onResponse(
|
||||||
|
call: Call<SuccessResponse>,
|
||||||
|
response: Response<SuccessResponse>
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
override fun onFailure(call: Call<SuccessResponse>, t: Throwable) {
|
override fun onFailure(
|
||||||
saveBtn.isLiked = true
|
call: Call<SuccessResponse>,
|
||||||
Toast.makeText(c, R.string.cant_unmark_favortie, Toast.LENGTH_SHORT).show()
|
t: Throwable
|
||||||
|
) {
|
||||||
|
mView.favButton.isLiked = true
|
||||||
|
Toast.makeText(
|
||||||
|
c,
|
||||||
|
R.string.cant_unmark_favortie,
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
shareBtn.setOnClickListener {
|
mView.shareBtn.setOnClickListener {
|
||||||
c.shareLink(items[adapterPosition].getLinkDecoded())
|
c.shareLink(items[adapterPosition].getLinkDecoded())
|
||||||
}
|
}
|
||||||
|
|
||||||
browserBtn.setOnClickListener {
|
mView.browserBtn.setOnClickListener {
|
||||||
c.openInBrowser(items[adapterPosition])
|
c.openInBrowserAsNewTask(items[adapterPosition])
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun handleCustomTabActions() {
|
private fun handleCustomTabActions() {
|
||||||
val customTabsIntent = c.buildCustomTabsIntent()
|
val customTabsIntent = c.buildCustomTabsIntent()
|
||||||
helper.bindCustomTabsService(app)
|
helper.bindCustomTabsService(app)
|
||||||
@ -239,11 +272,15 @@ class ItemListAdapter(private val app: Activity,
|
|||||||
|
|
||||||
if (!clickBehavior) {
|
if (!clickBehavior) {
|
||||||
mView.setOnClickListener {
|
mView.setOnClickListener {
|
||||||
c.openItemUrl(items[adapterPosition].getLinkDecoded(),
|
c.openItemUrl(
|
||||||
customTabsIntent,
|
items,
|
||||||
internalBrowser,
|
adapterPosition,
|
||||||
articleViewer,
|
items[adapterPosition].getLinkDecoded(),
|
||||||
app)
|
customTabsIntent,
|
||||||
|
internalBrowser,
|
||||||
|
articleViewer,
|
||||||
|
app
|
||||||
|
)
|
||||||
}
|
}
|
||||||
mView.setOnLongClickListener {
|
mView.setOnLongClickListener {
|
||||||
actionBarShowHide()
|
actionBarShowHide()
|
||||||
@ -252,11 +289,15 @@ class ItemListAdapter(private val app: Activity,
|
|||||||
} else {
|
} else {
|
||||||
mView.setOnClickListener { actionBarShowHide() }
|
mView.setOnClickListener { actionBarShowHide() }
|
||||||
mView.setOnLongClickListener {
|
mView.setOnLongClickListener {
|
||||||
c.openItemUrl(items[adapterPosition].getLinkDecoded(),
|
c.openItemUrl(
|
||||||
customTabsIntent,
|
items,
|
||||||
internalBrowser,
|
adapterPosition,
|
||||||
articleViewer,
|
items[adapterPosition].getLinkDecoded(),
|
||||||
app)
|
customTabsIntent,
|
||||||
|
internalBrowser,
|
||||||
|
articleViewer,
|
||||||
|
app
|
||||||
|
)
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -264,7 +305,11 @@ class ItemListAdapter(private val app: Activity,
|
|||||||
|
|
||||||
private fun actionBarShowHide() {
|
private fun actionBarShowHide() {
|
||||||
bars[adapterPosition] = true
|
bars[adapterPosition] = true
|
||||||
if (actionBar.visibility == View.GONE) actionBar.visibility = View.VISIBLE else actionBar.visibility = View.GONE
|
if (mView.actionBar.visibility == View.GONE) {
|
||||||
|
mView.actionBar.visibility = View.VISIBLE
|
||||||
|
} else {
|
||||||
|
mView.actionBar.visibility = View.GONE
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,32 +7,34 @@ import android.support.v7.widget.RecyclerView
|
|||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.Button
|
import android.widget.Button
|
||||||
import android.widget.ImageView
|
|
||||||
import android.widget.TextView
|
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
|
|
||||||
import com.amulyakhare.textdrawable.TextDrawable
|
|
||||||
import com.amulyakhare.textdrawable.util.ColorGenerator
|
|
||||||
import retrofit2.Call
|
|
||||||
import retrofit2.Callback
|
|
||||||
import retrofit2.Response
|
|
||||||
|
|
||||||
import apps.amine.bou.readerforselfoss.R
|
import apps.amine.bou.readerforselfoss.R
|
||||||
import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi
|
import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi
|
||||||
import apps.amine.bou.readerforselfoss.api.selfoss.Sources
|
import apps.amine.bou.readerforselfoss.api.selfoss.Sources
|
||||||
import apps.amine.bou.readerforselfoss.api.selfoss.SuccessResponse
|
import apps.amine.bou.readerforselfoss.api.selfoss.SuccessResponse
|
||||||
import apps.amine.bou.readerforselfoss.utils.glide.circularBitmapDrawable
|
import apps.amine.bou.readerforselfoss.utils.glide.circularBitmapDrawable
|
||||||
import apps.amine.bou.readerforselfoss.utils.toTextDrawableString
|
import apps.amine.bou.readerforselfoss.utils.toTextDrawableString
|
||||||
|
import com.amulyakhare.textdrawable.TextDrawable
|
||||||
|
import com.amulyakhare.textdrawable.util.ColorGenerator
|
||||||
|
import kotlinx.android.synthetic.main.source_list_item.view.*
|
||||||
|
import retrofit2.Call
|
||||||
|
import retrofit2.Callback
|
||||||
|
import retrofit2.Response
|
||||||
|
|
||||||
|
class SourcesListAdapter(
|
||||||
class SourcesListAdapter(private val app: Activity,
|
private val app: Activity,
|
||||||
private val items: ArrayList<Sources>,
|
private val items: ArrayList<Sources>,
|
||||||
private val api: SelfossApi) : RecyclerView.Adapter<SourcesListAdapter.ViewHolder>() {
|
private val api: SelfossApi
|
||||||
|
) : RecyclerView.Adapter<SourcesListAdapter.ViewHolder>() {
|
||||||
private val c: Context = app.baseContext
|
private val c: Context = app.baseContext
|
||||||
private val generator: ColorGenerator = ColorGenerator.MATERIAL
|
private val generator: ColorGenerator = ColorGenerator.MATERIAL
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||||
val v = LayoutInflater.from(c).inflate(R.layout.source_list_item, parent, false) as ConstraintLayout
|
val v = LayoutInflater.from(c).inflate(
|
||||||
|
R.layout.source_list_item,
|
||||||
|
parent,
|
||||||
|
false
|
||||||
|
) as ConstraintLayout
|
||||||
return ViewHolder(v)
|
return ViewHolder(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,57 +45,59 @@ class SourcesListAdapter(private val app: Activity,
|
|||||||
val color = generator.getColor(itm.title)
|
val color = generator.getColor(itm.title)
|
||||||
|
|
||||||
val drawable =
|
val drawable =
|
||||||
TextDrawable
|
TextDrawable
|
||||||
.builder()
|
.builder()
|
||||||
.round()
|
.round()
|
||||||
.build(itm.title.toTextDrawableString(), color)
|
.build(itm.title.toTextDrawableString(), color)
|
||||||
holder.sourceImage.setImageDrawable(drawable)
|
holder.mView.itemImage.setImageDrawable(drawable)
|
||||||
} else {
|
} else {
|
||||||
c.circularBitmapDrawable(itm.getIcon(c), holder.sourceImage)
|
c.circularBitmapDrawable(itm.getIcon(c), holder.mView.itemImage)
|
||||||
}
|
}
|
||||||
|
|
||||||
holder.sourceTitle.text = itm.title
|
holder.mView.sourceTitle.text = itm.title
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getItemCount(): Int {
|
override fun getItemCount(): Int = items.size
|
||||||
return items.size
|
|
||||||
}
|
|
||||||
|
|
||||||
inner class ViewHolder(internal val mView: ConstraintLayout) : RecyclerView.ViewHolder(mView) {
|
inner class ViewHolder(internal val mView: ConstraintLayout) : RecyclerView.ViewHolder(mView) {
|
||||||
lateinit var sourceImage: ImageView
|
|
||||||
lateinit var sourceTitle: TextView
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
|
||||||
handleClickListeners()
|
handleClickListeners()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleClickListeners() {
|
private fun handleClickListeners() {
|
||||||
sourceImage = mView.findViewById(R.id.itemImage)
|
|
||||||
sourceTitle = mView.findViewById(R.id.sourceTitle)
|
|
||||||
|
|
||||||
val deleteBtn: Button = mView.findViewById(R.id.deleteBtn)
|
val deleteBtn: Button = mView.findViewById(R.id.deleteBtn)
|
||||||
|
|
||||||
deleteBtn.setOnClickListener {
|
deleteBtn.setOnClickListener {
|
||||||
val (id) = items[adapterPosition]
|
val (id) = items[adapterPosition]
|
||||||
api.deleteSource(id).enqueue(object : Callback<SuccessResponse> {
|
api.deleteSource(id).enqueue(object : Callback<SuccessResponse> {
|
||||||
override fun onResponse(call: Call<SuccessResponse>, response: Response<SuccessResponse>) {
|
override fun onResponse(
|
||||||
|
call: Call<SuccessResponse>,
|
||||||
|
response: Response<SuccessResponse>
|
||||||
|
) {
|
||||||
if (response.body() != null && response.body()!!.isSuccess) {
|
if (response.body() != null && response.body()!!.isSuccess) {
|
||||||
items.removeAt(adapterPosition)
|
items.removeAt(adapterPosition)
|
||||||
notifyItemRemoved(adapterPosition)
|
notifyItemRemoved(adapterPosition)
|
||||||
notifyItemRangeChanged(adapterPosition, itemCount)
|
notifyItemRangeChanged(adapterPosition, itemCount)
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(app, R.string.can_delete_source, Toast.LENGTH_SHORT).show()
|
Toast.makeText(
|
||||||
|
app,
|
||||||
|
R.string.can_delete_source,
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onFailure(call: Call<SuccessResponse>, t: Throwable) {
|
override fun onFailure(call: Call<SuccessResponse>, t: Throwable) {
|
||||||
Toast.makeText(app, R.string.can_delete_source, Toast.LENGTH_SHORT).show()
|
Toast.makeText(
|
||||||
|
app,
|
||||||
|
R.string.can_delete_source,
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,27 +7,29 @@ import retrofit2.Call
|
|||||||
import retrofit2.Retrofit
|
import retrofit2.Retrofit
|
||||||
import retrofit2.converter.gson.GsonConverterFactory
|
import retrofit2.converter.gson.GsonConverterFactory
|
||||||
|
|
||||||
|
class MercuryApi(private val key: String, shouldLog: Boolean) {
|
||||||
|
|
||||||
class MercuryApi(private val key: String) {
|
|
||||||
private val service: MercuryService
|
private val service: MercuryService
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
|
||||||
val interceptor = HttpLoggingInterceptor()
|
val interceptor = HttpLoggingInterceptor()
|
||||||
interceptor.level = HttpLoggingInterceptor.Level.BODY
|
interceptor.level = if (shouldLog) {
|
||||||
|
HttpLoggingInterceptor.Level.BODY
|
||||||
|
} else {
|
||||||
|
HttpLoggingInterceptor.Level.NONE
|
||||||
|
}
|
||||||
val client = OkHttpClient.Builder().addInterceptor(interceptor).build()
|
val client = OkHttpClient.Builder().addInterceptor(interceptor).build()
|
||||||
|
|
||||||
val gson = GsonBuilder()
|
val gson = GsonBuilder()
|
||||||
.setLenient()
|
.setLenient()
|
||||||
.create()
|
.create()
|
||||||
val retrofit =
|
val retrofit =
|
||||||
Retrofit
|
Retrofit
|
||||||
.Builder()
|
.Builder()
|
||||||
.baseUrl("https://mercury.postlight.com")
|
.baseUrl("https://mercury.postlight.com")
|
||||||
.client(client)
|
.client(client)
|
||||||
.addConverterFactory(GsonConverterFactory.create(gson))
|
.addConverterFactory(GsonConverterFactory.create(gson))
|
||||||
.build()
|
.build()
|
||||||
service = retrofit.create(MercuryService::class.java)
|
service = retrofit.create(MercuryService::class.java)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,38 +4,40 @@ import android.os.Parcel
|
|||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
import com.google.gson.annotations.SerializedName
|
import com.google.gson.annotations.SerializedName
|
||||||
|
|
||||||
|
class ParsedContent(
|
||||||
class ParsedContent(@SerializedName("title") val title: String,
|
@SerializedName("title") val title: String,
|
||||||
@SerializedName("content") val content: String,
|
@SerializedName("content") val content: String,
|
||||||
@SerializedName("date_published") val date_published: String,
|
@SerializedName("date_published") val date_published: String,
|
||||||
@SerializedName("lead_image_url") val lead_image_url: String,
|
@SerializedName("lead_image_url") val lead_image_url: String,
|
||||||
@SerializedName("dek") val dek: String,
|
@SerializedName("dek") val dek: String,
|
||||||
@SerializedName("url") val url: String,
|
@SerializedName("url") val url: String,
|
||||||
@SerializedName("domain") val domain: String,
|
@SerializedName("domain") val domain: String,
|
||||||
@SerializedName("excerpt") val excerpt: String,
|
@SerializedName("excerpt") val excerpt: String,
|
||||||
@SerializedName("total_pages") val total_pages: Int,
|
@SerializedName("total_pages") val total_pages: Int,
|
||||||
@SerializedName("rendered_pages") val rendered_pages: Int,
|
@SerializedName("rendered_pages") val rendered_pages: Int,
|
||||||
@SerializedName("next_page_url") val next_page_url: String) : Parcelable {
|
@SerializedName("next_page_url") val next_page_url: String
|
||||||
|
) : Parcelable {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@JvmField val CREATOR: Parcelable.Creator<ParsedContent> = object : Parcelable.Creator<ParsedContent> {
|
@JvmField
|
||||||
|
val CREATOR: Parcelable.Creator<ParsedContent> = object : Parcelable.Creator<ParsedContent> {
|
||||||
override fun createFromParcel(source: Parcel): ParsedContent = ParsedContent(source)
|
override fun createFromParcel(source: Parcel): ParsedContent = ParsedContent(source)
|
||||||
override fun newArray(size: Int): Array<ParsedContent?> = arrayOfNulls(size)
|
override fun newArray(size: Int): Array<ParsedContent?> = arrayOfNulls(size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(source: Parcel) : this(
|
constructor(source: Parcel) : this(
|
||||||
title = source.readString(),
|
title = source.readString(),
|
||||||
content = source.readString(),
|
content = source.readString(),
|
||||||
date_published = source.readString(),
|
date_published = source.readString(),
|
||||||
lead_image_url = source.readString(),
|
lead_image_url = source.readString(),
|
||||||
dek = source.readString(),
|
dek = source.readString(),
|
||||||
url = source.readString(),
|
url = source.readString(),
|
||||||
domain = source.readString(),
|
domain = source.readString(),
|
||||||
excerpt = source.readString(),
|
excerpt = source.readString(),
|
||||||
total_pages = source.readInt(),
|
total_pages = source.readInt(),
|
||||||
rendered_pages = source.readInt(),
|
rendered_pages = source.readInt(),
|
||||||
next_page_url = source.readString()
|
next_page_url = source.readString()
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun describeContents() = 0
|
override fun describeContents() = 0
|
||||||
|
@ -1,13 +1,10 @@
|
|||||||
package apps.amine.bou.readerforselfoss.api.mercury
|
package apps.amine.bou.readerforselfoss.api.mercury
|
||||||
|
|
||||||
|
|
||||||
import retrofit2.Call
|
import retrofit2.Call
|
||||||
import retrofit2.http.GET
|
import retrofit2.http.GET
|
||||||
import retrofit2.http.Header
|
import retrofit2.http.Header
|
||||||
import retrofit2.http.Query
|
import retrofit2.http.Query
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
interface MercuryService {
|
interface MercuryService {
|
||||||
@GET("parser")
|
@GET("parser")
|
||||||
fun parseUrl(@Query("url") url: String, @Header("x-api-key") key: String): Call<ParsedContent>
|
fun parseUrl(@Query("url") url: String, @Header("x-api-key") key: String): Call<ParsedContent>
|
||||||
|
@ -1,21 +1,22 @@
|
|||||||
package apps.amine.bou.readerforselfoss.api.selfoss
|
package apps.amine.bou.readerforselfoss.api.selfoss
|
||||||
|
|
||||||
import java.lang.reflect.Type
|
|
||||||
|
|
||||||
import com.google.gson.JsonParseException
|
|
||||||
import com.google.gson.JsonDeserializationContext
|
import com.google.gson.JsonDeserializationContext
|
||||||
import com.google.gson.JsonElement
|
|
||||||
import com.google.gson.JsonDeserializer
|
import com.google.gson.JsonDeserializer
|
||||||
|
import com.google.gson.JsonElement
|
||||||
|
import com.google.gson.JsonParseException
|
||||||
|
import java.lang.reflect.Type
|
||||||
|
|
||||||
internal class BooleanTypeAdapter : JsonDeserializer<Boolean> {
|
internal class BooleanTypeAdapter : JsonDeserializer<Boolean> {
|
||||||
|
|
||||||
@Throws(JsonParseException::class)
|
@Throws(JsonParseException::class)
|
||||||
override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): Boolean? =
|
override fun deserialize(
|
||||||
try {
|
json: JsonElement,
|
||||||
json.asInt == 1
|
typeOfT: Type,
|
||||||
} catch (e: Exception) {
|
context: JsonDeserializationContext
|
||||||
json.asBoolean
|
): Boolean? =
|
||||||
}
|
try {
|
||||||
|
json.asInt == 1
|
||||||
|
} catch (e: Exception) {
|
||||||
|
json.asBoolean
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,8 @@ package apps.amine.bou.readerforselfoss.api.selfoss
|
|||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
import apps.amine.bou.readerforselfoss.utils.Config
|
||||||
|
import apps.amine.bou.readerforselfoss.utils.getUnsafeHttpClient
|
||||||
import com.burgstaller.okhttp.AuthenticationCacheInterceptor
|
import com.burgstaller.okhttp.AuthenticationCacheInterceptor
|
||||||
import com.burgstaller.okhttp.CachingAuthenticatorDecorator
|
import com.burgstaller.okhttp.CachingAuthenticatorDecorator
|
||||||
import com.burgstaller.okhttp.DispatchingAuthenticator
|
import com.burgstaller.okhttp.DispatchingAuthenticator
|
||||||
@ -13,19 +13,18 @@ import com.burgstaller.okhttp.digest.Credentials
|
|||||||
import com.burgstaller.okhttp.digest.DigestAuthenticator
|
import com.burgstaller.okhttp.digest.DigestAuthenticator
|
||||||
import com.google.gson.GsonBuilder
|
import com.google.gson.GsonBuilder
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
|
import okhttp3.logging.HttpLoggingInterceptor
|
||||||
import retrofit2.Call
|
import retrofit2.Call
|
||||||
import retrofit2.Retrofit
|
import retrofit2.Retrofit
|
||||||
import retrofit2.converter.gson.GsonConverterFactory
|
import retrofit2.converter.gson.GsonConverterFactory
|
||||||
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
|
|
||||||
import apps.amine.bou.readerforselfoss.utils.Config
|
class SelfossApi(
|
||||||
import apps.amine.bou.readerforselfoss.utils.getUnsafeHttpClient
|
c: Context,
|
||||||
import okhttp3.logging.HttpLoggingInterceptor
|
callingActivity: Activity,
|
||||||
|
isWithSelfSignedCert: Boolean,
|
||||||
|
shouldLog: Boolean
|
||||||
|
) {
|
||||||
|
|
||||||
// codebeat:disable[ARITY,TOO_MANY_FUNCTIONS]
|
|
||||||
class SelfossApi(c: Context, callingActivity: Activity, isWithSelfSignedCert: Boolean, shouldLog: Boolean) {
|
|
||||||
|
|
||||||
private lateinit var service: SelfossService
|
private lateinit var service: SelfossService
|
||||||
private val config: Config = Config(c)
|
private val config: Config = Config(c)
|
||||||
@ -33,50 +32,50 @@ class SelfossApi(c: Context, callingActivity: Activity, isWithSelfSignedCert: Bo
|
|||||||
private val password: String
|
private val password: String
|
||||||
|
|
||||||
fun OkHttpClient.Builder.maybeWithSelfSigned(isWithSelfSignedCert: Boolean): OkHttpClient.Builder =
|
fun OkHttpClient.Builder.maybeWithSelfSigned(isWithSelfSignedCert: Boolean): OkHttpClient.Builder =
|
||||||
if (isWithSelfSignedCert) {
|
if (isWithSelfSignedCert) {
|
||||||
getUnsafeHttpClient()
|
getUnsafeHttpClient()
|
||||||
} else {
|
} else {
|
||||||
this
|
this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Credentials.createAuthenticator(): DispatchingAuthenticator =
|
fun Credentials.createAuthenticator(): DispatchingAuthenticator =
|
||||||
DispatchingAuthenticator.Builder()
|
DispatchingAuthenticator.Builder()
|
||||||
.with("digest", DigestAuthenticator(this))
|
.with("digest", DigestAuthenticator(this))
|
||||||
.with("basic", BasicAuthenticator(this))
|
.with("basic", BasicAuthenticator(this))
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
fun DispatchingAuthenticator.getHttpClien(isWithSelfSignedCert: Boolean): OkHttpClient.Builder {
|
fun DispatchingAuthenticator.getHttpClien(isWithSelfSignedCert: Boolean): OkHttpClient.Builder {
|
||||||
val authCache = ConcurrentHashMap<String, CachingAuthenticator>()
|
val authCache = ConcurrentHashMap<String, CachingAuthenticator>()
|
||||||
return OkHttpClient
|
return OkHttpClient
|
||||||
.Builder()
|
.Builder()
|
||||||
.maybeWithSelfSigned(isWithSelfSignedCert)
|
.maybeWithSelfSigned(isWithSelfSignedCert)
|
||||||
.authenticator(CachingAuthenticatorDecorator(this, authCache))
|
.authenticator(CachingAuthenticatorDecorator(this, authCache))
|
||||||
.addInterceptor(AuthenticationCacheInterceptor(authCache))
|
.addInterceptor(AuthenticationCacheInterceptor(authCache))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
userName = config.userLogin
|
userName = config.userLogin
|
||||||
password = config.userPassword
|
password = config.userPassword
|
||||||
|
|
||||||
val authenticator =
|
val authenticator =
|
||||||
Credentials(
|
Credentials(
|
||||||
config.httpUserLogin,
|
config.httpUserLogin,
|
||||||
config.httpUserPassword
|
config.httpUserPassword
|
||||||
).createAuthenticator()
|
).createAuthenticator()
|
||||||
|
|
||||||
val gson =
|
val gson =
|
||||||
GsonBuilder()
|
GsonBuilder()
|
||||||
.registerTypeAdapter(Boolean::class.javaPrimitiveType, BooleanTypeAdapter())
|
.registerTypeAdapter(Boolean::class.javaPrimitiveType, BooleanTypeAdapter())
|
||||||
.setLenient()
|
.setLenient()
|
||||||
.create()
|
.create()
|
||||||
|
|
||||||
val logging = HttpLoggingInterceptor()
|
val logging = HttpLoggingInterceptor()
|
||||||
|
|
||||||
logging.level = if (shouldLog)
|
logging.level = if (shouldLog) {
|
||||||
HttpLoggingInterceptor.Level.BODY
|
HttpLoggingInterceptor.Level.BODY
|
||||||
else
|
} else {
|
||||||
HttpLoggingInterceptor.Level.NONE
|
HttpLoggingInterceptor.Level.NONE
|
||||||
|
}
|
||||||
|
|
||||||
val httpClient = authenticator.getHttpClien(isWithSelfSignedCert)
|
val httpClient = authenticator.getHttpClien(isWithSelfSignedCert)
|
||||||
|
|
||||||
@ -84,12 +83,12 @@ class SelfossApi(c: Context, callingActivity: Activity, isWithSelfSignedCert: Bo
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
val retrofit =
|
val retrofit =
|
||||||
Retrofit
|
Retrofit
|
||||||
.Builder()
|
.Builder()
|
||||||
.baseUrl(config.baseUrl)
|
.baseUrl(config.baseUrl)
|
||||||
.client(httpClient.build())
|
.client(httpClient.build())
|
||||||
.addConverterFactory(GsonConverterFactory.create(gson))
|
.addConverterFactory(GsonConverterFactory.create(gson))
|
||||||
.build()
|
.build()
|
||||||
service = retrofit.create(SelfossService::class.java)
|
service = retrofit.create(SelfossService::class.java)
|
||||||
} catch (e: IllegalArgumentException) {
|
} catch (e: IllegalArgumentException) {
|
||||||
Config.logoutAndRedirect(c, callingActivity, config.settings.edit(), baseUrlFail = true)
|
Config.logoutAndRedirect(c, callingActivity, config.settings.edit(), baseUrlFail = true)
|
||||||
@ -97,34 +96,59 @@ class SelfossApi(c: Context, callingActivity: Activity, isWithSelfSignedCert: Bo
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun login(): Call<SuccessResponse> =
|
fun login(): Call<SuccessResponse> =
|
||||||
service.loginToSelfoss(config.userLogin, config.userPassword)
|
service.loginToSelfoss(config.userLogin, config.userPassword)
|
||||||
|
|
||||||
fun readItems(tag: String?, sourceId: Long?, search: String?): Call<List<Item>> =
|
fun readItems(
|
||||||
getItems("read", tag, sourceId, search, 200)
|
tag: String?,
|
||||||
|
sourceId: Long?,
|
||||||
|
search: String?,
|
||||||
|
itemsNumber: Int,
|
||||||
|
offset: Int
|
||||||
|
): Call<List<Item>> =
|
||||||
|
getItems("read", tag, sourceId, search, itemsNumber, offset)
|
||||||
|
|
||||||
fun newItems(tag: String?, sourceId: Long?, search: String?, itemsNumber: Int): Call<List<Item>> =
|
fun newItems(
|
||||||
getItems("unread", tag, sourceId, search, itemsNumber)
|
tag: String?,
|
||||||
|
sourceId: Long?,
|
||||||
|
search: String?,
|
||||||
|
itemsNumber: Int,
|
||||||
|
offset: Int
|
||||||
|
): Call<List<Item>> =
|
||||||
|
getItems("unread", tag, sourceId, search, itemsNumber, offset)
|
||||||
|
|
||||||
fun starredItems(tag: String?, sourceId: Long?, search: String?): Call<List<Item>> =
|
fun starredItems(
|
||||||
getItems("starred", tag, sourceId, search, 200)
|
tag: String?,
|
||||||
|
sourceId: Long?,
|
||||||
|
search: String?,
|
||||||
|
itemsNumber: Int,
|
||||||
|
offset: Int
|
||||||
|
): Call<List<Item>> =
|
||||||
|
getItems("starred", tag, sourceId, search, itemsNumber, offset)
|
||||||
|
|
||||||
private fun getItems(type: String, tag: String?, sourceId: Long?, search: String?, items: Int): Call<List<Item>> =
|
private fun getItems(
|
||||||
service.getItems(type, tag, sourceId, search, userName, password, items)
|
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)
|
||||||
|
|
||||||
fun markItem(itemId: String): Call<SuccessResponse> =
|
fun markItem(itemId: String): Call<SuccessResponse> =
|
||||||
service.markAsRead(itemId, userName, password)
|
service.markAsRead(itemId, userName, password)
|
||||||
|
|
||||||
fun unmarkItem(itemId: String): Call<SuccessResponse> =
|
fun unmarkItem(itemId: String): Call<SuccessResponse> =
|
||||||
service.unmarkAsRead(itemId, userName, password)
|
service.unmarkAsRead(itemId, userName, password)
|
||||||
|
|
||||||
fun readAll(ids: List<String>): Call<SuccessResponse> =
|
fun readAll(ids: List<String>): Call<SuccessResponse> =
|
||||||
service.markAllAsRead(ids, userName, password)
|
service.markAllAsRead(ids, userName, password)
|
||||||
|
|
||||||
fun starrItem(itemId: String): Call<SuccessResponse> =
|
fun starrItem(itemId: String): Call<SuccessResponse> =
|
||||||
service.starr(itemId, userName, password)
|
service.starr(itemId, userName, password)
|
||||||
|
|
||||||
fun unstarrItem(itemId: String): Call<SuccessResponse> =
|
fun unstarrItem(itemId: String): Call<SuccessResponse> =
|
||||||
service.unstarr(itemId, userName, password)
|
service.unstarr(itemId, userName, password)
|
||||||
|
|
||||||
val stats: Call<Stats>
|
val stats: Call<Stats>
|
||||||
get() = service.stats(userName, password)
|
get() = service.stats(userName, password)
|
||||||
@ -133,20 +157,23 @@ class SelfossApi(c: Context, callingActivity: Activity, isWithSelfSignedCert: Bo
|
|||||||
get() = service.tags(userName, password)
|
get() = service.tags(userName, password)
|
||||||
|
|
||||||
fun update(): Call<String> =
|
fun update(): Call<String> =
|
||||||
service.update(userName, password)
|
service.update(userName, password)
|
||||||
|
|
||||||
val sources: Call<List<Sources>>
|
val sources: Call<List<Sources>>
|
||||||
get() = service.sources(userName, password)
|
get() = service.sources(userName, password)
|
||||||
|
|
||||||
fun deleteSource(id: String): Call<SuccessResponse> =
|
fun deleteSource(id: String): Call<SuccessResponse> =
|
||||||
service.deleteSource(id, userName, password)
|
service.deleteSource(id, userName, password)
|
||||||
|
|
||||||
fun spouts(): Call<Map<String, Spout>> =
|
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): Call<SuccessResponse> =
|
|
||||||
service.createSource(title, url, spout, tags, filter, userName, password)
|
|
||||||
|
|
||||||
|
fun createSource(
|
||||||
|
title: String,
|
||||||
|
url: String,
|
||||||
|
spout: String,
|
||||||
|
tags: String,
|
||||||
|
filter: String
|
||||||
|
): Call<SuccessResponse> =
|
||||||
|
service.createSource(title, url, spout, tags, filter, userName, password)
|
||||||
}
|
}
|
||||||
|
|
||||||
// codebeat:enable[ARITY,TOO_MANY_FUNCTIONS]
|
|
@ -9,58 +9,69 @@ import apps.amine.bou.readerforselfoss.utils.Config
|
|||||||
import apps.amine.bou.readerforselfoss.utils.isEmptyOrNullOrNullString
|
import apps.amine.bou.readerforselfoss.utils.isEmptyOrNullOrNullString
|
||||||
import com.google.gson.annotations.SerializedName
|
import com.google.gson.annotations.SerializedName
|
||||||
|
|
||||||
|
|
||||||
private fun constructUrl(config: Config?, path: String, file: String): String {
|
private fun constructUrl(config: Config?, path: String, file: String): String {
|
||||||
val baseUriBuilder = Uri.parse(config!!.baseUrl).buildUpon()
|
val baseUriBuilder = Uri.parse(config!!.baseUrl).buildUpon()
|
||||||
baseUriBuilder.appendPath(path).appendPath(file)
|
baseUriBuilder.appendPath(path).appendPath(file)
|
||||||
|
|
||||||
return if (file.isEmptyOrNullOrNullString()) ""
|
return if (file.isEmptyOrNullOrNullString()) {
|
||||||
else baseUriBuilder.toString()
|
""
|
||||||
|
} else {
|
||||||
|
baseUriBuilder.toString()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data class Tag(
|
||||||
data class Tag(@SerializedName("tag") val tag: String,
|
@SerializedName("tag") val tag: String,
|
||||||
@SerializedName("color") val color: String,
|
@SerializedName("color") val color: String,
|
||||||
@SerializedName("unread") val unread: Int)
|
@SerializedName("unread") val unread: Int
|
||||||
|
)
|
||||||
|
|
||||||
class SuccessResponse(@SerializedName("success") val success: Boolean) {
|
class SuccessResponse(@SerializedName("success") val success: Boolean) {
|
||||||
val isSuccess: Boolean
|
val isSuccess: Boolean
|
||||||
get() = success
|
get() = success
|
||||||
}
|
}
|
||||||
|
|
||||||
class Stats(@SerializedName("total") val total: Int,
|
class Stats(
|
||||||
@SerializedName("unread") val unread: Int,
|
@SerializedName("total") val total: Int,
|
||||||
@SerializedName("starred") val starred: Int)
|
@SerializedName("unread") val unread: Int,
|
||||||
|
@SerializedName("starred") val starred: Int
|
||||||
|
)
|
||||||
|
|
||||||
data class Spout(@SerializedName("name") val name: String,
|
data class Spout(
|
||||||
@SerializedName("description") val description: String)
|
@SerializedName("name") val name: String,
|
||||||
|
@SerializedName("description") val description: String
|
||||||
|
)
|
||||||
|
|
||||||
data class Sources(@SerializedName("id") val id: String,
|
data class Sources(
|
||||||
@SerializedName("title") val title: String,
|
@SerializedName("id") val id: String,
|
||||||
@SerializedName("tags") val tags: String,
|
@SerializedName("title") val title: String,
|
||||||
@SerializedName("spout") val spout: String,
|
@SerializedName("tags") val tags: String,
|
||||||
@SerializedName("error") val error: String,
|
@SerializedName("spout") val spout: String,
|
||||||
@SerializedName("icon") val icon: String) {
|
@SerializedName("error") val error: String,
|
||||||
|
@SerializedName("icon") val icon: String
|
||||||
|
) {
|
||||||
var config: Config? = null
|
var config: Config? = null
|
||||||
|
|
||||||
fun getIcon(app: Context): String {
|
fun getIcon(app: Context): String {
|
||||||
if (config == null) {
|
if (config == null) {
|
||||||
config = Config(app)
|
config = Config(app)
|
||||||
}
|
}
|
||||||
return constructUrl(config,"favicons", icon)
|
return constructUrl(config, "favicons", icon)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
data class Item(@SerializedName("id") val id: String,
|
data class Item(
|
||||||
@SerializedName("datetime") val datetime: String,
|
@SerializedName("id") val id: String,
|
||||||
@SerializedName("title") val title: String,
|
@SerializedName("datetime") val datetime: String,
|
||||||
@SerializedName("unread") val unread: Boolean,
|
@SerializedName("title") val title: String,
|
||||||
@SerializedName("starred") val starred: Boolean,
|
@SerializedName("content") val content: String,
|
||||||
@SerializedName("thumbnail") val thumbnail: String,
|
@SerializedName("unread") val unread: Boolean,
|
||||||
@SerializedName("icon") val icon: String,
|
@SerializedName("starred") val starred: Boolean,
|
||||||
@SerializedName("link") val link: String,
|
@SerializedName("thumbnail") val thumbnail: String,
|
||||||
@SerializedName("sourcetitle") val sourcetitle: String) : Parcelable {
|
@SerializedName("icon") val icon: String,
|
||||||
|
@SerializedName("link") val link: String,
|
||||||
|
@SerializedName("sourcetitle") val sourcetitle: String
|
||||||
|
) : Parcelable {
|
||||||
|
|
||||||
var config: Config? = null
|
var config: Config? = null
|
||||||
|
|
||||||
@ -72,15 +83,16 @@ data class Item(@SerializedName("id") val id: String,
|
|||||||
}
|
}
|
||||||
|
|
||||||
constructor(source: Parcel) : this(
|
constructor(source: Parcel) : this(
|
||||||
id = source.readString(),
|
id = source.readString(),
|
||||||
datetime = source.readString(),
|
datetime = source.readString(),
|
||||||
title = source.readString(),
|
title = source.readString(),
|
||||||
unread = 0.toByte() != source.readByte(),
|
content = source.readString(),
|
||||||
starred = 0.toByte() != source.readByte(),
|
unread = 0.toByte() != source.readByte(),
|
||||||
thumbnail = source.readString(),
|
starred = 0.toByte() != source.readByte(),
|
||||||
icon = source.readString(),
|
thumbnail = source.readString(),
|
||||||
link = source.readString(),
|
icon = source.readString(),
|
||||||
sourcetitle = source.readString()
|
link = source.readString(),
|
||||||
|
sourcetitle = source.readString()
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun describeContents() = 0
|
override fun describeContents() = 0
|
||||||
@ -89,6 +101,7 @@ data class Item(@SerializedName("id") val id: String,
|
|||||||
dest.writeString(id)
|
dest.writeString(id)
|
||||||
dest.writeString(datetime)
|
dest.writeString(datetime)
|
||||||
dest.writeString(title)
|
dest.writeString(title)
|
||||||
|
dest.writeString(content)
|
||||||
dest.writeByte((if (unread) 1 else 0))
|
dest.writeByte((if (unread) 1 else 0))
|
||||||
dest.writeByte((if (starred) 1 else 0))
|
dest.writeByte((if (starred) 1 else 0))
|
||||||
dest.writeString(thumbnail)
|
dest.writeString(thumbnail)
|
||||||
@ -114,21 +127,26 @@ data class Item(@SerializedName("id") val id: String,
|
|||||||
// TODO: maybe find a better way to handle these kind of urls
|
// TODO: maybe find a better way to handle these kind of urls
|
||||||
fun getLinkDecoded(): String {
|
fun getLinkDecoded(): String {
|
||||||
var stringUrl: String
|
var stringUrl: String
|
||||||
if (link.startsWith("http://news.google.com/news/") || link.startsWith("https://news.google.com/news/")) {
|
stringUrl = if (link.startsWith("http://news.google.com/news/") || link.startsWith("https://news.google.com/news/")) {
|
||||||
if (link.contains("&url=")) {
|
if (link.contains("&url=")) {
|
||||||
stringUrl = link.substringAfter("&url=")
|
link.substringAfter("&url=")
|
||||||
} else {
|
} else {
|
||||||
stringUrl = this.link.replace("&", "&")
|
this.link.replace("&", "&")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
stringUrl = this.link.replace("&", "&")
|
this.link.replace("&", "&")
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle :443 => https
|
// handle :443 => https
|
||||||
if (stringUrl.contains(":443")) {
|
if (stringUrl.contains(":443")) {
|
||||||
stringUrl = stringUrl.replace(":443", "").replace("http://", "https://")
|
stringUrl = stringUrl.replace(":443", "").replace("http://", "https://")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handle url not starting with http
|
||||||
|
if (stringUrl.startsWith("//")) {
|
||||||
|
stringUrl = "http:" + stringUrl
|
||||||
|
}
|
||||||
|
|
||||||
return stringUrl
|
return stringUrl
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -5,92 +5,114 @@ import retrofit2.http.DELETE
|
|||||||
import retrofit2.http.Field
|
import retrofit2.http.Field
|
||||||
import retrofit2.http.FormUrlEncoded
|
import retrofit2.http.FormUrlEncoded
|
||||||
import retrofit2.http.GET
|
import retrofit2.http.GET
|
||||||
|
import retrofit2.http.Headers
|
||||||
import retrofit2.http.POST
|
import retrofit2.http.POST
|
||||||
import retrofit2.http.Path
|
import retrofit2.http.Path
|
||||||
import retrofit2.http.Query
|
import retrofit2.http.Query
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// codebeat:disable[ARITY]
|
|
||||||
internal interface SelfossService {
|
internal interface SelfossService {
|
||||||
|
|
||||||
@GET("login")
|
@GET("login")
|
||||||
fun loginToSelfoss(@Query("username") username: String, @Query("password") password: String): Call<SuccessResponse>
|
fun loginToSelfoss(@Query("username") username: String, @Query("password") password: String): Call<SuccessResponse>
|
||||||
|
|
||||||
@GET("items")
|
@GET("items")
|
||||||
fun getItems(@Query("type") type: String,
|
fun getItems(
|
||||||
@Query("tag") tag: String?,
|
@Query("type") type: String,
|
||||||
@Query("source") source: Long?,
|
@Query("tag") tag: String?,
|
||||||
@Query("search") search: String?,
|
@Query("source") source: Long?,
|
||||||
@Query("username") username: String,
|
@Query("search") search: String?,
|
||||||
@Query("password") password: String,
|
@Query("username") username: String,
|
||||||
@Query("items") items: Int): Call<List<Item>>
|
@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}")
|
@POST("mark/{id}")
|
||||||
fun markAsRead(@Path("id") id: String,
|
fun markAsRead(
|
||||||
@Query("username") username: String,
|
@Path("id") id: String,
|
||||||
@Query("password") password: String): Call<SuccessResponse>
|
@Query("username") username: String,
|
||||||
|
@Query("password") password: String
|
||||||
|
): Call<SuccessResponse>
|
||||||
|
|
||||||
|
@Headers("Content-Type: application/x-www-form-urlencoded")
|
||||||
@POST("unmark/{id}")
|
@POST("unmark/{id}")
|
||||||
fun unmarkAsRead(@Path("id") id: String,
|
fun unmarkAsRead(
|
||||||
@Query("username") username: String,
|
@Path("id") id: String,
|
||||||
@Query("password") password: String): Call<SuccessResponse>
|
@Query("username") username: String,
|
||||||
|
@Query("password") password: String
|
||||||
|
): Call<SuccessResponse>
|
||||||
|
|
||||||
@FormUrlEncoded
|
@FormUrlEncoded
|
||||||
@POST("mark")
|
@POST("mark")
|
||||||
fun markAllAsRead(@Field("ids[]") ids: List<String>,
|
fun markAllAsRead(
|
||||||
@Query("username") username: String,
|
@Field("ids[]") ids: List<String>,
|
||||||
@Query("password") password: String): Call<SuccessResponse>
|
@Query("username") username: String,
|
||||||
|
@Query("password") password: String
|
||||||
|
): Call<SuccessResponse>
|
||||||
|
|
||||||
|
@Headers("Content-Type: application/x-www-form-urlencoded")
|
||||||
@POST("starr/{id}")
|
@POST("starr/{id}")
|
||||||
fun starr(@Path("id") id: String,
|
fun starr(
|
||||||
@Query("username") username: String,
|
@Path("id") id: String,
|
||||||
@Query("password") password: String): Call<SuccessResponse>
|
@Query("username") username: String,
|
||||||
|
@Query("password") password: String
|
||||||
|
): Call<SuccessResponse>
|
||||||
|
|
||||||
|
@Headers("Content-Type: application/x-www-form-urlencoded")
|
||||||
@POST("unstarr/{id}")
|
@POST("unstarr/{id}")
|
||||||
fun unstarr(@Path("id") id: String,
|
fun unstarr(
|
||||||
@Query("username") username: String,
|
@Path("id") id: String,
|
||||||
@Query("password") password: String): Call<SuccessResponse>
|
@Query("username") username: String,
|
||||||
|
@Query("password") password: String
|
||||||
|
): Call<SuccessResponse>
|
||||||
|
|
||||||
@GET("stats")
|
@GET("stats")
|
||||||
fun stats(@Query("username") username: String,
|
fun stats(
|
||||||
@Query("password") password: String): Call<Stats>
|
@Query("username") username: String,
|
||||||
|
@Query("password") password: String
|
||||||
|
): Call<Stats>
|
||||||
|
|
||||||
@GET("tags")
|
@GET("tags")
|
||||||
fun tags(@Query("username") username: String,
|
fun tags(
|
||||||
@Query("password") password: String): Call<List<Tag>>
|
@Query("username") username: String,
|
||||||
|
@Query("password") password: String
|
||||||
|
): Call<List<Tag>>
|
||||||
|
|
||||||
@GET("update")
|
@GET("update")
|
||||||
fun update(@Query("username") username: String,
|
fun update(
|
||||||
@Query("password") password: String): Call<String>
|
@Query("username") username: String,
|
||||||
|
@Query("password") password: String
|
||||||
|
): Call<String>
|
||||||
|
|
||||||
@GET("sources/spouts")
|
@GET("sources/spouts")
|
||||||
fun spouts(@Query("username") username: String,
|
fun spouts(
|
||||||
@Query("password") password: String): Call<Map<String, Spout>>
|
@Query("username") username: String,
|
||||||
|
@Query("password") password: String
|
||||||
|
): Call<Map<String, Spout>>
|
||||||
|
|
||||||
@GET("sources/list")
|
@GET("sources/list")
|
||||||
fun sources(@Query("username") username: String,
|
fun sources(
|
||||||
@Query("password") password: String): Call<List<Sources>>
|
@Query("username") username: String,
|
||||||
|
@Query("password") password: String
|
||||||
|
): Call<List<Sources>>
|
||||||
|
|
||||||
@DELETE("source/{id}")
|
@DELETE("source/{id}")
|
||||||
fun deleteSource(@Path("id") id: String,
|
fun deleteSource(
|
||||||
@Query("username") username: String,
|
@Path("id") id: String,
|
||||||
@Query("password") password: String): Call<SuccessResponse>
|
@Query("username") username: String,
|
||||||
|
@Query("password") password: String
|
||||||
|
): Call<SuccessResponse>
|
||||||
|
|
||||||
@FormUrlEncoded
|
@FormUrlEncoded
|
||||||
@POST("source")
|
@POST("source")
|
||||||
fun createSource(@Field("title") title: String,
|
fun createSource(
|
||||||
@Field("url") url: String,
|
@Field("title") title: String,
|
||||||
@Field("spout") spout: String,
|
@Field("url") url: String,
|
||||||
@Field("tags") tags: String,
|
@Field("spout") spout: String,
|
||||||
@Field("filter") filter: String,
|
@Field("tags") tags: String,
|
||||||
@Query("username") username: String,
|
@Field("filter") filter: String,
|
||||||
@Query("password") password: String): Call<SuccessResponse>
|
@Query("username") username: String,
|
||||||
|
@Query("password") password: String
|
||||||
|
): Call<SuccessResponse>
|
||||||
}
|
}
|
||||||
// codebeat:disable[ARITY]
|
|
@ -0,0 +1,241 @@
|
|||||||
|
package apps.amine.bou.readerforselfoss.fragments
|
||||||
|
|
||||||
|
import android.content.SharedPreferences
|
||||||
|
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.widget.NestedScrollView
|
||||||
|
import android.text.Html
|
||||||
|
import android.text.method.LinkMovementMethod
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.MenuItem
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
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.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 com.bumptech.glide.Glide
|
||||||
|
import com.bumptech.glide.request.RequestOptions
|
||||||
|
import com.crashlytics.android.Crashlytics
|
||||||
|
import com.github.rubensousa.floatingtoolbar.FloatingToolbar
|
||||||
|
import org.sufficientlysecure.htmltextview.HtmlHttpImageGetter
|
||||||
|
import retrofit2.Call
|
||||||
|
import retrofit2.Callback
|
||||||
|
import retrofit2.Response
|
||||||
|
|
||||||
|
|
||||||
|
import kotlinx.android.synthetic.main.fragment_article.view.*
|
||||||
|
|
||||||
|
class ArticleFragment : Fragment() {
|
||||||
|
private lateinit var pageNumber: Number
|
||||||
|
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 lateinit var fab: FloatingActionButton
|
||||||
|
|
||||||
|
override fun onStop() {
|
||||||
|
super.onStop()
|
||||||
|
mCustomTabActivityHelper.unbindCustomTabsService(activity)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
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?
|
||||||
|
): View? {
|
||||||
|
rootView = inflater
|
||||||
|
.inflate(R.layout.fragment_article, container, false) as ViewGroup
|
||||||
|
|
||||||
|
url = allItems[pageNumber.toInt()].getLinkDecoded()
|
||||||
|
contentText = allItems[pageNumber.toInt()].content
|
||||||
|
contentTitle = allItems[pageNumber.toInt()].title
|
||||||
|
contentImage = allItems[pageNumber.toInt()].getThumbnail(activity!!)
|
||||||
|
contentSource = allItems[pageNumber.toInt()].sourceAndDateText()
|
||||||
|
|
||||||
|
fab = rootView.fab
|
||||||
|
val mFloatingToolbar: FloatingToolbar = rootView.floatingToolbar
|
||||||
|
mFloatingToolbar.attachFab(fab)
|
||||||
|
|
||||||
|
val customTabsIntent = activity!!.buildCustomTabsIntent()
|
||||||
|
mCustomTabActivityHelper = CustomTabActivityHelper()
|
||||||
|
mCustomTabActivityHelper.bindCustomTabsService(activity)
|
||||||
|
|
||||||
|
val prefs = PreferenceManager.getDefaultSharedPreferences(activity)
|
||||||
|
|
||||||
|
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(
|
||||||
|
allItems,
|
||||||
|
pageNumber.toInt(),
|
||||||
|
url,
|
||||||
|
customTabsIntent,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
activity!!
|
||||||
|
)
|
||||||
|
else -> Unit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onItemLongClick(item: MenuItem?) {
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
if (contentText.isEmptyOrNullOrNullString()) {
|
||||||
|
getContentFromMercury(customTabsIntent, prefs)
|
||||||
|
} else {
|
||||||
|
rootView.source.text = contentSource
|
||||||
|
rootView.titleView.text = contentTitle
|
||||||
|
tryToHandleHtml(contentText, customTabsIntent, prefs)
|
||||||
|
|
||||||
|
if (!contentImage.isEmptyOrNullOrNullString()) {
|
||||||
|
rootView.imageView.visibility = View.VISIBLE
|
||||||
|
Glide
|
||||||
|
.with(activity!!.baseContext)
|
||||||
|
.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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
rootView.content.movementMethod = LinkMovementMethod.getInstance()
|
||||||
|
|
||||||
|
return rootView
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getContentFromMercury(
|
||||||
|
customTabsIntent: CustomTabsIntent,
|
||||||
|
prefs: SharedPreferences
|
||||||
|
) {
|
||||||
|
rootView.progressBar.visibility = View.VISIBLE
|
||||||
|
val parser = MercuryApi(
|
||||||
|
BuildConfig.MERCURY_KEY,
|
||||||
|
prefs.getBoolean("should_log_everything", false)
|
||||||
|
)
|
||||||
|
|
||||||
|
parser.parseUrl(url).enqueue(object : Callback<ParsedContent> {
|
||||||
|
override fun onResponse(
|
||||||
|
call: Call<ParsedContent>,
|
||||||
|
response: Response<ParsedContent>
|
||||||
|
) {
|
||||||
|
if (response.body() != null && response.body()!!.content != null && response.body()!!.content.isNotEmpty()) {
|
||||||
|
rootView.source.text = response.body()!!.domain
|
||||||
|
rootView.titleView.text = response.body()!!.title
|
||||||
|
url = response.body()!!.url
|
||||||
|
|
||||||
|
if (response.body()!!.content != null && !response.body()!!.content.isEmpty()) {
|
||||||
|
tryToHandleHtml(response.body()!!.content, customTabsIntent, prefs)
|
||||||
|
}
|
||||||
|
|
||||||
|
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(
|
||||||
|
call: Call<ParsedContent>,
|
||||||
|
t: Throwable
|
||||||
|
) = openInBrowserAfterFailing(customTabsIntent)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun tryToHandleHtml(
|
||||||
|
c: String,
|
||||||
|
customTabsIntent: CustomTabsIntent,
|
||||||
|
prefs: SharedPreferences
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
rootView.content.text = Html.fromHtml(c, HtmlHttpImageGetter(rootView.content, null, true), null)
|
||||||
|
|
||||||
|
//content.setHtml(response.body()!!.content, HtmlHttpImageGetter(content, null, true))
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Crashlytics.setUserIdentifier(prefs.getString("unique_id", ""))
|
||||||
|
Crashlytics.log(100, "CANT_TRANSFORM_TO_HTML", e.message)
|
||||||
|
Crashlytics.logException(e)
|
||||||
|
openInBrowserAfterFailing(customTabsIntent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun openInBrowserAfterFailing(customTabsIntent: CustomTabsIntent) {
|
||||||
|
rootView.progressBar.visibility = View.GONE
|
||||||
|
activity!!.openItemUrl(
|
||||||
|
allItems,
|
||||||
|
pageNumber.toInt(),
|
||||||
|
url,
|
||||||
|
customTabsIntent,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
activity!!
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val ARG_POSITION = "position"
|
||||||
|
private val ARG_ITEMS = "items"
|
||||||
|
|
||||||
|
fun newInstance(position: Int, allItems: ArrayList<Item>): ArticleFragment {
|
||||||
|
val fragment = ArticleFragment()
|
||||||
|
val args = Bundle()
|
||||||
|
args.putInt(ARG_POSITION, position)
|
||||||
|
args.putParcelableArrayList(ARG_ITEMS, allItems)
|
||||||
|
fragment.arguments = args
|
||||||
|
return fragment
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -24,7 +24,7 @@ import com.ftinc.scoop.Scoop;
|
|||||||
* A {@link PreferenceActivity} which implements and proxies the necessary calls
|
* A {@link PreferenceActivity} which implements and proxies the necessary calls
|
||||||
* to be used with AppCompat.
|
* to be used with AppCompat.
|
||||||
*/
|
*/
|
||||||
public abstract class AppCompatPreferenceActivity extends PreferenceActivity {
|
public abstract class AppCompatPreferenceActivity extends PreferenceActivity { //NOSONAR
|
||||||
|
|
||||||
private AppCompatDelegate mDelegate;
|
private AppCompatDelegate mDelegate;
|
||||||
|
|
||||||
@ -116,6 +116,7 @@ public abstract class AppCompatPreferenceActivity extends PreferenceActivity {
|
|||||||
getDelegate().onDestroy();
|
getDelegate().onDestroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void invalidateOptionsMenu() {
|
public void invalidateOptionsMenu() {
|
||||||
getDelegate().invalidateOptionsMenu();
|
getDelegate().invalidateOptionsMenu();
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package apps.amine.bou.readerforselfoss.settings;
|
package apps.amine.bou.readerforselfoss.settings;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import android.annotation.TargetApi;
|
import android.annotation.TargetApi;
|
||||||
import android.content.ClipData;
|
import android.content.ClipData;
|
||||||
import android.content.ClipboardManager;
|
import android.content.ClipboardManager;
|
||||||
@ -16,17 +18,15 @@ import android.preference.Preference;
|
|||||||
import android.preference.Preference.OnPreferenceChangeListener;
|
import android.preference.Preference.OnPreferenceChangeListener;
|
||||||
import android.preference.Preference.OnPreferenceClickListener;
|
import android.preference.Preference.OnPreferenceClickListener;
|
||||||
import android.preference.PreferenceActivity;
|
import android.preference.PreferenceActivity;
|
||||||
import android.preference.SwitchPreference;
|
|
||||||
import android.support.v7.app.ActionBar;
|
|
||||||
import android.preference.PreferenceFragment;
|
import android.preference.PreferenceFragment;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
|
import android.preference.SwitchPreference;
|
||||||
|
import android.support.v7.app.ActionBar;
|
||||||
import android.text.InputFilter;
|
import android.text.InputFilter;
|
||||||
import android.text.Spanned;
|
import android.text.Spanned;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import apps.amine.bou.readerforselfoss.BuildConfig;
|
import apps.amine.bou.readerforselfoss.BuildConfig;
|
||||||
import apps.amine.bou.readerforselfoss.R;
|
import apps.amine.bou.readerforselfoss.R;
|
||||||
import apps.amine.bou.readerforselfoss.utils.Config;
|
import apps.amine.bou.readerforselfoss.utils.Config;
|
||||||
@ -44,7 +44,7 @@ import com.ftinc.scoop.ui.ScoopSettingsActivity;
|
|||||||
* href="http://developer.android.com/guide/topics/ui/settings.html">Settings
|
* href="http://developer.android.com/guide/topics/ui/settings.html">Settings
|
||||||
* API Guide</a> for more information on developing a Settings UI.
|
* API Guide</a> for more information on developing a Settings UI.
|
||||||
*/
|
*/
|
||||||
public class SettingsActivity extends AppCompatPreferenceActivity {
|
public class SettingsActivity extends AppCompatPreferenceActivity { //NOSONAR
|
||||||
/**
|
/**
|
||||||
* A preference value change listener that updates the preference's summary
|
* A preference value change listener that updates the preference's summary
|
||||||
* to reflect its new value.
|
* to reflect its new value.
|
||||||
@ -126,6 +126,7 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
|
|||||||
* This method stops fragment injection in malicious applications.
|
* This method stops fragment injection in malicious applications.
|
||||||
* Make sure to deny any unknown fragments here.
|
* Make sure to deny any unknown fragments here.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
protected boolean isValidFragment(String fragmentName) {
|
protected boolean isValidFragment(String fragmentName) {
|
||||||
return PreferenceFragment.class.getName().equals(fragmentName)
|
return PreferenceFragment.class.getName().equals(fragmentName)
|
||||||
|| GeneralPreferenceFragment.class.getName().equals(fragmentName)
|
|| GeneralPreferenceFragment.class.getName().equals(fragmentName)
|
||||||
@ -166,7 +167,9 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
|
|||||||
int input = Integer.parseInt(dest.toString() + source.toString());
|
int input = Integer.parseInt(dest.toString() + source.toString());
|
||||||
if (input <= 200 && input >0)
|
if (input <= 200 && input >0)
|
||||||
return null;
|
return null;
|
||||||
} catch (NumberFormatException nfe) { }
|
} catch (NumberFormatException nfe) {
|
||||||
|
Toast.makeText(getActivity(), R.string.items_number_should_be_number, Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -255,6 +258,14 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
findPreference("translation").setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onPreferenceClick(Preference preference) {
|
||||||
|
openUrl(Uri.parse(BuildConfig.TRANSLATION_URL));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -5,9 +5,6 @@ import android.content.Context
|
|||||||
import android.support.annotation.ColorInt
|
import android.support.annotation.ColorInt
|
||||||
import android.util.TypedValue
|
import android.util.TypedValue
|
||||||
import apps.amine.bou.readerforselfoss.R
|
import apps.amine.bou.readerforselfoss.R
|
||||||
import java.lang.reflect.AccessibleObject.setAccessible
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class AppColors(a: Activity) {
|
class AppColors(a: Activity) {
|
||||||
@ColorInt val accent: Int
|
@ColorInt val accent: Int
|
||||||
@ -22,7 +19,7 @@ class AppColors(a: Activity) {
|
|||||||
val method = wrapper!!.getMethod("getThemeResId")
|
val method = wrapper!!.getMethod("getThemeResId")
|
||||||
method.isAccessible = true
|
method.isAccessible = true
|
||||||
|
|
||||||
isDarkTheme = when(method.invoke(a.baseContext)) {
|
isDarkTheme = when (method.invoke(a.baseContext)) {
|
||||||
R.style.NoBarTealOrangeDark,
|
R.style.NoBarTealOrangeDark,
|
||||||
R.style.NoBarDark,
|
R.style.NoBarDark,
|
||||||
R.style.NoBarBlueAmberDark,
|
R.style.NoBarBlueAmberDark,
|
||||||
|
@ -0,0 +1,43 @@
|
|||||||
|
package apps.amine.bou.readerforselfoss.transformers
|
||||||
|
|
||||||
|
import android.support.v4.view.ViewPager
|
||||||
|
import android.view.View
|
||||||
|
|
||||||
|
class DepthPageTransformer : ViewPager.PageTransformer {
|
||||||
|
|
||||||
|
override fun transformPage(view: View, position: Float) {
|
||||||
|
val pageWidth = view.width
|
||||||
|
|
||||||
|
when {
|
||||||
|
position < -1 -> // [-Infinity,-1)
|
||||||
|
// This page is way off-screen to the left.
|
||||||
|
view.alpha = 0F
|
||||||
|
position <= 0 -> { // [-1,0]
|
||||||
|
// Use the default slide transition when moving to the left page
|
||||||
|
view.alpha = 1F
|
||||||
|
view.translationX = 0F
|
||||||
|
view.scaleX = 1F
|
||||||
|
view.scaleY = 1F
|
||||||
|
}
|
||||||
|
position <= 1 -> { // (0,1]
|
||||||
|
// Fade the page out.
|
||||||
|
view.alpha = 1 - position
|
||||||
|
|
||||||
|
// Counteract the default slide transition
|
||||||
|
view.translationX = pageWidth * -position
|
||||||
|
|
||||||
|
// Scale the page down (between MIN_SCALE and 1)
|
||||||
|
val scaleFactor = MIN_SCALE + (1 - MIN_SCALE) * (1 - Math.abs(position))
|
||||||
|
view.scaleX = scaleFactor
|
||||||
|
view.scaleY = scaleFactor
|
||||||
|
}
|
||||||
|
else -> // (1,+Infinity]
|
||||||
|
// This page is way off-screen to the right.
|
||||||
|
view.alpha = 0F
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val MIN_SCALE = 0.75f
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package apps.amine.bou.readerforselfoss.utils
|
||||||
|
|
||||||
|
import apps.amine.bou.readerforselfoss.api.selfoss.SuccessResponse
|
||||||
|
import retrofit2.Response
|
||||||
|
|
||||||
|
fun Response<SuccessResponse>.succeeded(): Boolean =
|
||||||
|
this.code() === 200 && this.body() != null && this.body()!!.isSuccess
|
@ -5,57 +5,17 @@ import android.content.Intent
|
|||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.support.v7.app.AlertDialog
|
import android.support.v7.app.AlertDialog
|
||||||
import android.text.TextUtils
|
|
||||||
import android.util.Patterns
|
|
||||||
|
|
||||||
import com.google.firebase.remoteconfig.FirebaseRemoteConfig
|
|
||||||
import okhttp3.HttpUrl
|
|
||||||
|
|
||||||
import apps.amine.bou.readerforselfoss.BuildConfig
|
|
||||||
import apps.amine.bou.readerforselfoss.R
|
import apps.amine.bou.readerforselfoss.R
|
||||||
import apps.amine.bou.readerforselfoss.api.selfoss.Item
|
import com.google.firebase.remoteconfig.FirebaseRemoteConfig
|
||||||
|
|
||||||
|
|
||||||
fun Context.checkAndDisplayStoreApk() = {
|
|
||||||
fun isStoreVersion(): Boolean =
|
|
||||||
try {
|
|
||||||
val installer = this.packageManager
|
|
||||||
.getInstallerPackageName(this.packageName)
|
|
||||||
!TextUtils.isEmpty(installer)
|
|
||||||
} catch (e: Throwable) {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isStoreVersion() && !BuildConfig.GITHUB_VERSION) {
|
|
||||||
val alertDialog = AlertDialog.Builder(this).create()
|
|
||||||
alertDialog.setTitle(getString(R.string.warning_version))
|
|
||||||
alertDialog.setMessage(getString(R.string.text_version))
|
|
||||||
alertDialog.setButton(AlertDialog.BUTTON_NEUTRAL, "OK",
|
|
||||||
{ dialog, _ -> dialog.dismiss() })
|
|
||||||
alertDialog.show()
|
|
||||||
} else Unit
|
|
||||||
}
|
|
||||||
|
|
||||||
fun String.isUrlValid(): Boolean =
|
|
||||||
HttpUrl.parse(this) != null && Patterns.WEB_URL.matcher(this).matches()
|
|
||||||
|
|
||||||
fun String.isBaseUrlValid(): Boolean {
|
|
||||||
val baseUrl = HttpUrl.parse(this)
|
|
||||||
var existsAndEndsWithSlash = false
|
|
||||||
if (baseUrl != null) {
|
|
||||||
val pathSegments = baseUrl.pathSegments()
|
|
||||||
existsAndEndsWithSlash = "" == pathSegments[pathSegments.size - 1]
|
|
||||||
}
|
|
||||||
|
|
||||||
return Patterns.WEB_URL.matcher(this).matches() && existsAndEndsWithSlash
|
|
||||||
}
|
|
||||||
|
|
||||||
fun String?.isEmptyOrNullOrNullString(): Boolean =
|
fun String?.isEmptyOrNullOrNullString(): Boolean =
|
||||||
this == null || this == "null" || this.isEmpty()
|
this == null || this == "null" || this.isEmpty()
|
||||||
|
|
||||||
fun Context.checkApkVersion(settings: SharedPreferences,
|
fun Context.checkApkVersion(
|
||||||
editor: SharedPreferences.Editor,
|
settings: SharedPreferences,
|
||||||
mFirebaseRemoteConfig: FirebaseRemoteConfig) = {
|
editor: SharedPreferences.Editor,
|
||||||
|
mFirebaseRemoteConfig: FirebaseRemoteConfig
|
||||||
|
) = {
|
||||||
fun isThereAnUpdate() {
|
fun isThereAnUpdate() {
|
||||||
val APK_LINK = "github_apk"
|
val APK_LINK = "github_apk"
|
||||||
|
|
||||||
@ -65,31 +25,35 @@ fun Context.checkApkVersion(settings: SharedPreferences,
|
|||||||
val alertDialog = AlertDialog.Builder(this).create()
|
val alertDialog = AlertDialog.Builder(this).create()
|
||||||
alertDialog.setTitle(getString(R.string.new_apk_available_title))
|
alertDialog.setTitle(getString(R.string.new_apk_available_title))
|
||||||
alertDialog.setMessage(getString(R.string.new_apk_available_message))
|
alertDialog.setMessage(getString(R.string.new_apk_available_message))
|
||||||
alertDialog.setButton(AlertDialog.BUTTON_POSITIVE, getString(R.string.new_apk_available_get)) { _, _ ->
|
alertDialog.setButton(
|
||||||
|
AlertDialog.BUTTON_POSITIVE,
|
||||||
|
getString(R.string.new_apk_available_get)
|
||||||
|
) { _, _ ->
|
||||||
editor.putString(APK_LINK, apkLink)
|
editor.putString(APK_LINK, apkLink)
|
||||||
editor.apply()
|
editor.apply()
|
||||||
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(apkLink))
|
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(apkLink))
|
||||||
startActivity(browserIntent)
|
startActivity(browserIntent)
|
||||||
}
|
}
|
||||||
alertDialog.setButton(AlertDialog.BUTTON_NEUTRAL, getString(R.string.new_apk_available_no),
|
alertDialog.setButton(
|
||||||
{ dialog, _ ->
|
AlertDialog.BUTTON_NEUTRAL, getString(R.string.new_apk_available_no),
|
||||||
editor.putString(APK_LINK, apkLink)
|
{ dialog, _ ->
|
||||||
editor.apply()
|
editor.putString(APK_LINK, apkLink)
|
||||||
dialog.dismiss()
|
editor.apply()
|
||||||
})
|
dialog.dismiss()
|
||||||
|
}
|
||||||
|
)
|
||||||
alertDialog.show()
|
alertDialog.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mFirebaseRemoteConfig.fetch(43200)
|
mFirebaseRemoteConfig.fetch(43200)
|
||||||
.addOnCompleteListener { task ->
|
.addOnCompleteListener { task ->
|
||||||
if (task.isSuccessful) {
|
if (task.isSuccessful) {
|
||||||
mFirebaseRemoteConfig.activateFetched()
|
mFirebaseRemoteConfig.activateFetched()
|
||||||
}
|
}
|
||||||
|
|
||||||
isThereAnUpdate()
|
isThereAnUpdate()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun String.longHash(): Long {
|
fun String.longHash(): Long {
|
||||||
@ -97,17 +61,18 @@ fun String.longHash(): Long {
|
|||||||
val l = this.length
|
val l = this.length
|
||||||
val chars = this.toCharArray()
|
val chars = this.toCharArray()
|
||||||
|
|
||||||
for (i in 0..l - 1) {
|
for (i in 0 until l) {
|
||||||
h = 31 * h + chars[i].toLong()
|
h = 31 * h + chars[i].toLong()
|
||||||
}
|
}
|
||||||
return h
|
return h
|
||||||
}
|
}
|
||||||
|
|
||||||
fun String.toStringUriWithHttp() =
|
fun String.toStringUriWithHttp(): String =
|
||||||
if (!this.startsWith("https://") && !this.startsWith("http://"))
|
if (!this.startsWith("https://") && !this.startsWith("http://")) {
|
||||||
"http://" + this
|
"http://" + this
|
||||||
else
|
} else {
|
||||||
this
|
this
|
||||||
|
}
|
||||||
|
|
||||||
fun Context.shareLink(itemUrl: String) {
|
fun Context.shareLink(itemUrl: String) {
|
||||||
val sendIntent = Intent()
|
val sendIntent = Intent()
|
||||||
@ -115,12 +80,10 @@ fun Context.shareLink(itemUrl: String) {
|
|||||||
sendIntent.action = Intent.ACTION_SEND
|
sendIntent.action = Intent.ACTION_SEND
|
||||||
sendIntent.putExtra(Intent.EXTRA_TEXT, itemUrl.toStringUriWithHttp())
|
sendIntent.putExtra(Intent.EXTRA_TEXT, itemUrl.toStringUriWithHttp())
|
||||||
sendIntent.type = "text/plain"
|
sendIntent.type = "text/plain"
|
||||||
startActivity(Intent.createChooser(sendIntent, getString(R.string.share)).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK))
|
startActivity(
|
||||||
}
|
Intent.createChooser(
|
||||||
|
sendIntent,
|
||||||
fun Context.openInBrowser(i: Item) {
|
getString(R.string.share)
|
||||||
val intent = Intent(Intent.ACTION_VIEW)
|
).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
)
|
||||||
intent.data = Uri.parse(i.getLinkDecoded().toStringUriWithHttp())
|
|
||||||
startActivity(intent)
|
|
||||||
}
|
}
|
@ -6,7 +6,6 @@ import android.content.Intent
|
|||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import apps.amine.bou.readerforselfoss.LoginActivity
|
import apps.amine.bou.readerforselfoss.LoginActivity
|
||||||
|
|
||||||
|
|
||||||
class Config(c: Context) {
|
class Config(c: Context) {
|
||||||
|
|
||||||
val settings: SharedPreferences = c.getSharedPreferences(settingsName, Context.MODE_PRIVATE)
|
val settings: SharedPreferences = c.getSharedPreferences(settingsName, Context.MODE_PRIVATE)
|
||||||
@ -26,21 +25,23 @@ class Config(c: Context) {
|
|||||||
val httpUserPassword: String
|
val httpUserPassword: String
|
||||||
get() = settings.getString("httpPassword", "")
|
get() = settings.getString("httpPassword", "")
|
||||||
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val settingsName = "paramsselfoss"
|
val settingsName = "paramsselfoss"
|
||||||
|
|
||||||
fun logoutAndRedirect(c: Context,
|
fun logoutAndRedirect(
|
||||||
callingActivity: Activity,
|
c: Context,
|
||||||
editor: SharedPreferences.Editor,
|
callingActivity: Activity,
|
||||||
baseUrlFail: Boolean = false): Boolean {
|
editor: SharedPreferences.Editor,
|
||||||
|
baseUrlFail: Boolean = false
|
||||||
|
): Boolean {
|
||||||
editor.remove("url")
|
editor.remove("url")
|
||||||
editor.remove("login")
|
editor.remove("login")
|
||||||
editor.remove("password")
|
editor.remove("password")
|
||||||
editor.apply()
|
editor.apply()
|
||||||
val intent = Intent(c, LoginActivity::class.java)
|
val intent = Intent(c, LoginActivity::class.java)
|
||||||
if (baseUrlFail)
|
if (baseUrlFail) {
|
||||||
intent.putExtra("baseUrlFail", baseUrlFail)
|
intent.putExtra("baseUrlFail", baseUrlFail)
|
||||||
|
}
|
||||||
c.startActivity(intent)
|
c.startActivity(intent)
|
||||||
callingActivity.finish()
|
callingActivity.finish()
|
||||||
return true
|
return true
|
||||||
|
@ -8,32 +8,36 @@ import javax.net.ssl.TrustManager
|
|||||||
import javax.net.ssl.X509TrustManager
|
import javax.net.ssl.X509TrustManager
|
||||||
|
|
||||||
fun getUnsafeHttpClient() =
|
fun getUnsafeHttpClient() =
|
||||||
try {
|
try {
|
||||||
// Create a trust manager that does not validate certificate chains
|
// Create a trust manager that does not validate certificate chains
|
||||||
val trustAllCerts = arrayOf<TrustManager>(object : X509TrustManager {
|
val trustAllCerts = arrayOf<TrustManager>(object : X509TrustManager {
|
||||||
override fun getAcceptedIssuers(): Array<X509Certificate> =
|
override fun getAcceptedIssuers(): Array<X509Certificate> =
|
||||||
arrayOf()
|
arrayOf()
|
||||||
|
|
||||||
@Throws(CertificateException::class)
|
@Throws(CertificateException::class)
|
||||||
override fun checkClientTrusted(chain: Array<java.security.cert.X509Certificate>, authType: String) {
|
override fun checkClientTrusted(
|
||||||
}
|
chain: Array<java.security.cert.X509Certificate>,
|
||||||
|
authType: String
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
@Throws(CertificateException::class)
|
@Throws(CertificateException::class)
|
||||||
override fun checkServerTrusted(chain: Array<java.security.cert.X509Certificate>, authType: String) {
|
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 sslSocketFactory = sslContext.socketFactory
|
||||||
val sslContext = SSLContext.getInstance("SSL")
|
|
||||||
sslContext.init(null, trustAllCerts, java.security.SecureRandom())
|
|
||||||
|
|
||||||
val sslSocketFactory = sslContext.socketFactory
|
OkHttpClient.Builder()
|
||||||
|
.sslSocketFactory(sslSocketFactory, trustAllCerts[0] as X509TrustManager)
|
||||||
OkHttpClient.Builder()
|
.hostnameVerifier { _, _ -> true }
|
||||||
.sslSocketFactory(sslSocketFactory, trustAllCerts[0] as X509TrustManager)
|
} catch (e: Exception) {
|
||||||
.hostnameVerifier { _, _ -> true }
|
throw RuntimeException(e)
|
||||||
|
}
|
||||||
} catch (e: Exception) {
|
|
||||||
throw RuntimeException(e)
|
|
||||||
}
|
|
@ -6,7 +6,6 @@ import java.text.ParseException
|
|||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
fun String.toTextDrawableString(): String {
|
fun String.toTextDrawableString(): String {
|
||||||
val textDrawable = StringBuilder()
|
val textDrawable = StringBuilder()
|
||||||
for (s in this.split(" ".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()) {
|
for (s in this.split(" ".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()) {
|
||||||
@ -16,12 +15,12 @@ fun String.toTextDrawableString(): String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun Item.sourceAndDateText(): String {
|
fun Item.sourceAndDateText(): String {
|
||||||
var formattedDate: String = try {
|
val formattedDate: String = try {
|
||||||
" " + DateUtils.getRelativeTimeSpanString(
|
" " + DateUtils.getRelativeTimeSpanString(
|
||||||
SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(this.datetime).time,
|
SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(this.datetime).time,
|
||||||
Date().time,
|
Date().time,
|
||||||
DateUtils.MINUTE_IN_MILLIS,
|
DateUtils.MINUTE_IN_MILLIS,
|
||||||
DateUtils.FORMAT_ABBREV_RELATIVE
|
DateUtils.FORMAT_ABBREV_RELATIVE
|
||||||
)
|
)
|
||||||
} catch (e: ParseException) {
|
} catch (e: ParseException) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
|
@ -7,22 +7,24 @@ import android.content.Intent
|
|||||||
import android.graphics.BitmapFactory
|
import android.graphics.BitmapFactory
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.support.customtabs.CustomTabsIntent
|
import android.support.customtabs.CustomTabsIntent
|
||||||
|
import android.util.Patterns
|
||||||
import xyz.klinker.android.drag_dismiss.DragDismissIntentBuilder
|
import android.widget.Toast
|
||||||
|
|
||||||
import apps.amine.bou.readerforselfoss.R
|
import apps.amine.bou.readerforselfoss.R
|
||||||
import apps.amine.bou.readerforselfoss.ReaderActivity
|
import apps.amine.bou.readerforselfoss.ReaderActivity
|
||||||
import apps.amine.bou.readerforselfoss.api.selfoss.Item
|
import apps.amine.bou.readerforselfoss.api.selfoss.Item
|
||||||
import apps.amine.bou.readerforselfoss.utils.customtabs.CustomTabActivityHelper
|
import apps.amine.bou.readerforselfoss.utils.customtabs.CustomTabActivityHelper
|
||||||
|
import okhttp3.HttpUrl
|
||||||
|
|
||||||
|
|
||||||
fun Context.buildCustomTabsIntent(): CustomTabsIntent {
|
fun Context.buildCustomTabsIntent(): CustomTabsIntent {
|
||||||
|
|
||||||
val actionIntent = Intent(Intent.ACTION_SEND)
|
val actionIntent = Intent(Intent.ACTION_SEND)
|
||||||
actionIntent.type = "text/plain"
|
actionIntent.type = "text/plain"
|
||||||
val createPendingShareIntent: PendingIntent = PendingIntent.getActivity(this, 0, actionIntent, 0)
|
val createPendingShareIntent: PendingIntent = PendingIntent.getActivity(
|
||||||
|
this,
|
||||||
|
0,
|
||||||
|
actionIntent,
|
||||||
|
0
|
||||||
|
)
|
||||||
|
|
||||||
val intentBuilder = CustomTabsIntent.Builder()
|
val intentBuilder = CustomTabsIntent.Builder()
|
||||||
|
|
||||||
@ -32,53 +34,88 @@ fun Context.buildCustomTabsIntent(): CustomTabsIntent {
|
|||||||
intentBuilder.setShowTitle(true)
|
intentBuilder.setShowTitle(true)
|
||||||
|
|
||||||
|
|
||||||
intentBuilder.setStartAnimations(this,
|
intentBuilder.setStartAnimations(
|
||||||
|
this,
|
||||||
R.anim.slide_in_right,
|
R.anim.slide_in_right,
|
||||||
R.anim.slide_out_left)
|
R.anim.slide_out_left
|
||||||
intentBuilder.setExitAnimations(this,
|
)
|
||||||
|
intentBuilder.setExitAnimations(
|
||||||
|
this,
|
||||||
android.R.anim.slide_in_left,
|
android.R.anim.slide_in_left,
|
||||||
android.R.anim.slide_out_right)
|
android.R.anim.slide_out_right
|
||||||
|
)
|
||||||
|
|
||||||
val closeicon = BitmapFactory.decodeResource(resources, R.drawable.ic_close_white_24dp)
|
val closeicon = BitmapFactory.decodeResource(resources, R.drawable.ic_close_white_24dp)
|
||||||
intentBuilder.setCloseButtonIcon(closeicon)
|
intentBuilder.setCloseButtonIcon(closeicon)
|
||||||
|
|
||||||
val shareLabel = this.getString(R.string.label_share)
|
val shareLabel = this.getString(R.string.label_share)
|
||||||
val icon = BitmapFactory.decodeResource(resources,
|
val icon = BitmapFactory.decodeResource(
|
||||||
R.drawable.ic_share_white_24dp)
|
resources,
|
||||||
|
R.drawable.ic_share_white_24dp
|
||||||
|
)
|
||||||
intentBuilder.setActionButton(icon, shareLabel, createPendingShareIntent)
|
intentBuilder.setActionButton(icon, shareLabel, createPendingShareIntent)
|
||||||
|
|
||||||
return intentBuilder.build()
|
return intentBuilder.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Context.openItemUrl(linkDecoded: String,
|
fun Context.openItemUrlInternally(
|
||||||
customTabsIntent: CustomTabsIntent,
|
allItems: ArrayList<Item>,
|
||||||
internalBrowser: Boolean,
|
currentItem: Int,
|
||||||
articleViewer: Boolean,
|
linkDecoded: String,
|
||||||
app: Activity) {
|
customTabsIntent: CustomTabsIntent,
|
||||||
if (!internalBrowser || !linkDecoded.isUrlValid()) {
|
articleViewer: Boolean,
|
||||||
openInBrowser(linkDecoded, app)
|
app: Activity
|
||||||
|
) {
|
||||||
|
if (articleViewer) {
|
||||||
|
val intent = Intent(this, ReaderActivity::class.java)
|
||||||
|
intent.putParcelableArrayListExtra("allItems", allItems)
|
||||||
|
intent.putExtra("currentItem", currentItem)
|
||||||
|
app.startActivity(intent)
|
||||||
} else {
|
} else {
|
||||||
if (articleViewer) {
|
try {
|
||||||
val intent = Intent(this, ReaderActivity::class.java)
|
CustomTabActivityHelper.openCustomTab(
|
||||||
|
app,
|
||||||
DragDismissIntentBuilder(this)
|
customTabsIntent,
|
||||||
.setFullscreenOnTablets(true) // defaults to false, tablets will have padding on each side
|
Uri.parse(linkDecoded)
|
||||||
.setDragElasticity(DragDismissIntentBuilder.DragElasticity.NORMAL) // Larger elasticities will make it easier to dismiss.
|
) { _, uri ->
|
||||||
.build(intent)
|
val intent = Intent(Intent.ACTION_VIEW, uri)
|
||||||
|
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||||
intent.putExtra("url", linkDecoded)
|
startActivity(intent)
|
||||||
app.startActivity(intent)
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
CustomTabActivityHelper.openCustomTab(app, customTabsIntent, Uri.parse(linkDecoded)
|
|
||||||
) { _, uri ->
|
|
||||||
val intent = Intent(Intent.ACTION_VIEW, uri)
|
|
||||||
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
|
||||||
startActivity(intent)
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
openInBrowser(linkDecoded, app)
|
|
||||||
}
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
openInBrowser(linkDecoded, app)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Context.openItemUrl(
|
||||||
|
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
|
||||||
|
).show()
|
||||||
|
} else {
|
||||||
|
if (!internalBrowser) {
|
||||||
|
openInBrowser(linkDecoded, app)
|
||||||
|
} else {
|
||||||
|
this.openItemUrlInternally(
|
||||||
|
allItems,
|
||||||
|
currentItem,
|
||||||
|
linkDecoded,
|
||||||
|
customTabsIntent,
|
||||||
|
articleViewer,
|
||||||
|
app
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -88,3 +125,24 @@ private fun openInBrowser(linkDecoded: String, app: Activity) {
|
|||||||
intent.data = Uri.parse(linkDecoded)
|
intent.data = Uri.parse(linkDecoded)
|
||||||
app.startActivity(intent)
|
app.startActivity(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun String.isUrlValid(): Boolean =
|
||||||
|
HttpUrl.parse(this) != null && Patterns.WEB_URL.matcher(this).matches()
|
||||||
|
|
||||||
|
fun String.isBaseUrlValid(): Boolean {
|
||||||
|
val baseUrl = HttpUrl.parse(this)
|
||||||
|
var existsAndEndsWithSlash = false
|
||||||
|
if (baseUrl != null) {
|
||||||
|
val pathSegments = baseUrl.pathSegments()
|
||||||
|
existsAndEndsWithSlash = "" == pathSegments[pathSegments.size - 1]
|
||||||
|
}
|
||||||
|
|
||||||
|
return Patterns.WEB_URL.matcher(this).matches() && existsAndEndsWithSlash
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Context.openInBrowserAsNewTask(i: Item) {
|
||||||
|
val intent = Intent(Intent.ACTION_VIEW)
|
||||||
|
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||||
|
intent.data = Uri.parse(i.getLinkDecoded().toStringUriWithHttp())
|
||||||
|
startActivity(intent)
|
||||||
|
}
|
||||||
|
@ -0,0 +1,53 @@
|
|||||||
|
package apps.amine.bou.readerforselfoss.utils
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.support.design.widget.CoordinatorLayout
|
||||||
|
import android.support.design.widget.FloatingActionButton
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.view.View
|
||||||
|
|
||||||
|
class ScrollAwareFABBehavior(
|
||||||
|
context: Context,
|
||||||
|
attrs: AttributeSet
|
||||||
|
) : CoordinatorLayout.Behavior<FloatingActionButton>() {
|
||||||
|
|
||||||
|
override fun onStartNestedScroll(
|
||||||
|
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
|
||||||
|
) {
|
||||||
|
super.onNestedScroll(
|
||||||
|
coordinatorLayout,
|
||||||
|
child,
|
||||||
|
target,
|
||||||
|
dxConsumed,
|
||||||
|
dyConsumed,
|
||||||
|
dxUnconsumed,
|
||||||
|
dyUnconsumed
|
||||||
|
)
|
||||||
|
if (dyConsumed > 0 && child.visibility == View.VISIBLE) {
|
||||||
|
child.hide(object : FloatingActionButton.OnVisibilityChangedListener() {
|
||||||
|
override fun onHidden(fab: FloatingActionButton?) {
|
||||||
|
super.onHidden(fab)
|
||||||
|
fab!!.visibility = View.INVISIBLE
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else if (dyConsumed < 0 && child.visibility != View.VISIBLE) {
|
||||||
|
child.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -2,7 +2,6 @@ package apps.amine.bou.readerforselfoss.utils.bottombar
|
|||||||
|
|
||||||
import com.ashokvarma.bottomnavigation.TextBadgeItem
|
import com.ashokvarma.bottomnavigation.TextBadgeItem
|
||||||
|
|
||||||
|
|
||||||
fun TextBadgeItem.removeBadge(): TextBadgeItem {
|
fun TextBadgeItem.removeBadge(): TextBadgeItem {
|
||||||
this.setText("")
|
this.setText("")
|
||||||
this.hide()
|
this.hide()
|
||||||
@ -10,7 +9,4 @@ fun TextBadgeItem.removeBadge(): TextBadgeItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun TextBadgeItem.maybeShow(): TextBadgeItem =
|
fun TextBadgeItem.maybeShow(): TextBadgeItem =
|
||||||
if (this.isHidden)
|
if (this.isHidden) this.show() else this
|
||||||
this.show()
|
|
||||||
else
|
|
||||||
this
|
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package apps.amine.bou.readerforselfoss.utils.customtabs;
|
package apps.amine.bou.readerforselfoss.utils.customtabs;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
@ -8,8 +11,6 @@ import android.support.customtabs.CustomTabsIntent;
|
|||||||
import android.support.customtabs.CustomTabsServiceConnection;
|
import android.support.customtabs.CustomTabsServiceConnection;
|
||||||
import android.support.customtabs.CustomTabsSession;
|
import android.support.customtabs.CustomTabsSession;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a helper class to manage the connection to the Custom Tabs Service.
|
* This is a helper class to manage the connection to the Custom Tabs Service.
|
||||||
*/
|
*/
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
package apps.amine.bou.readerforselfoss.utils.customtabs;
|
package apps.amine.bou.readerforselfoss.utils.customtabs;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
@ -9,10 +13,8 @@ import android.net.Uri;
|
|||||||
import android.support.customtabs.CustomTabsService;
|
import android.support.customtabs.CustomTabsService;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import apps.amine.bou.readerforselfoss.utils.customtabs.helpers.KeepAliveService;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import apps.amine.bou.readerforselfoss.utils.customtabs.helpers.KeepAliveService;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@SuppressWarnings("ALL")
|
@SuppressWarnings("ALL")
|
||||||
class CustomTabsHelper {
|
class CustomTabsHelper {
|
||||||
@ -101,7 +103,7 @@ class CustomTabsHelper {
|
|||||||
List<ResolveInfo> handlers = pm.queryIntentActivities(
|
List<ResolveInfo> handlers = pm.queryIntentActivities(
|
||||||
intent,
|
intent,
|
||||||
PackageManager.GET_RESOLVED_FILTER);
|
PackageManager.GET_RESOLVED_FILTER);
|
||||||
if (handlers == null || handlers.size() == 0) {
|
if (handlers == null || handlers.isEmpty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (ResolveInfo resolveInfo : handlers) {
|
for (ResolveInfo resolveInfo : handlers) {
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
package apps.amine.bou.readerforselfoss.utils.customtabs;
|
package apps.amine.bou.readerforselfoss.utils.customtabs;
|
||||||
|
|
||||||
|
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
|
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.support.customtabs.CustomTabsClient;
|
import android.support.customtabs.CustomTabsClient;
|
||||||
import android.support.customtabs.CustomTabsServiceConnection;
|
import android.support.customtabs.CustomTabsServiceConnection;
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation for the CustomTabsServiceConnection that avoids leaking the
|
* Implementation for the CustomTabsServiceConnection that avoids leaking the
|
||||||
* ServiceConnectionCallback
|
* ServiceConnectionCallback
|
||||||
|
@ -8,8 +8,6 @@ import android.widget.TextView
|
|||||||
|
|
||||||
import apps.amine.bou.readerforselfoss.R
|
import apps.amine.bou.readerforselfoss.R
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
open class CustomBaseViewHolder(var view: View) : RecyclerView.ViewHolder(view) {
|
open class CustomBaseViewHolder(var view: View) : RecyclerView.ViewHolder(view) {
|
||||||
var icon: ImageView = view.findViewById(R.id.material_drawer_icon)
|
var icon: ImageView = view.findViewById(R.id.material_drawer_icon)
|
||||||
var name: TextView = view.findViewById(R.id.material_drawer_name)
|
var name: TextView = view.findViewById(R.id.material_drawer_name)
|
||||||
|
@ -15,8 +15,6 @@ import com.mikepenz.materialdrawer.util.DrawerImageLoader
|
|||||||
import com.mikepenz.materialdrawer.util.DrawerUIUtils
|
import com.mikepenz.materialdrawer.util.DrawerUIUtils
|
||||||
import com.mikepenz.materialize.util.UIUtils
|
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 {
|
fun withIcon(url: String): T {
|
||||||
this.icon = ImageHolder(url)
|
this.icon = ImageHolder(url)
|
||||||
@ -77,7 +75,10 @@ abstract class CustomUrlBasePrimaryDrawerItem<T, VH : RecyclerView.ViewHolder> :
|
|||||||
val selectedIconColor = getSelectedIconColor(ctx)
|
val selectedIconColor = getSelectedIconColor(ctx)
|
||||||
|
|
||||||
//set the background for the item
|
//set the background for the item
|
||||||
UIUtils.setBackground(viewHolder.view, UIUtils.getSelectableBackground(ctx, selectedColor, true))
|
UIUtils.setBackground(
|
||||||
|
viewHolder.view,
|
||||||
|
UIUtils.getSelectableBackground(ctx, selectedColor, true)
|
||||||
|
)
|
||||||
//set the text for the name
|
//set the text for the name
|
||||||
StringHolder.applyTo(this.getName(), viewHolder.name)
|
StringHolder.applyTo(this.getName(), viewHolder.name)
|
||||||
//set the text for the description or hide
|
//set the text for the description or hide
|
||||||
@ -86,8 +87,11 @@ abstract class CustomUrlBasePrimaryDrawerItem<T, VH : RecyclerView.ViewHolder> :
|
|||||||
//set the colors for textViews
|
//set the colors for textViews
|
||||||
viewHolder.name.setTextColor(getTextColorStateList(color, selectedTextColor))
|
viewHolder.name.setTextColor(getTextColorStateList(color, selectedTextColor))
|
||||||
//set the description text color
|
//set the description text color
|
||||||
ColorHolder.applyToOr(descriptionTextColor,
|
ColorHolder.applyToOr(
|
||||||
viewHolder.description, getTextColorStateList(color, selectedTextColor))
|
descriptionTextColor,
|
||||||
|
viewHolder.description,
|
||||||
|
getTextColorStateList(color, selectedTextColor)
|
||||||
|
)
|
||||||
|
|
||||||
//define the typeface for our textViews
|
//define the typeface for our textViews
|
||||||
if (getTypeface() != null) {
|
if (getTypeface() != null) {
|
||||||
|
@ -5,15 +5,11 @@ import android.support.annotation.LayoutRes
|
|||||||
import android.support.annotation.StringRes
|
import android.support.annotation.StringRes
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
|
import apps.amine.bou.readerforselfoss.R
|
||||||
import com.mikepenz.materialdrawer.holder.BadgeStyle
|
import com.mikepenz.materialdrawer.holder.BadgeStyle
|
||||||
import com.mikepenz.materialdrawer.holder.StringHolder
|
import com.mikepenz.materialdrawer.holder.StringHolder
|
||||||
import com.mikepenz.materialdrawer.model.interfaces.ColorfulBadgeable
|
import com.mikepenz.materialdrawer.model.interfaces.ColorfulBadgeable
|
||||||
|
|
||||||
import apps.amine.bou.readerforselfoss.R
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class CustomUrlPrimaryDrawerItem : CustomUrlBasePrimaryDrawerItem<CustomUrlPrimaryDrawerItem, CustomUrlPrimaryDrawerItem.ViewHolder>(), ColorfulBadgeable<CustomUrlPrimaryDrawerItem> {
|
class CustomUrlPrimaryDrawerItem : CustomUrlBasePrimaryDrawerItem<CustomUrlPrimaryDrawerItem, CustomUrlPrimaryDrawerItem.ViewHolder>(), ColorfulBadgeable<CustomUrlPrimaryDrawerItem> {
|
||||||
protected var mBadge: StringHolder = StringHolder("")
|
protected var mBadge: StringHolder = StringHolder("")
|
||||||
protected var mBadgeStyle = BadgeStyle()
|
protected var mBadgeStyle = BadgeStyle()
|
||||||
@ -67,7 +63,10 @@ class CustomUrlPrimaryDrawerItem : CustomUrlBasePrimaryDrawerItem<CustomUrlPrima
|
|||||||
val badgeVisible = StringHolder.applyToOrHide(mBadge, viewHolder.badge)
|
val badgeVisible = StringHolder.applyToOrHide(mBadge, viewHolder.badge)
|
||||||
//style the badge if it is visible
|
//style the badge if it is visible
|
||||||
if (badgeVisible) {
|
if (badgeVisible) {
|
||||||
mBadgeStyle.style(viewHolder.badge, getTextColorStateList(getColor(ctx), getSelectedTextColor(ctx)))
|
mBadgeStyle.style(
|
||||||
|
viewHolder.badge,
|
||||||
|
getTextColorStateList(getColor(ctx), getSelectedTextColor(ctx))
|
||||||
|
)
|
||||||
viewHolder.badgeContainer.visibility = View.VISIBLE
|
viewHolder.badgeContainer.visibility = View.VISIBLE
|
||||||
} else {
|
} else {
|
||||||
viewHolder.badgeContainer.visibility = View.GONE
|
viewHolder.badgeContainer.visibility = View.GONE
|
||||||
@ -89,6 +88,5 @@ class CustomUrlPrimaryDrawerItem : CustomUrlBasePrimaryDrawerItem<CustomUrlPrima
|
|||||||
class ViewHolder(view: View) : CustomBaseViewHolder(view) {
|
class ViewHolder(view: View) : CustomBaseViewHolder(view) {
|
||||||
val badgeContainer: View = view.findViewById(R.id.material_drawer_badge_container)
|
val badgeContainer: View = view.findViewById(R.id.material_drawer_badge_container)
|
||||||
val badge: TextView = view.findViewById(R.id.material_drawer_badge)
|
val badge: TextView = view.findViewById(R.id.material_drawer_badge)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -8,22 +8,32 @@ import com.bumptech.glide.Glide
|
|||||||
import com.bumptech.glide.request.RequestOptions
|
import com.bumptech.glide.request.RequestOptions
|
||||||
import com.bumptech.glide.request.target.BitmapImageViewTarget
|
import com.bumptech.glide.request.target.BitmapImageViewTarget
|
||||||
|
|
||||||
|
|
||||||
fun Context.bitmapCenterCrop(url: String, iv: ImageView) =
|
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) =
|
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) =
|
fun Context.circularBitmapDrawable(url: String, iv: ImageView) =
|
||||||
Glide.with(this)
|
Glide.with(this)
|
||||||
.asBitmap()
|
.asBitmap()
|
||||||
.load(url)
|
.load(url)
|
||||||
.apply(RequestOptions.centerCropTransform()).
|
.apply(RequestOptions.centerCropTransform())
|
||||||
into(object : BitmapImageViewTarget(iv) {
|
.into(object : BitmapImageViewTarget(iv) {
|
||||||
override fun setResource(resource: Bitmap?) {
|
override fun setResource(resource: Bitmap?) {
|
||||||
val circularBitmapDrawable = RoundedBitmapDrawableFactory.create(resources, resource)
|
val circularBitmapDrawable = RoundedBitmapDrawableFactory.create(
|
||||||
circularBitmapDrawable.isCircular = true
|
resources,
|
||||||
iv.setImageDrawable(circularBitmapDrawable)
|
resource
|
||||||
}
|
)
|
||||||
})
|
circularBitmapDrawable.isCircular = true
|
||||||
|
iv.setImageDrawable(circularBitmapDrawable)
|
||||||
|
}
|
||||||
|
})
|
@ -6,14 +6,14 @@ import apps.amine.bou.readerforselfoss.utils.getUnsafeHttpClient
|
|||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
import com.bumptech.glide.GlideBuilder
|
import com.bumptech.glide.GlideBuilder
|
||||||
import com.bumptech.glide.Registry
|
import com.bumptech.glide.Registry
|
||||||
import com.bumptech.glide.module.GlideModule
|
|
||||||
import com.bumptech.glide.load.model.GlideUrl
|
import com.bumptech.glide.load.model.GlideUrl
|
||||||
|
import com.bumptech.glide.module.GlideModule
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
|
|
||||||
|
|
||||||
class SelfSignedGlideModule : GlideModule {
|
class SelfSignedGlideModule : GlideModule {
|
||||||
|
|
||||||
override fun applyOptions(context: Context?, builder: GlideBuilder?) {}
|
override fun applyOptions(context: Context?, builder: GlideBuilder?) {
|
||||||
|
}
|
||||||
|
|
||||||
override fun registerComponents(context: Context?, glide: Glide?, registry: Registry?) {
|
override fun registerComponents(context: Context?, glide: Glide?, registry: Registry?) {
|
||||||
|
|
||||||
@ -22,11 +22,12 @@ class SelfSignedGlideModule : GlideModule {
|
|||||||
if (pref.getBoolean("isSelfSignedCert", false)) {
|
if (pref.getBoolean("isSelfSignedCert", false)) {
|
||||||
val client = getUnsafeHttpClient().build()
|
val client = getUnsafeHttpClient().build()
|
||||||
|
|
||||||
registry?.append(GlideUrl::class.java, InputStream::class.java,
|
registry?.append(
|
||||||
com.bumptech.glide.integration.okhttp3.OkHttpUrlLoader.Factory(client))
|
GlideUrl::class.java,
|
||||||
|
InputStream::class.java,
|
||||||
|
com.bumptech.glide.integration.okhttp3.OkHttpUrlLoader.Factory(client)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
BIN
app/src/main/res/drawable-hdpi/ic_add.png
Normal file
After Width: | Height: | Size: 134 B |
Before Width: | Height: | Size: 124 B |
BIN
app/src/main/res/drawable-hdpi/ic_chrome_reader_mode.png
Normal file
After Width: | Height: | Size: 216 B |
BIN
app/src/main/res/drawable-hdpi/ic_open_in_browser.png
Normal file
After Width: | Height: | Size: 204 B |
Before Width: | Height: | Size: 434 B |
BIN
app/src/main/res/drawable-mdpi/ic_add.png
Normal file
After Width: | Height: | Size: 116 B |
Before Width: | Height: | Size: 86 B |
BIN
app/src/main/res/drawable-mdpi/ic_chrome_reader_mode.png
Normal file
After Width: | Height: | Size: 136 B |
BIN
app/src/main/res/drawable-mdpi/ic_open_in_browser.png
Normal file
After Width: | Height: | Size: 157 B |
Before Width: | Height: | Size: 307 B |
BIN
app/src/main/res/drawable-xhdpi/ic_add.png
Normal file
After Width: | Height: | Size: 168 B |
Before Width: | Height: | Size: 108 B |
BIN
app/src/main/res/drawable-xhdpi/ic_chrome_reader_mode.png
Normal file
After Width: | Height: | Size: 171 B |
BIN
app/src/main/res/drawable-xhdpi/ic_open_in_browser.png
Normal file
After Width: | Height: | Size: 230 B |
Before Width: | Height: | Size: 542 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_add.png
Normal file
After Width: | Height: | Size: 242 B |
Before Width: | Height: | Size: 114 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_chrome_reader_mode.png
Normal file
After Width: | Height: | Size: 263 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_open_in_browser.png
Normal file
After Width: | Height: | Size: 318 B |
Before Width: | Height: | Size: 768 B |
BIN
app/src/main/res/drawable-xxxhdpi/ic_add.png
Normal file
After Width: | Height: | Size: 500 B |
Before Width: | Height: | Size: 119 B |
BIN
app/src/main/res/drawable-xxxhdpi/ic_chrome_reader_mode.png
Normal file
After Width: | Height: | Size: 296 B |
BIN
app/src/main/res/drawable-xxxhdpi/ic_open_in_browser.png
Normal file
After Width: | Height: | Size: 408 B |
Before Width: | Height: | Size: 1.1 KiB |
@ -15,7 +15,8 @@
|
|||||||
android:id="@+id/toolbar"
|
android:id="@+id/toolbar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="?attr/actionBarSize"
|
android:layout_height="?attr/actionBarSize"
|
||||||
app:theme="@style/ToolBarStyle" />
|
app:theme="@style/ToolBarStyle"
|
||||||
|
app:popupTheme="?attr/toolbarPopupTheme" />
|
||||||
|
|
||||||
</android.support.design.widget.AppBarLayout>
|
</android.support.design.widget.AppBarLayout>
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
<com.github.stkent.amplify.prompt.DefaultLayoutPromptView
|
<com.github.stkent.amplify.prompt.DefaultLayoutPromptView
|
||||||
android:id="@+id/prompt_view"
|
android:id="@+id/promptView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:prompt_view_user_opinion_question_title="@string/rating_prompt_title"
|
app:prompt_view_user_opinion_question_title="@string/rating_prompt_title"
|
||||||
@ -34,7 +34,7 @@
|
|||||||
android:id="@+id/coordLayout"
|
android:id="@+id/coordLayout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_below="@id/prompt_view">
|
android:layout_below="@id/promptView">
|
||||||
|
|
||||||
<android.support.design.widget.CoordinatorLayout
|
<android.support.design.widget.CoordinatorLayout
|
||||||
android:id="@+id/intern_coordLayout"
|
android:id="@+id/intern_coordLayout"
|
||||||
@ -51,10 +51,11 @@
|
|||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
<android.support.v7.widget.Toolbar
|
<android.support.v7.widget.Toolbar
|
||||||
android:id="@+id/toolbar"
|
android:id="@+id/toolBar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="?attr/actionBarSize"
|
android:layout_height="?attr/actionBarSize"
|
||||||
app:theme="@style/ToolBarStyle" />
|
app:theme="@style/ToolBarStyle"
|
||||||
|
app:popupTheme="?attr/toolbarPopupTheme" />
|
||||||
|
|
||||||
</android.support.design.widget.AppBarLayout>
|
</android.support.design.widget.AppBarLayout>
|
||||||
|
|
||||||
@ -88,7 +89,7 @@
|
|||||||
android:background="@color/transparent"
|
android:background="@color/transparent"
|
||||||
android:visibility="gone" />
|
android:visibility="gone" />
|
||||||
<android.support.v7.widget.RecyclerView
|
<android.support.v7.widget.RecyclerView
|
||||||
android:id="@+id/my_recycler_view"
|
android:id="@+id/recyclerView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="@color/transparent"
|
android:background="@color/transparent"
|
||||||
|
@ -14,7 +14,8 @@
|
|||||||
android:id="@+id/toolbar"
|
android:id="@+id/toolbar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="?attr/actionBarSize"
|
android:layout_height="?attr/actionBarSize"
|
||||||
app:theme="@style/ToolBarStyle" />
|
app:theme="@style/ToolBarStyle"
|
||||||
|
app:popupTheme="?attr/toolbarPopupTheme" />
|
||||||
|
|
||||||
</android.support.design.widget.AppBarLayout>
|
</android.support.design.widget.AppBarLayout>
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
@ -27,7 +28,7 @@
|
|||||||
android:paddingTop="@dimen/activity_vertical_margin">
|
android:paddingTop="@dimen/activity_vertical_margin">
|
||||||
<!-- Login progress -->
|
<!-- Login progress -->
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
android:id="@+id/login_progress"
|
android:id="@+id/loginProgress"
|
||||||
style="?android:attr/progressBarStyleLarge"
|
style="?android:attr/progressBarStyleLarge"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@ -35,7 +36,7 @@
|
|||||||
android:visibility="gone"/>
|
android:visibility="gone"/>
|
||||||
|
|
||||||
<ScrollView
|
<ScrollView
|
||||||
android:id="@+id/login_form"
|
android:id="@+id/loginForm"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
@ -51,15 +52,13 @@
|
|||||||
>
|
>
|
||||||
|
|
||||||
<EditText
|
<EditText
|
||||||
android:id="@+id/url"
|
android:id="@+id/urlView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:hint="@string/prompt_url"
|
android:hint="@string/prompt_url"
|
||||||
android:imeActionId="@+id/login"
|
|
||||||
android:inputType="textUri"
|
|
||||||
android:imeOptions="actionUnspecified"
|
android:imeOptions="actionUnspecified"
|
||||||
android:maxLines="1"
|
android:inputType="textUri"
|
||||||
/>
|
android:maxLines="1" />
|
||||||
|
|
||||||
</android.support.design.widget.TextInputLayout>
|
</android.support.design.widget.TextInputLayout>
|
||||||
|
|
||||||
@ -77,13 +76,12 @@
|
|||||||
android:visibility="gone">
|
android:visibility="gone">
|
||||||
|
|
||||||
<AutoCompleteTextView
|
<AutoCompleteTextView
|
||||||
android:id="@+id/login"
|
android:id="@+id/loginView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:hint="@string/prompt_login"
|
android:hint="@string/prompt_login"
|
||||||
android:inputType="text"
|
android:inputType="text"
|
||||||
android:maxLines="1"
|
android:maxLines="1" />
|
||||||
/>
|
|
||||||
|
|
||||||
</android.support.design.widget.TextInputLayout>
|
</android.support.design.widget.TextInputLayout>
|
||||||
|
|
||||||
@ -94,13 +92,12 @@
|
|||||||
android:visibility="gone">
|
android:visibility="gone">
|
||||||
|
|
||||||
<EditText
|
<EditText
|
||||||
android:id="@+id/password"
|
android:id="@+id/passwordView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:hint="@string/prompt_password"
|
android:hint="@string/prompt_password"
|
||||||
android:inputType="textPassword"
|
android:inputType="textPassword"
|
||||||
android:maxLines="1"
|
android:maxLines="1" />
|
||||||
/>
|
|
||||||
|
|
||||||
</android.support.design.widget.TextInputLayout>
|
</android.support.design.widget.TextInputLayout>
|
||||||
|
|
||||||
@ -118,7 +115,7 @@
|
|||||||
android:visibility="gone">
|
android:visibility="gone">
|
||||||
|
|
||||||
<EditText
|
<EditText
|
||||||
android:id="@+id/httpLogin"
|
android:id="@+id/httpLoginView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:hint="@string/prompt_http_login" />
|
android:hint="@string/prompt_http_login" />
|
||||||
@ -131,11 +128,11 @@
|
|||||||
android:visibility="gone">
|
android:visibility="gone">
|
||||||
|
|
||||||
<EditText
|
<EditText
|
||||||
android:id="@+id/httpPassword"
|
android:id="@+id/httpPasswordView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:inputType="textPassword"
|
android:hint="@string/prompt_http_password"
|
||||||
android:hint="@string/prompt_http_password" />
|
android:inputType="textPassword" />
|
||||||
</android.support.design.widget.TextInputLayout>
|
</android.support.design.widget.TextInputLayout>
|
||||||
|
|
||||||
<Switch
|
<Switch
|
||||||
@ -153,7 +150,7 @@
|
|||||||
android:visibility="gone" />
|
android:visibility="gone" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/email_sign_in_button"
|
android:id="@+id/signInButton"
|
||||||
style="?android:textAppearanceSmall"
|
style="?android:textAppearanceSmall"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
@ -1,126 +1,44 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<android.support.constraint.ConstraintLayout
|
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent">
|
||||||
tools:context="apps.amine.bou.readerforselfoss.ReaderActivity"
|
|
||||||
android:background="?android:attr/windowBackground">
|
|
||||||
|
|
||||||
<ImageView
|
<android.support.design.widget.AppBarLayout
|
||||||
android:id="@+id/imageView"
|
android:id="@+id/appBarLayout"
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="200dp"
|
|
||||||
android:scaleType="centerCrop"
|
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/source"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginEnd="16dp"
|
|
||||||
android:layout_marginLeft="16dp"
|
|
||||||
android:layout_marginRight="16dp"
|
|
||||||
android:layout_marginStart="16dp"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
|
||||||
android:textSize="12sp"
|
|
||||||
app:layout_constraintHorizontal_bias="0.0"
|
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/imageView" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/title"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginEnd="16dp"
|
|
||||||
android:layout_marginLeft="16dp"
|
|
||||||
android:layout_marginRight="16dp"
|
|
||||||
android:layout_marginStart="16dp"
|
|
||||||
android:layout_marginTop="6dp"
|
|
||||||
android:textAppearance="@style/TextAppearance.AppCompat.Headline"
|
|
||||||
android:textStyle="bold"
|
|
||||||
app:layout_constraintHorizontal_bias="0.0"
|
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/source" />
|
|
||||||
|
|
||||||
<org.sufficientlysecure.htmltextview.HtmlTextView
|
|
||||||
android:id="@+id/content"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginEnd="16dp"
|
|
||||||
android:layout_marginLeft="16dp"
|
|
||||||
android:layout_marginRight="16dp"
|
|
||||||
android:layout_marginStart="16dp"
|
|
||||||
android:layout_marginTop="24dp"
|
|
||||||
android:paddingBottom="48dp"
|
|
||||||
app:layout_constraintHorizontal_bias="0.0"
|
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/title"
|
|
||||||
tools:text="Some text @android:string/fingerprint_icon_content_description" />
|
|
||||||
|
|
||||||
<android.support.constraint.ConstraintLayout
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="35dp"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="0dp"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
android:layout_marginEnd="0dp"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
android:layout_marginRight="16dp"
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:background="#BBBBBB"
|
<android.support.v7.widget.Toolbar
|
||||||
|
android:id="@+id/toolBar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="?attr/actionBarSize"
|
||||||
|
app:popupTheme="?attr/toolbarPopupTheme"
|
||||||
|
app:theme="@style/ToolBarStyle" />
|
||||||
|
|
||||||
|
</android.support.design.widget.AppBarLayout>
|
||||||
|
|
||||||
|
<android.support.v4.view.ViewPager
|
||||||
|
android:id="@+id/pager"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintHorizontal_bias="0.0"
|
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/content"
|
app:layout_constraintTop_toBottomOf="@+id/appBarLayout" />
|
||||||
app:layout_constraintVertical_bias="1.0">
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/browserBtn"
|
|
||||||
android:layout_width="35dp"
|
|
||||||
android:layout_height="35dp"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:layout_marginEnd="16dp"
|
|
||||||
android:layout_marginRight="16dp"
|
|
||||||
android:layout_toLeftOf="@+id/shareBtn"
|
|
||||||
android:layout_toStartOf="@+id/shareBtn"
|
|
||||||
android:adjustViewBounds="true"
|
|
||||||
android:background="@android:color/transparent"
|
|
||||||
android:elevation="5dp"
|
|
||||||
android:padding="4dp"
|
|
||||||
android:scaleType="centerCrop"
|
|
||||||
android:src="@drawable/ic_open_in_browser_black_24dp"
|
|
||||||
android:tint="?android:attr/textColorPrimary"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toStartOf="@+id/shareBtn"
|
|
||||||
app:layout_constraintHorizontal_bias="0.5"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/shareBtn"
|
|
||||||
android:layout_width="35dp"
|
|
||||||
android:layout_height="35dp"
|
|
||||||
android:adjustViewBounds="true"
|
|
||||||
android:background="@android:color/transparent"
|
|
||||||
android:elevation="5dp"
|
|
||||||
android:padding="4dp"
|
|
||||||
android:scaleType="centerCrop"
|
|
||||||
android:src="@drawable/ic_share_black_24dp"
|
|
||||||
android:tint="?android:attr/textColorPrimary"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintHorizontal_bias="0.5"
|
|
||||||
app:layout_constraintStart_toEndOf="@+id/browserBtn"
|
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
|
||||||
|
|
||||||
</android.support.constraint.ConstraintLayout>
|
|
||||||
|
|
||||||
|
<me.relex.circleindicator.CircleIndicator
|
||||||
|
android:id="@+id/indicator"
|
||||||
|
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" />
|
||||||
</android.support.constraint.ConstraintLayout>
|
</android.support.constraint.ConstraintLayout>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
<RelativeLayout
|
<android.support.design.widget.CoordinatorLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
@ -16,28 +16,25 @@
|
|||||||
android:id="@+id/toolbar"
|
android:id="@+id/toolbar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="?attr/actionBarSize"
|
android:layout_height="?attr/actionBarSize"
|
||||||
app:theme="@style/ToolBarStyle" />
|
app:theme="@style/ToolBarStyle"
|
||||||
|
app:popupTheme="?attr/toolbarPopupTheme" />
|
||||||
|
|
||||||
</android.support.design.widget.AppBarLayout>
|
</android.support.design.widget.AppBarLayout>
|
||||||
|
|
||||||
<android.support.v7.widget.RecyclerView
|
<android.support.v7.widget.RecyclerView
|
||||||
android:id="@+id/activity_sources"
|
android:id="@+id/recyclerView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:scrollbars="vertical"
|
android:scrollbars="vertical"
|
||||||
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
||||||
</android.support.v7.widget.RecyclerView>
|
</android.support.v7.widget.RecyclerView>
|
||||||
|
|
||||||
<com.melnykov.fab.FloatingActionButton
|
<android.support.design.widget.FloatingActionButton
|
||||||
android:id="@+id/fab"
|
android:id="@+id/fab"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="end|bottom|right"
|
android:layout_gravity="end|bottom|right"
|
||||||
android:src="@drawable/ic_add_black_24dp"
|
android:src="@drawable/ic_add"
|
||||||
android:tint="?android:textColorPrimary"
|
|
||||||
fab:fab_colorNormal="?attr/colorAccent"
|
|
||||||
fab:fab_colorPressed="?attr/colorAccentDark"
|
|
||||||
fab:fab_colorRipple="@color/pink"
|
|
||||||
android:paddingBottom="@dimen/activity_vertical_margin"
|
android:paddingBottom="@dimen/activity_vertical_margin"
|
||||||
android:paddingTop="@dimen/activity_vertical_margin"
|
android:paddingTop="@dimen/activity_vertical_margin"
|
||||||
android:layout_alignParentBottom="true"
|
android:layout_alignParentBottom="true"
|
||||||
@ -45,5 +42,6 @@
|
|||||||
android:layout_alignParentEnd="true"
|
android:layout_alignParentEnd="true"
|
||||||
android:layout_marginBottom="16dp"
|
android:layout_marginBottom="16dp"
|
||||||
android:layout_marginEnd="16dp"
|
android:layout_marginEnd="16dp"
|
||||||
android:layout_marginRight="16dp"/>
|
android:layout_marginRight="16dp"
|
||||||
</RelativeLayout>
|
app:layout_behavior="apps.amine.bou.readerforselfoss.utils.ScrollAwareFABBehavior" />
|
||||||
|
</android.support.design.widget.CoordinatorLayout>
|
||||||
|
@ -1,157 +1,149 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<android.support.v7.widget.CardView
|
||||||
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"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:layout_width="match_parent"
|
xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
||||||
android:layout_height="wrap_content">
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/card"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="8dp"
|
||||||
|
android:layout_marginRight="8dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
app:layout_constraintHorizontal_bias="0.62"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
card_view:cardElevation="2dp"
|
||||||
|
card_view:cardUseCompatPadding="true"
|
||||||
|
card_view:layout_constraintBottom_toBottomOf="parent">
|
||||||
|
|
||||||
<android.support.v7.widget.CardView
|
<android.support.constraint.ConstraintLayout
|
||||||
android:id="@+id/card"
|
android:layout_width="match_parent"
|
||||||
xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
android:layout_height="wrap_content">
|
||||||
android:layout_width="0dp"
|
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
<ImageView
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
android:id="@+id/itemImage"
|
||||||
app:layout_constraintHorizontal_bias="0.62"
|
android:layout_width="0dp"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
android:layout_height="wrap_content"
|
||||||
card_view:cardElevation="2dp"
|
android:adjustViewBounds="true"
|
||||||
card_view:cardUseCompatPadding="true"
|
android:cropToPadding="true"
|
||||||
android:layout_height="wrap_content"
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
android:layout_marginStart="8dp"
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
android:layout_marginLeft="8dp"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
android:layout_marginTop="8dp"
|
app:srcCompat="@drawable/background_splash"
|
||||||
android:layout_marginEnd="8dp"
|
card_view:layout_constraintBottom_toTopOf="@+id/constraintLayout" />
|
||||||
android:layout_marginRight="8dp">
|
|
||||||
|
|
||||||
<android.support.constraint.ConstraintLayout
|
<android.support.constraint.ConstraintLayout
|
||||||
android:layout_width="match_parent"
|
android:id="@+id/constraintLayout"
|
||||||
android:layout_height="wrap_content">
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/itemImage">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:layout_width="0dp"
|
android:id="@+id/sourceImage"
|
||||||
android:layout_height="wrap_content"
|
android:layout_width="40dp"
|
||||||
app:srcCompat="@drawable/background_splash"
|
android:layout_height="40dp"
|
||||||
android:id="@+id/itemImage"
|
android:layout_marginLeft="8dp"
|
||||||
android:scaleType="fitCenter"
|
android:layout_marginStart="8dp"
|
||||||
android:adjustViewBounds="true"
|
android:layout_marginTop="8dp"
|
||||||
android:cropToPadding="true"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
android:layout_marginTop="0dp"
|
|
||||||
android:layout_marginRight="0dp"
|
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
|
||||||
android:layout_marginLeft="0dp"
|
|
||||||
app:layout_constraintLeft_toLeftOf="parent" />
|
|
||||||
|
|
||||||
<android.support.constraint.ConstraintLayout
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/itemImage"
|
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:srcCompat="@drawable/background_splash" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/title"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:layout_marginLeft="8dp"
|
||||||
|
android:layout_marginRight="8dp"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:gravity="start"
|
||||||
|
android:textAlignment="viewStart"
|
||||||
|
android:textStyle="bold"
|
||||||
|
app:layout_constraintHorizontal_bias="0.0"
|
||||||
|
app:layout_constraintLeft_toRightOf="@+id/sourceImage"
|
||||||
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="@+id/sourceImage"
|
||||||
|
tools:text="Titre" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/sourceTitleAndDate"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:gravity="start"
|
||||||
|
android:textAlignment="viewStart"
|
||||||
|
android:textSize="14sp"
|
||||||
|
app:layout_constraintLeft_toLeftOf="@+id/title"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/title"
|
||||||
|
tools:text="Google Actualité Il y a 5h" />
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
>
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/sourceTitleAndDate">
|
||||||
|
|
||||||
<ImageView
|
<com.like.LikeButton
|
||||||
android:layout_height="40dp"
|
android:id="@+id/favButton"
|
||||||
app:srcCompat="@drawable/background_splash"
|
android:layout_width="35dp"
|
||||||
android:id="@+id/sourceImage"
|
android:layout_height="35dp"
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
android:layout_alignParentEnd="true"
|
||||||
android:layout_marginStart="8dp"
|
android:layout_alignParentRight="true"
|
||||||
android:layout_marginLeft="8dp"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:layout_width="40dp" />
|
|
||||||
|
|
||||||
<TextView
|
android:layout_centerVertical="true"
|
||||||
android:id="@+id/title"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
android:layout_marginLeft="8dp"
|
|
||||||
android:layout_marginRight="8dp"
|
android:layout_marginRight="8dp"
|
||||||
android:layout_marginStart="8dp"
|
android:elevation="5dp"
|
||||||
android:gravity="start"
|
android:padding="4dp"
|
||||||
android:textAlignment="viewStart"
|
app:icon_size="22dp"
|
||||||
android:textStyle="bold"
|
app:icon_type="heart" />
|
||||||
app:layout_constraintHorizontal_bias="0.0"
|
|
||||||
app:layout_constraintLeft_toRightOf="@+id/sourceImage"
|
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="@+id/sourceImage"
|
|
||||||
tools:text="Titre" />
|
|
||||||
|
|
||||||
<TextView
|
<ImageButton
|
||||||
android:layout_width="wrap_content"
|
android:id="@+id/shareBtn"
|
||||||
android:layout_height="wrap_content"
|
android:layout_width="35dp"
|
||||||
android:id="@+id/sourceTitleAndDate"
|
android:layout_height="35dp"
|
||||||
android:textSize="14sp"
|
android:layout_centerVertical="true"
|
||||||
tools:text="Google Actualité Il y a 5h"
|
android:layout_marginEnd="16dp"
|
||||||
android:textAlignment="viewStart"
|
android:layout_marginRight="16dp"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/title"
|
android:layout_toLeftOf="@+id/favButton"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_toStartOf="@+id/favButton"
|
||||||
app:layout_constraintLeft_toLeftOf="@+id/title"
|
android:adjustViewBounds="true"
|
||||||
android:gravity="start" />
|
android:background="@android:color/transparent"
|
||||||
|
android:elevation="5dp"
|
||||||
|
android:padding="4dp"
|
||||||
|
android:scaleType="centerCrop"
|
||||||
|
android:src="@drawable/ic_share_black_24dp"
|
||||||
|
android:tint="?android:attr/textColorPrimary" />
|
||||||
|
|
||||||
<RelativeLayout
|
<ImageButton
|
||||||
android:layout_width="0dp"
|
android:id="@+id/browserBtn"
|
||||||
android:layout_height="wrap_content"
|
android:layout_width="35dp"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/sourceTitleAndDate"
|
android:layout_height="35dp"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_centerVertical="true"
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
android:layout_marginEnd="16dp"
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
android:layout_marginRight="16dp"
|
||||||
app:layout_constraintBottom_toBottomOf="parent">
|
android:layout_toLeftOf="@+id/shareBtn"
|
||||||
|
android:layout_toStartOf="@+id/shareBtn"
|
||||||
|
android:adjustViewBounds="true"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
|
android:elevation="5dp"
|
||||||
|
android:padding="4dp"
|
||||||
|
android:scaleType="centerCrop"
|
||||||
|
android:src="@drawable/ic_open_in_browser_black_24dp"
|
||||||
|
android:tint="?android:attr/textColorPrimary" />
|
||||||
|
|
||||||
<com.like.LikeButton
|
</RelativeLayout>
|
||||||
app:icon_type="heart"
|
|
||||||
app:icon_size="22dp"
|
|
||||||
android:id="@+id/favButton"
|
|
||||||
android:layout_width="35dp"
|
|
||||||
android:layout_height="35dp"
|
|
||||||
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:layout_alignParentRight="true"
|
|
||||||
android:layout_alignParentEnd="true"
|
|
||||||
android:elevation="5dp"
|
|
||||||
android:padding="4dp"
|
|
||||||
android:layout_marginRight="8dp"
|
|
||||||
android:layout_marginEnd="8dp"/>
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/shareBtn"
|
|
||||||
android:layout_width="35dp"
|
|
||||||
android:layout_height="35dp"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:layout_marginEnd="16dp"
|
|
||||||
android:layout_marginRight="16dp"
|
|
||||||
android:layout_toLeftOf="@+id/favButton"
|
|
||||||
android:layout_toStartOf="@+id/favButton"
|
|
||||||
android:adjustViewBounds="true"
|
|
||||||
android:background="@android:color/transparent"
|
|
||||||
android:elevation="5dp"
|
|
||||||
android:padding="4dp"
|
|
||||||
android:scaleType="centerCrop"
|
|
||||||
android:src="@drawable/ic_share_black_24dp"
|
|
||||||
android:tint="?android:attr/textColorPrimary" />
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/browserBtn"
|
|
||||||
android:layout_width="35dp"
|
|
||||||
android:layout_height="35dp"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:layout_marginEnd="16dp"
|
|
||||||
android:layout_marginRight="16dp"
|
|
||||||
android:layout_toLeftOf="@+id/shareBtn"
|
|
||||||
android:layout_toStartOf="@+id/shareBtn"
|
|
||||||
android:adjustViewBounds="true"
|
|
||||||
android:background="@android:color/transparent"
|
|
||||||
android:elevation="5dp"
|
|
||||||
android:padding="4dp"
|
|
||||||
android:scaleType="centerCrop"
|
|
||||||
android:src="@drawable/ic_open_in_browser_black_24dp"
|
|
||||||
android:tint="?android:attr/textColorPrimary" />
|
|
||||||
|
|
||||||
</RelativeLayout>
|
|
||||||
|
|
||||||
</android.support.constraint.ConstraintLayout>
|
|
||||||
</android.support.constraint.ConstraintLayout>
|
</android.support.constraint.ConstraintLayout>
|
||||||
|
</android.support.constraint.ConstraintLayout>
|
||||||
|
|
||||||
</android.support.v7.widget.CardView>
|
</android.support.v7.widget.CardView>
|
||||||
</android.support.constraint.ConstraintLayout>
|
|
141
app/src/main/res/layout/fragment_article.xml
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
<android.support.design.widget.CoordinatorLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<android.support.v4.widget.NestedScrollView
|
||||||
|
android:id="@+id/nestedScrollView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<android.support.constraint.ConstraintLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/imageView"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="200dp"
|
||||||
|
android:scaleType="centerCrop"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/source"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="16dp"
|
||||||
|
android:layout_marginRight="16dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||||
|
android:textSize="12sp"
|
||||||
|
app:layout_constraintHorizontal_bias="0.0"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/titleView" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/titleView"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="16dp"
|
||||||
|
android:layout_marginRight="16dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:textAppearance="@style/TextAppearance.AppCompat.Headline"
|
||||||
|
android:textStyle="bold"
|
||||||
|
app:layout_constraintHorizontal_bias="0.0"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/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"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:layout_marginLeft="16dp"
|
||||||
|
android:layout_marginRight="16dp"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:layout_marginTop="24dp"
|
||||||
|
android:paddingBottom="48dp"
|
||||||
|
app:layout_constraintHorizontal_bias="0.0"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/titleView" />-->
|
||||||
|
|
||||||
|
</android.support.constraint.ConstraintLayout>
|
||||||
|
|
||||||
|
</android.support.v4.widget.NestedScrollView>
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
android:layout_gravity="end|bottom|right">
|
||||||
|
|
||||||
|
<com.github.rubensousa.floatingtoolbar.FloatingToolbar
|
||||||
|
android:id="@+id/floatingToolbar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="?attr/actionBarSize"
|
||||||
|
android:layout_gravity="bottom"
|
||||||
|
app:floatingItemBackground="?attr/colorAccent"
|
||||||
|
app:floatingMenu="@menu/reader_toolbar" />
|
||||||
|
|
||||||
|
<android.support.design.widget.FloatingActionButton
|
||||||
|
android:id="@+id/fab"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentBottom="true"
|
||||||
|
android:layout_alignParentEnd="true"
|
||||||
|
android:layout_alignParentRight="true"
|
||||||
|
android:layout_gravity="end|bottom|right"
|
||||||
|
android:layout_marginBottom="16dp"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:layout_marginRight="16dp"
|
||||||
|
android:paddingBottom="@dimen/activity_vertical_margin"
|
||||||
|
android:paddingTop="@dimen/activity_vertical_margin"
|
||||||
|
android:src="@drawable/ic_add"
|
||||||
|
app:backgroundTint="?attr/colorAccent"
|
||||||
|
app:fabSize="mini"
|
||||||
|
app:rippleColor="?attr/colorAccentDark" />
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/progressBar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:animateLayoutChanges="true"
|
||||||
|
android:alpha="0.8"
|
||||||
|
android:background="@color/black"
|
||||||
|
android:clickable="false">
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
style="?android:attr/progressBarStyleLarge"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:progressTint="?attr/colorAccent" />
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
</android.support.design.widget.CoordinatorLayout>
|
@ -1,55 +1,66 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<android.support.constraint.ConstraintLayout
|
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:orientation="vertical"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:minHeight="88dp">
|
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
|
<ImageView
|
||||||
android:id="@+id/itemImage"
|
android:id="@+id/itemImage"
|
||||||
android:layout_width="88dp"
|
android:layout_width="88dp"
|
||||||
android:layout_height="88dp"
|
android:layout_height="88dp"
|
||||||
android:src="@color/about_libraries_accent"
|
app:layout_constraintBottom_toTopOf="@+id/guideline4"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/actionBar"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/title"
|
android:id="@+id/title"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
android:layout_marginEnd="16dp"
|
android:layout_marginEnd="16dp"
|
||||||
android:layout_marginLeft="16dp"
|
|
||||||
android:layout_marginRight="16dp"
|
|
||||||
android:layout_marginStart="16dp"
|
android:layout_marginStart="16dp"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="16dp"
|
||||||
android:fontFamily="sans-serif"
|
android:fontFamily="sans-serif"
|
||||||
android:gravity="start"
|
android:gravity="start"
|
||||||
|
android:maxLines="3"
|
||||||
|
android:ellipsize="end"
|
||||||
android:textAlignment="viewStart"
|
android:textAlignment="viewStart"
|
||||||
android:textAllCaps="false"
|
android:textAllCaps="false"
|
||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/sourceTitleAndDate"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintHorizontal_bias="0.0"
|
app:layout_constraintHorizontal_bias="0.0"
|
||||||
app:layout_constraintLeft_toRightOf="@+id/itemImage"
|
app:layout_constraintStart_toEndOf="@+id/itemImage"
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintVertical_bias="0.0"
|
||||||
tools:text="Titre" />
|
tools:text="Titre" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:id="@+id/sourceTitleAndDate"
|
android:id="@+id/sourceTitleAndDate"
|
||||||
android:textSize="14sp"
|
android:layout_width="0dp"
|
||||||
tools:text="Google Actualité Il y a 5h"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:gravity="start"
|
||||||
android:textAlignment="viewStart"
|
android:textAlignment="viewStart"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/title"
|
android:textSize="14sp"
|
||||||
android:layout_marginTop="8dp"
|
app:layout_constraintBottom_toTopOf="@+id/guideline4"
|
||||||
app:layout_constraintLeft_toLeftOf="@+id/title"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
android:gravity="start" />
|
app:layout_constraintHorizontal_bias="0.0"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/itemImage"
|
||||||
|
tools:text="Google Actualité Il y a 5h" />
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:id="@+id/actionBar"
|
android:id="@+id/actionBar"
|
||||||
@ -58,9 +69,11 @@
|
|||||||
android:background="#BBBBBB"
|
android:background="#BBBBBB"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/sourceTitleAndDate">
|
app:layout_constraintTop_toTopOf="@+id/guideline4"
|
||||||
|
app:layout_constraintVertical_bias="1.0"
|
||||||
|
tools:visibility="visible">
|
||||||
|
|
||||||
<com.like.LikeButton
|
<com.like.LikeButton
|
||||||
android:id="@+id/favButton"
|
android:id="@+id/favButton"
|
||||||
@ -68,7 +81,6 @@
|
|||||||
android:layout_height="35dp"
|
android:layout_height="35dp"
|
||||||
android:layout_alignParentEnd="true"
|
android:layout_alignParentEnd="true"
|
||||||
android:layout_alignParentRight="true"
|
android:layout_alignParentRight="true"
|
||||||
|
|
||||||
android:layout_centerVertical="true"
|
android:layout_centerVertical="true"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
android:layout_marginRight="8dp"
|
android:layout_marginRight="8dp"
|
||||||
@ -110,7 +122,7 @@
|
|||||||
android:padding="4dp"
|
android:padding="4dp"
|
||||||
android:scaleType="centerCrop"
|
android:scaleType="centerCrop"
|
||||||
android:src="@drawable/ic_open_in_browser_black_24dp" />
|
android:src="@drawable/ic_open_in_browser_black_24dp" />
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
|
|
||||||
</android.support.constraint.ConstraintLayout>
|
</android.support.constraint.ConstraintLayout>
|
@ -9,6 +9,7 @@
|
|||||||
android:id="@+id/toolbar"
|
android:id="@+id/toolbar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="?attr/actionBarSize"
|
android:layout_height="?attr/actionBarSize"
|
||||||
app:theme="@style/ToolBarStyle" />
|
app:theme="@style/ToolBarStyle"
|
||||||
|
app:popupTheme="?attr/toolbarPopupTheme" />
|
||||||
|
|
||||||
</android.support.design.widget.AppBarLayout>
|
</android.support.design.widget.AppBarLayout>
|
@ -1,11 +0,0 @@
|
|||||||
<RelativeLayout
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
|
|
||||||
<Switch
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_centerHorizontal="true"
|
|
||||||
android:layout_centerVertical="true" />
|
|
||||||
</RelativeLayout>
|
|
@ -5,14 +5,14 @@
|
|||||||
<item android:id="@+id/action_search"
|
<item android:id="@+id/action_search"
|
||||||
android:title="@string/menu_home_search"
|
android:title="@string/menu_home_search"
|
||||||
android:icon="@drawable/ic_action_search"
|
android:icon="@drawable/ic_action_search"
|
||||||
app:showAsAction="always|collapseActionView"
|
app:showAsAction="ifRoom|collapseActionView"
|
||||||
app:actionViewClass="android.support.v7.widget.SearchView" />
|
app:actionViewClass="android.support.v7.widget.SearchView" />
|
||||||
|
|
||||||
<item android:id="@+id/readAll"
|
<item android:id="@+id/readAll"
|
||||||
android:icon="@drawable/ic_done_all_white_24dp"
|
android:icon="@drawable/ic_done_all_white_24dp"
|
||||||
android:title="@string/readAll"
|
android:title="@string/readAll"
|
||||||
android:orderInCategory="1"
|
android:orderInCategory="1"
|
||||||
app:showAsAction="always"/>
|
app:showAsAction="ifRoom"/>
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/refresh"
|
android:id="@+id/refresh"
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/loging_debug"
|
android:id="@+id/login_debug"
|
||||||
android:checkable="true"
|
android:checkable="true"
|
||||||
android:checked="false"
|
android:checked="false"
|
||||||
android:icon="@drawable/ic_bug_report"
|
android:icon="@drawable/ic_bug_report"
|
||||||
|
25
app/src/main/res/menu/reader_toolbar.xml
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/more_action"
|
||||||
|
android:icon="@drawable/ic_chrome_reader_mode"
|
||||||
|
android:title="@string/reader_action_more"
|
||||||
|
app:showAsAction="ifRoom" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/open_action"
|
||||||
|
android:icon="@drawable/ic_open_in_browser"
|
||||||
|
android:iconTint="@color/white"
|
||||||
|
android:title="@string/reader_action_open"
|
||||||
|
app:showAsAction="ifRoom" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/share_action"
|
||||||
|
android:icon="@drawable/ic_share_white_24dp"
|
||||||
|
android:title="@string/reader_action_share"
|
||||||
|
app:showAsAction="ifRoom" />
|
||||||
|
|
||||||
|
</menu>
|
162
app/src/main/res/values-af-rZA/strings.xml
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
<?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>
|
162
app/src/main/res/values-ar-rSA/strings.xml
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
<?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>
|
162
app/src/main/res/values-ca-rES/strings.xml
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
<?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>
|
162
app/src/main/res/values-cs-rCZ/strings.xml
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
<?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>
|
162
app/src/main/res/values-da-rDK/strings.xml
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
<?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>
|
162
app/src/main/res/values-de-rDE/strings.xml
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
<?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="title_activity_login">"Anmelden"</string>
|
||||||
|
<string name="prompt_password">"Passwort"</string>
|
||||||
|
<string name="prompt_http_password">"HTTP Passwort"</string>
|
||||||
|
<string name="action_sign_in">"Fortfahren"</string>
|
||||||
|
<string name="error_invalid_password">"Passwort ist nicht lang genug"</string>
|
||||||
|
<string name="error_field_required">"Pflichtfeld"</string>
|
||||||
|
<string name="prompt_url">"URL"</string>
|
||||||
|
<string name="withLoginSwitch">"Anmeldung erforderlich?"</string>
|
||||||
|
<string name="withHttpLoginSwitch">"HTTP Anmeldung erforderlich?"</string>
|
||||||
|
<string name="login_url_problem">"Ups. Du musst eventuell ein \"/\" am Ende der URL anhängen."</string>
|
||||||
|
<string name="prompt_login">"Benutzername"</string>
|
||||||
|
<string name="prompt_http_login">"HTTP Benutzername"</string>
|
||||||
|
<string name="label_share">"Teilen"</string>
|
||||||
|
<string name="readAll">"Alle gelesen"</string>
|
||||||
|
<string name="action_disconnect">"Verbindung trennen"</string>
|
||||||
|
<string name="title_activity_settings">"Einstellungen"</string>
|
||||||
|
<string name="pref_header_general">"Allgemein"</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">"Neue Quelle hinzufügen"</string>
|
||||||
|
<string name="add_source_save">"Speichern"</string>
|
||||||
|
<string name="wrong_infos">"Überprüfe deine Angaben noch einmal."</string>
|
||||||
|
<string name="all_posts_not_read">"Nicht alle Beiträge wurden gelesen"</string>
|
||||||
|
<string name="all_posts_read">"Alle Beiträge wurden gelesen"</string>
|
||||||
|
<string name="cant_get_favs">"Favoriten können nicht abgerufen werden"</string>
|
||||||
|
<string name="cant_get_new_elements">"Neue Artikel können nicht abgerufen werden"</string>
|
||||||
|
<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_favs">"Favoriten"</string>
|
||||||
|
<string name="action_about">"Über"</string>
|
||||||
|
<string name="marked_as_read">"Artikel gelesen"</string>
|
||||||
|
<string name="undo_string">"Rückgängig"</string>
|
||||||
|
<string name="addStringNoUrl">"Melde dich an um Quellen hinzuzufügen."</string>
|
||||||
|
<string name="cant_get_sources">"Quellen können nicht abgerufen werden."</string>
|
||||||
|
<string name="cant_create_source">"Quelle kann nicht gespeichert werden."</string>
|
||||||
|
<string name="cant_get_spouts">"Can't get spouts list."</string>
|
||||||
|
<string name="form_not_complete">"Das Formular ist nicht vollständig"</string>
|
||||||
|
<string name="pref_header_links">"Links"</string>
|
||||||
|
<string name="issue_tracker_link">"Issue Tracker"</string>
|
||||||
|
<string name="issue_tracker_summary">"Melde einen Bug oder rege ein neues Feature an"</string>
|
||||||
|
<string name="warning_wrong_url">"WARNUNG"</string>
|
||||||
|
<string name="pref_switch_card_view_title">"Kachelansicht"</string>
|
||||||
|
<string name="cant_mark_favortie">"Artikel kann nicht als Favorit markiert werden"</string>
|
||||||
|
<string name="cant_unmark_favortie">"Eintrag kann nicht aus Favoriten entfernt werden"</string>
|
||||||
|
<string name="share">"Teilen"</string>
|
||||||
|
<string name="rating_prompt_title">"Gefällt Dir die App?"</string>
|
||||||
|
<string name="rating_prompt_yes">"Ja!"</string>
|
||||||
|
<string name="rating_prompt_no">"Nicht wirklich…"</string>
|
||||||
|
<string name="rating_prompt_feedback_title">"Magst du uns sagen warum?"</string>
|
||||||
|
<string name="rating_prompt_feedback_yes">"OK!"</string>
|
||||||
|
<string name="rating_prompt_feedback_no">"Nicht jetzt."</string>
|
||||||
|
<string name="rating_prompt_rating_title">"Wunderbar! Magst du uns im Play Store bewerten?"</string>
|
||||||
|
<string name="rating_prompt_rating_yes">"Sicher!"</string>
|
||||||
|
<string name="rating_prompt_rating_no">"Nicht jetzt."</string>
|
||||||
|
<string name="rating_prompt_thanks">"Vielen Dank, dein Feedback hilft die App zu verbessern!"</string>
|
||||||
|
<string name="switch_unread_count">"Zeige die Zahl ungelesener Artikel in der unteren Leiste."</string>
|
||||||
|
<string name="switch_unread_count_title">"Zeige Anzahl ungelesener Artikel"</string>
|
||||||
|
<string name="display_all_counts_title">"Zeige Anzahl der Favoriten und gelesenen Artikel"</string>
|
||||||
|
<string name="menu_share_the_app">"Freunde einladen"</string>
|
||||||
|
<string name="invitation_title">"Probiere diese App für deine Selfoss RSS-Feeds!"</string>
|
||||||
|
<string name="invitation_message">"Ich benutze diese App für meine Selfoss RSS-Feeds. Vielleicht magst du sie auch!"</string>
|
||||||
|
<string name="invitation_cta">"Probier die App"</string>
|
||||||
|
<string name="text_wrong_url">"Sie scheinen eine ungültige URL verwenden. Stellen Sie sicher, dass die URL richtig ist. Sollte das Problem weiterhin bestehen kontaktieren Sie mich (über den Playstore-Kontakt-Link). Bitte beachten Sie, dass Sie Selfoss benötigen um RSS-Feeds zu lesen."</string>
|
||||||
|
<string name="pref_general_internal_browser_title">"Öffne Links innerhalb der App"</string>
|
||||||
|
<string name="pref_general_internal_browser_on">"Artikel werden innerhalb der App geöffnet"</string>
|
||||||
|
<string name="pref_general_internal_browser_off">"Artikel werden mit deinem Standard-Browser geöffnet"</string>
|
||||||
|
<string name="prefer_article_viewer_title">"Verwenden Sie den Artikel-viewer"</string>
|
||||||
|
<string name="prefer_article_viewer_on">"Artikel-Viewer wird anstelle des internen Browser verwendet"</string>
|
||||||
|
<string name="prefer_article_viewer_off">"Der internen Browser wird anstelle des Artikel-Viewer verwendet"</string>
|
||||||
|
<string name="pref_general_category_links">"Umgang mit Links"</string>
|
||||||
|
<string name="pref_general_category_displaying">"Ansicht"</string>
|
||||||
|
<string name="pref_general_category_actions">"Aktionen"</string>
|
||||||
|
<string name="pref_switch_card_view_on">"Artikel werden als Kacheln angezeigt"</string>
|
||||||
|
<string name="pref_switch_card_view_off">"Artikel werden als Liste angezeigt"</string>
|
||||||
|
<string name="pref_switch_actions_tap_on">"Zeigt die Aktionsleiste unter dem Artikel"</string>
|
||||||
|
<string name="pref_switch_actions_tap_off">"Bei der Auswahl eines Artikels wird dieser im ausgewählten Browser geöffnet"</string>
|
||||||
|
<string name="menu_home_refresh">"Remote-Aktualisierung"</string>
|
||||||
|
<string name="refresh_success_response">"Selfoss wird aktualisiert, du kannst jetzt die Artikel laden"</string>
|
||||||
|
<string name="refresh_failer_message">"Das Update hat nicht funktioniert, versuche es erneut oder überprüfe die Protokolle von Selfoss."</string>
|
||||||
|
<string name="refresh_in_progress">"Aktualisierung läuft"</string>
|
||||||
|
<string name="new_apk_available_title">"Eine neue Version ist verfügbar."</string>
|
||||||
|
<string name="new_apk_available_message">"Eine neue APK steht im offiziellen Repository zur Verfügung."</string>
|
||||||
|
<string name="new_apk_available_get">"Jetzt herunterladen"</string>
|
||||||
|
<string name="new_apk_available_no">"Version ignorieren"</string>
|
||||||
|
<string name="intro_hello_title">"Hallo!"</string>
|
||||||
|
<string name="intro_hello_message">"Danke fürs Herunterladen der App!"</string>
|
||||||
|
<string name="intro_needs_selfoss_title">"Bevor du beginnst…"</string>
|
||||||
|
<string name="intro_needs_selfoss_message">"Die App kann nicht ohne Selfoss-Instanz benutzt werden."</string>
|
||||||
|
<string name="intro_needs_selfoss_link">"Was ist Selfoss?"</string>
|
||||||
|
<string name="intro_all_set_title">"Fertig!"</string>
|
||||||
|
<string name="intro_all_set_message">"Sie können die App jetzt verwenden. Vergiss nicht deine App unter \"Einstellungen\" zu konfigurieren. Dort findest du auch einige nützliche Links."</string>
|
||||||
|
<string name="card_height_title">Maximale Kartenhöhe</string>
|
||||||
|
<string name="card_height_on">Kartenhöhe passt sich Inhalt an</string>
|
||||||
|
<string name="card_height_off">Kartenhöhe ist fix</string>
|
||||||
|
<string name="source_code">Quellcode</string>
|
||||||
|
<string name="cant_mark_read">Artikel kann nicht als gelesen markiert werden</string>
|
||||||
|
<string name="drawer_error_loading_tags">Fehler beim Laden der Tags…</string>
|
||||||
|
<string name="drawer_error_loading_sources">Fehler beim Laden der Quellen…</string>
|
||||||
|
<string name="drawer_item_filters">Filter</string>
|
||||||
|
<string name="drawer_action_clear">leeren</string>
|
||||||
|
<string name="drawer_item_tags">Tags</string>
|
||||||
|
<string name="drawer_item_sources">Quellen</string>
|
||||||
|
<string name="drawer_action_edit">bearbeiten</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">Keine Quellen geladen</string>
|
||||||
|
<string name="drawer_loading">Lade…</string>
|
||||||
|
<string name="menu_home_search">Suche</string>
|
||||||
|
<string name="can_delete_source">Can\'t delete the source…</string>
|
||||||
|
<string name="base_url_error">Beim Versuch deine Selfoss-Instanz zu erreichen ist ein Fehler aufgetreten. Solltet dieser Fehler bestehen bleiben, trete bitte mit mir in Kontakt.</string>
|
||||||
|
<string name="pref_header_theme">Designs</string>
|
||||||
|
<string name="default_theme">Standard</string>
|
||||||
|
<string name="teal_orange_theme">Türkis/Orange/Hell</string>
|
||||||
|
<string name="cyan_pink_theme">Cyan/Pink/Hell</string>
|
||||||
|
<string name="grey_orange_theme">Türkis/Orange/Hell</string>
|
||||||
|
<string name="blue_amber_theme">Blau/Amber/Hell</string>
|
||||||
|
<string name="indigo_pink_theme">Indigo/Pink/Hell</string>
|
||||||
|
<string name="red_teal_theme">Rot/Türkis/Hell</string>
|
||||||
|
<string name="teal_orange_dark_theme">Türkis/Orange/Dunkel</string>
|
||||||
|
<string name="cyan_pink_dark_theme">Cyan/Pink/Dunkel</string>
|
||||||
|
<string name="default_dark_theme">Standard (Dunkel)</string>
|
||||||
|
<string name="grey_orange_dark_theme">Grau/Orange/Dunkel</string>
|
||||||
|
<string name="blue_amber_dark_theme">Blau/Gelb/Dunkel</string>
|
||||||
|
<string name="indigo_pink_dark_theme">Indigo/Pink/Dunkel</string>
|
||||||
|
<string name="red_teal_dark_theme">Rot/Türkis/Dunkel</string>
|
||||||
|
<string name="pref_header_debug">Debug</string>
|
||||||
|
<string name="login_debug_title">Aktivieren, um Login-Fehler zu protokollieren</string>
|
||||||
|
<string name="login_debug_on">Fehler auf der Login-Seite werden protokolliert</string>
|
||||||
|
<string name="login_debug_off">Fehler auf der Login-Seite werden nicht protokolliert</string>
|
||||||
|
<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_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">Übersetzung</string>
|
||||||
|
<string name="cant_open_invalid_url">The item url is invalid. I\'m looking into solving this issue so the app won\'t crash.</string>
|
||||||
|
<string name="drawer_report_bug">Report a bug</string>
|
||||||
|
<string name="items_number_should_be_number">The items number should be an integer.</string>
|
||||||
|
<string name="reader_action_more">Read more</string>
|
||||||
|
<string name="reader_action_open">Open in browser</string>
|
||||||
|
<string name="reader_action_share">Share</string>
|
||||||
|
<string name="pref_switch_actions_pager_scroll">Mark articles as read when scrolling between articles.</string>
|
||||||
|
</resources>
|
162
app/src/main/res/values-el-rGR/strings.xml
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
<?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>
|
162
app/src/main/res/values-en-rID/strings.xml
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
<?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>
|
162
app/src/main/res/values-es-rES/strings.xml
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--Generated by crowdin.com-->
|
||||||
|
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
<string name="app_name">"Lector para Selfoss"</string>
|
||||||
|
<string name="title_activity_login">"Iniciar sesión"</string>
|
||||||
|
<string name="prompt_password">"Contraseña"</string>
|
||||||
|
<string name="prompt_http_password">"Contraseña HTTP"</string>
|
||||||
|
<string name="action_sign_in">"Empezar"</string>
|
||||||
|
<string name="error_invalid_password">"La contraseña no es suficientemente larga"</string>
|
||||||
|
<string name="error_field_required">"Campo requerido"</string>
|
||||||
|
<string name="prompt_url">"Url"</string>
|
||||||
|
<string name="withLoginSwitch">"Inicio de sesión requerido ?"</string>
|
||||||
|
<string name="withHttpLoginSwitch">"Inicio de sesión HTTP requerido ?"</string>
|
||||||
|
<string name="login_url_problem">"Oops. Puede que necesite añadir un \"/\" al final de la url."</string>
|
||||||
|
<string name="prompt_login">"Nombre de usuario"</string>
|
||||||
|
<string name="prompt_http_login">"Nombre de usuario HTTP"</string>
|
||||||
|
<string name="label_share">"Compartir"</string>
|
||||||
|
<string name="readAll">"Leer todo"</string>
|
||||||
|
<string name="action_disconnect">"Desconectar"</string>
|
||||||
|
<string name="title_activity_settings">"Configuración"</string>
|
||||||
|
<string name="pref_header_general">"General"</string>
|
||||||
|
<string name="pref_switch_actions_tap_title">"Acción tocar en los artículos"</string>
|
||||||
|
<string name="add_source_hint_tags">"Etiqueta1, Etiqueta2, Etiqueta3"</string>
|
||||||
|
<string name="add_source_hint_url">"Enlace"</string>
|
||||||
|
<string name="add_source_hint_name">"Nombre"</string>
|
||||||
|
<string name="add_source">"Añadir una fuente"</string>
|
||||||
|
<string name="add_source_save">"Guardar"</string>
|
||||||
|
<string name="wrong_infos">"Revise sus datos de nuevo."</string>
|
||||||
|
<string name="all_posts_not_read">"No todas las publicaciones fueron leídas"</string>
|
||||||
|
<string name="all_posts_read">"Todas las publicaciones fueron leídas"</string>
|
||||||
|
<string name="cant_get_favs">"No se pueden obtener favoritos"</string>
|
||||||
|
<string name="cant_get_new_elements">"No puede recibir nuevos artículos"</string>
|
||||||
|
<string name="cant_get_read">"No puede recibir artículos leídos"</string>
|
||||||
|
<string name="nothing_here">"Nada aquí"</string>
|
||||||
|
<string name="tab_new">"Nuevo"</string>
|
||||||
|
<string name="tab_read">"Todo"</string>
|
||||||
|
<string name="tab_favs">"Favoritos"</string>
|
||||||
|
<string name="action_about">"Acerca de"</string>
|
||||||
|
<string name="marked_as_read">"Artículo leído"</string>
|
||||||
|
<string name="undo_string">"Deshacer"</string>
|
||||||
|
<string name="addStringNoUrl">"Iniciar sesión para añadir fuentes."</string>
|
||||||
|
<string name="cant_get_sources">"No se puede obtener la lista de fuentes."</string>
|
||||||
|
<string name="cant_create_source">"No se puede crear la fuente."</string>
|
||||||
|
<string name="cant_get_spouts">"No se puede obtener la lista de fuentes."</string>
|
||||||
|
<string name="form_not_complete">"El formulario no está completo"</string>
|
||||||
|
<string name="pref_header_links">"Enlaces"</string>
|
||||||
|
<string name="issue_tracker_link">"Rastreador de Incidencias"</string>
|
||||||
|
<string name="issue_tracker_summary">"Reportar un error o solicitar una nueva función"</string>
|
||||||
|
<string name="warning_wrong_url">"ADVERTENCIA"</string>
|
||||||
|
<string name="pref_switch_card_view_title">"Vista de la tarjeta"</string>
|
||||||
|
<string name="cant_mark_favortie">"No puede marcar el artículo como favorito"</string>
|
||||||
|
<string name="cant_unmark_favortie">"No se puede quitar el artículo de favoritos"</string>
|
||||||
|
<string name="share">"Compartir"</string>
|
||||||
|
<string name="rating_prompt_title">"¿Disfrutando la aplicación?"</string>
|
||||||
|
<string name="rating_prompt_yes">"¡Sí!"</string>
|
||||||
|
<string name="rating_prompt_no">"La verdad es que no…"</string>
|
||||||
|
<string name="rating_prompt_feedback_title">"¿Puede decirnos por qué?"</string>
|
||||||
|
<string name="rating_prompt_feedback_yes">"¡Vale!"</string>
|
||||||
|
<string name="rating_prompt_feedback_no">"Ahora no."</string>
|
||||||
|
<string name="rating_prompt_rating_title">"¡Excelente! ¿Puede valorarnos en la tienda?"</string>
|
||||||
|
<string name="rating_prompt_rating_yes">"¡Claro!"</string>
|
||||||
|
<string name="rating_prompt_rating_no">"No en este momento."</string>
|
||||||
|
<string name="rating_prompt_thanks">"¡Gracias, sus comentarios ayudan a mejorar la aplicación!"</string>
|
||||||
|
<string name="switch_unread_count">"Mostrar el recuento no leído como una insignia de la barra inferior."</string>
|
||||||
|
<string name="switch_unread_count_title">"Mostrar recuento no leído"</string>
|
||||||
|
<string name="display_all_counts_title">"Mostrar recuento de favoritos y leídos"</string>
|
||||||
|
<string name="menu_share_the_app">"Invitar amigos"</string>
|
||||||
|
<string name="invitation_title">"¡Prueba esta aplicación para tu contenido RSS de Selfoss!"</string>
|
||||||
|
<string name="invitation_message">"Yo uso esta aplicación para mi contenido RSS de Selfoss. ¡Te puede gusta también!"</string>
|
||||||
|
<string name="invitation_cta">"Probar la aplicación"</string>
|
||||||
|
<string name="text_wrong_url">"Parece estar tratando de utilizar una dirección URL inválida. Asegúrese de que sea correcta y si el problema persiste, póngase en contacto conmigo (mediante el enlace de contacto de la tienda). Tenga en cuenta que la aplicación necesita utilizar Selfoss. No se puede acceder al contenido RSS sin él."</string>
|
||||||
|
<string name="pref_general_internal_browser_title">"Abrir enlaces dentro de la aplicación"</string>
|
||||||
|
<string name="pref_general_internal_browser_on">"Los artículos se abrirán dentro de la aplicación"</string>
|
||||||
|
<string name="pref_general_internal_browser_off">"Los artículos se abrirán con tu navegador predeterminado"</string>
|
||||||
|
<string name="prefer_article_viewer_title">"Utilizar el visor de artículo"</string>
|
||||||
|
<string name="prefer_article_viewer_on">"Se usará el visor de artículos en lugar del navegador interno"</string>
|
||||||
|
<string name="prefer_article_viewer_off">"Se utilizará el navegador interno en lugar del visor de artículo"</string>
|
||||||
|
<string name="pref_general_category_links">"Control de enlaces"</string>
|
||||||
|
<string name="pref_general_category_displaying">"Mostrando"</string>
|
||||||
|
<string name="pref_general_category_actions">"Acciones"</string>
|
||||||
|
<string name="pref_switch_card_view_on">"Los artículos se mostrarán como tarjetas"</string>
|
||||||
|
<string name="pref_switch_card_view_off">"Los artículos se mostrarán como una lista"</string>
|
||||||
|
<string name="pref_switch_actions_tap_on">"Muestra la barra de acción debajo del artículo"</string>
|
||||||
|
<string name="pref_switch_actions_tap_off">"Al seleccionar un artículo se abrirá en el navegador seleccionado"</string>
|
||||||
|
<string name="menu_home_refresh">"Actualizar remoto"</string>
|
||||||
|
<string name="refresh_success_response">"Se actualizó el remoto, ahora puede recargar la lista de artículos"</string>
|
||||||
|
<string name="refresh_failer_message">"La actualización no funcionó, inténtalo más tarde o compruebe los registros de selfoss."</string>
|
||||||
|
<string name="refresh_in_progress">"Actualización en progreso"</string>
|
||||||
|
<string name="new_apk_available_title">"Una nueva versión está disponible."</string>
|
||||||
|
<string name="new_apk_available_message">"Un APK nuevo está disponible para descarga en el repositorio oficial."</string>
|
||||||
|
<string name="new_apk_available_get">"Descargar ahora"</string>
|
||||||
|
<string name="new_apk_available_no">"Ignorar versión"</string>
|
||||||
|
<string name="intro_hello_title">"¡Hola!"</string>
|
||||||
|
<string name="intro_hello_message">"¡Gracias por descargar la aplicación!"</string>
|
||||||
|
<string name="intro_needs_selfoss_title">"Antes de empezar…"</string>
|
||||||
|
<string name="intro_needs_selfoss_message">"No se puede utilizar la aplicación sin una instancia de Selfoss."</string>
|
||||||
|
<string name="intro_needs_selfoss_link">"¿Qué es Selfoss?"</string>
|
||||||
|
<string name="intro_all_set_title">"¡Todo listo!"</string>
|
||||||
|
<string name="intro_all_set_message">"Estás listo para utilizar la aplicación. No olvides ir a la página de configuración para configurar su aplicación, y donde usted encontrará algunos enlaces útiles."</string>
|
||||||
|
<string name="card_height_title">Tarjetas de altura completas</string>
|
||||||
|
<string name="card_height_on">Altura de tarjetas se ajustará a su contenido</string>
|
||||||
|
<string name="card_height_off">Se fijará la altura de la tarjeta</string>
|
||||||
|
<string name="source_code">Código fuente</string>
|
||||||
|
<string name="cant_mark_read">No puede marcar el artículo como leído</string>
|
||||||
|
<string name="drawer_error_loading_tags">Error al cargar etiquetas…</string>
|
||||||
|
<string name="drawer_error_loading_sources">Error al cargar fuentes…</string>
|
||||||
|
<string name="drawer_item_filters">Filtros</string>
|
||||||
|
<string name="drawer_action_clear">limpiar</string>
|
||||||
|
<string name="drawer_item_tags">Etiquetas</string>
|
||||||
|
<string name="drawer_item_sources">Fuentes</string>
|
||||||
|
<string name="drawer_action_edit">editar</string>
|
||||||
|
<string name="cache_drawer_error" tools:keep="@string/cache_drawer_error">No se pudieron guardar en caché los datos de su cajón</string>
|
||||||
|
<string name="no_tags_loaded">No hay etiquetas cargadas</string>
|
||||||
|
<string name="no_sources_loaded">No hay fuentes cargadas</string>
|
||||||
|
<string name="drawer_loading">Cargando…</string>
|
||||||
|
<string name="menu_home_search">Buscar</string>
|
||||||
|
<string name="can_delete_source">No se puede eliminar la fuente…</string>
|
||||||
|
<string name="base_url_error">Hubo un problema al intentar comunicarse con su instancia de Selfoss. Si el problema persiste, póngase en contacto conmigo.</string>
|
||||||
|
<string name="pref_header_theme">Temas</string>
|
||||||
|
<string name="default_theme">Predeterminado</string>
|
||||||
|
<string name="teal_orange_theme">Turquesa/Naranja/Claro</string>
|
||||||
|
<string name="cyan_pink_theme">Cian/Rosa/Claro</string>
|
||||||
|
<string name="grey_orange_theme">Gris/Naranja/Claro</string>
|
||||||
|
<string name="blue_amber_theme">Azul/Ámbar/Claro</string>
|
||||||
|
<string name="indigo_pink_theme">Índigo/Rosa/Claro</string>
|
||||||
|
<string name="red_teal_theme">Rojo/Turquesa/Claro</string>
|
||||||
|
<string name="teal_orange_dark_theme">Turquesa/Naranja/Oscuro</string>
|
||||||
|
<string name="cyan_pink_dark_theme">Cian/Rosa/Oscuro</string>
|
||||||
|
<string name="default_dark_theme">Predeterminado/Oscuro</string>
|
||||||
|
<string name="grey_orange_dark_theme">Gris/Naranja/Oscuro</string>
|
||||||
|
<string name="blue_amber_dark_theme">Azul/Ámbar/Oscuro</string>
|
||||||
|
<string name="indigo_pink_dark_theme">Índigo/Rosa/Oscuro</string>
|
||||||
|
<string name="red_teal_dark_theme">Rojo/Turquesa/Oscuro</string>
|
||||||
|
<string name="pref_header_debug">Depurar</string>
|
||||||
|
<string name="login_debug_title">Activar para registrar errores de inicio de sesión</string>
|
||||||
|
<string name="login_debug_on">Cualquier error en la página de inicio de sesión se registrará</string>
|
||||||
|
<string name="login_debug_off">No hay registro en la página de inicio de sesión</string>
|
||||||
|
<string name="login_menu_debug">Depurar</string>
|
||||||
|
<string name="self_hosted_cert_switch">Utilizando un certificado alojado propiamente ?</string>
|
||||||
|
<string name="self_signed_cert_warning">Por razones de seguridad, los certificados propios no son compatibles por defecto. Activando esto, no seré responsable de cualquier problema de seguridad que encuentre.</string>
|
||||||
|
<string name="pref_selfoss_category">Api de Selfoss</string>
|
||||||
|
<string name="pref_api_items_number_title">Número de artículos cargados</string>
|
||||||
|
<string name="read_debug_title">¿Leer los artículos que aparecen como no leídos?</string>
|
||||||
|
<string name="read_debug_off">Sin registro al marcar un elemento como leído</string>
|
||||||
|
<string name="read_debug_on">Llamadas a la Api se registrarán al marcar un artículo como leído</string>
|
||||||
|
<string name="summary_debug_identifier">Identificador de depuración</string>
|
||||||
|
<string name="unique_id_to_clipboard">Identificador copiado a su portapapeles</string>
|
||||||
|
<string name="display_header_drawer_summary">Mostrar una cabecera con la url de instancia de selfoss en el cajón lateral.</string>
|
||||||
|
<string name="display_header_drawer_title">Cabecera de cuenta</string>
|
||||||
|
<string name="login_everything_title">Registrando todas las llamadas a la api</string>
|
||||||
|
<string name="login_everything_on">Esto registrará cada llamada a la api para propósito de depuración.</string>
|
||||||
|
<string name="login_everything_off">Ninguna llamada de api se registrará</string>
|
||||||
|
<string name="pref_general_infinite_loading_title">Cargar más artículos en desplazamiento</string>
|
||||||
|
<string name="translation">Traducción</string>
|
||||||
|
<string name="cant_open_invalid_url">La url del elemento no es válida. Estoy buscando resolver este problema para que la aplicación no colapse.</string>
|
||||||
|
<string name="drawer_report_bug">Reportar un error</string>
|
||||||
|
<string name="items_number_should_be_number">El número de artículos debe ser un número entero.</string>
|
||||||
|
<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>
|
||||||
|
</resources>
|
162
app/src/main/res/values-fi-rFI/strings.xml
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
<?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>
|