Compare commits

...

88 Commits
v1.5.7 ... v1.6

Author SHA1 Message Date
c17980a032 Versionning changes. 2018-04-15 21:32:34 +02:00
a929e419d9 Version names. 2018-04-15 15:46:42 +02:00
487d484bae More styling. 2018-04-15 11:33:37 +02:00
0ca4c04c61 Add to sources. 2018-04-11 22:25:51 +02:00
c857cf2d67 No theme handling for the login page. 2018-04-11 22:25:51 +02:00
acb502028b Article fragment color. 2018-04-11 22:25:51 +02:00
533636f3a1 Link colors in cards and list items. 2018-04-11 22:25:51 +02:00
eb5672901b AS update. 2018-04-11 22:25:51 +02:00
53a8716b51 New translations strings.xml (Spanish) (#190) 2018-04-09 11:06:40 +02:00
3aaff612af WIP. All activities dynamic themes. 2018-04-08 14:16:16 +02:00
fdcd8c6c6a Dynamic theme handling. Works only on the homeactivity for now. 2018-04-08 13:08:42 +02:00
bafd478604 Keeping the source even when fetching details from mercury. 2018-04-07 19:55:55 +02:00
987513a88b Version for alpha deploy. 2018-04-07 19:31:50 +02:00
a450ab2a3b Handling items with multiple tags. 2018-04-07 18:51:39 +02:00
db89fe5aad Updating lateral panel tags without network call. 2018-04-07 18:19:24 +02:00
67a30b92f6 Cleaning. 2018-04-07 17:19:41 +02:00
c397de8c3e New Crowdin translations (#189)
* New translations strings.xml (German)

* New translations strings.xml (Japanese)

* New translations strings.xml (Ukrainian)

* New translations strings.xml (Turkish)

* New translations strings.xml (Swedish)

* New translations strings.xml (Spanish)

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

* New translations strings.xml (Russian)

* New translations strings.xml (Romanian)

* New translations strings.xml (Portuguese, Brazilian)

* New translations strings.xml (Portuguese)

* New translations strings.xml (Polish)

* New translations strings.xml (Norwegian)

* New translations strings.xml (Korean)

* New translations strings.xml (Italian)

* New translations strings.xml (Afrikaans)

* New translations strings.xml (Indonesian)

* New translations strings.xml (Hungarian)

* New translations strings.xml (Hebrew)

* New translations strings.xml (Greek)

* New translations strings.xml (French)

* New translations strings.xml (Finnish)

* New translations strings.xml (Dutch)

* New translations strings.xml (Danish)

* New translations strings.xml (Czech)

* New translations strings.xml (Chinese Traditional)

* New translations strings.xml (Chinese Simplified)

* New translations strings.xml (Catalan)

* New translations strings.xml (Arabic)

* New translations strings.xml (Vietnamese)

* New translations strings.xml (French)

* New translations strings.xml (Portuguese)

* New translations strings.xml (Portuguese, Brazilian)

* New translations strings.xml (Spanish)

* New translations strings.xml (Chinese Simplified)
2018-04-07 10:56:13 +02:00
b4db532c45 Fixes #184. Needs translations. 2018-04-07 10:40:27 +02:00
ebecc9c80a Fixes #188. 2018-04-02 09:08:58 +02:00
4f8556fca8 Change version code generation. 2018-03-31 18:25:14 +02:00
68892fb41b Fixed play store update. 2018-03-31 08:22:57 +02:00
6d6f6c72ac Fixes #187. 2018-03-31 07:40:11 +02:00
df5556b945 Build. 2018-03-30 22:17:47 +02:00
d6c74049c3 Fixes #185. 2018-03-30 22:14:49 +02:00
18946464a2 Do nothing if ids are empty. More logging. 2018-03-30 19:54:42 +02:00
edb5eabee7 Fixing NPE. And obfuscation. 2018-03-29 19:59:07 +02:00
99a305f3e2 Cache url as parameter. 2018-03-28 21:11:25 +02:00
68dc5a6acf Debugging read all items. WILL ONLY WORK IF THE OPTION IS ENABLED IN SETTINGS. 2018-03-28 19:26:59 +02:00
6816461502 D8 enabling and gradle cache debug. 2018-03-28 19:13:47 +02:00
15b93bbd9e Updated AS. Enabled build cache. 2018-03-27 20:00:02 +02:00
cd61e140f6 New Crowdin translations (#182)
* New translations strings.xml (German)

* New translations strings.xml (German)

* New translations strings.xml (French)

* New translations strings.xml (German)

* New translations strings.xml (French)

* New translations strings.xml (Portuguese, Brazilian)
2018-03-26 16:08:18 +02:00
4d861a84e6 Fixing permissions added by firebase update
See https://www.reddit.com/r/androiddev/comments/86c02l/google_play_services_1200_released/dw4ehln/?context=0 for more details.
2018-03-26 12:00:57 +02:00
f24de68618 Code cleaning and versions updates. 2018-03-25 21:11:47 +02:00
3bcffff444 Fixing crashlytics issues. 2018-03-25 20:54:33 +02:00
75e9031fa5 Changelog. 2018-03-19 07:53:46 +01:00
3b77e24399 Removed english indonesian translation. 2018-03-19 07:48:08 +01:00
0a738e895f Version updates. 2018-03-03 16:18:29 +01:00
242e5ba035 New Crowdin translations (#181)
* New translations strings.xml (Spanish)

* New translations strings.xml (Spanish)

* New translations strings.xml (Indonesian)

* New translations strings.xml (Ukrainian)

* New translations strings.xml (Turkish)

* New translations strings.xml (Swedish)

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

* New translations strings.xml (Russian)

* New translations strings.xml (Romanian)

* New translations strings.xml (Portuguese, Brazilian)

* New translations strings.xml (Portuguese)

* New translations strings.xml (Polish)

* New translations strings.xml (Norwegian)

* New translations strings.xml (Korean)

* New translations strings.xml (Japanese)

* New translations strings.xml (Italian)

* New translations strings.xml (Hungarian)

* New translations strings.xml (Afrikaans)

* New translations strings.xml (Hebrew)

* New translations strings.xml (Greek)

* New translations strings.xml (German)

* New translations strings.xml (French)

* New translations strings.xml (Finnish)

* New translations strings.xml (English, Indonesia)

* New translations strings.xml (Dutch)

* New translations strings.xml (Danish)

* New translations strings.xml (Czech)

* New translations strings.xml (Chinese Traditional)

* New translations strings.xml (Chinese Simplified)

* New translations strings.xml (Catalan)

* New translations strings.xml (Arabic)

* New translations strings.xml (Vietnamese)
2018-03-03 16:10:02 +01:00
c94612106c Changelog. 2018-03-03 16:03:07 +01:00
320924b4ed Fixes #180. 2018-03-03 16:00:56 +01:00
403ecc4521 Trying to understand #83. 2018-02-07 21:30:39 +01:00
6a50b37364 Added a padding to the recyclerview. 2018-02-07 21:22:08 +01:00
d9d341ac5d Versions updates. 2018-02-07 21:16:51 +01:00
e9805b731e New translations strings.xml (Portuguese, Brazilian) (#177) 2018-02-06 11:35:31 +01:00
c6d4337cd1 New Crowdin translations (#176)
* New translations strings.xml (English, Indonesia)

* New translations strings.xml (English, Indonesia)

* New translations strings.xml (English, Indonesia)

* New translations strings.xml (English, Indonesia)

* New translations strings.xml (English, Indonesia)
2018-02-01 17:55:54 +01:00
173f4b2ff7 Build. 2018-01-27 17:23:31 +01:00
3b9436264c Still fixing small fonts issues. 2018-01-27 17:17:43 +01:00
35fe87d79d New Crowdin translations (#175)
* New translations strings.xml (Afrikaans)

* New translations strings.xml (Italian)

* New translations strings.xml (Ukrainian)

* New translations strings.xml (Turkish)

* New translations strings.xml (Swedish)

* New translations strings.xml (Spanish)

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

* New translations strings.xml (Russian)

* New translations strings.xml (Romanian)

* New translations strings.xml (Portuguese, Brazilian)

* New translations strings.xml (Portuguese)

* New translations strings.xml (Polish)

* New translations strings.xml (Norwegian)

* New translations strings.xml (Korean)

* New translations strings.xml (Japanese)

* New translations strings.xml (Indonesian)

* New translations strings.xml (Arabic)

* New translations strings.xml (Hungarian)

* New translations strings.xml (Hebrew)

* New translations strings.xml (Greek)

* New translations strings.xml (German)

* New translations strings.xml (French)

* New translations strings.xml (Finnish)

* New translations strings.xml (English, Indonesia)

* New translations strings.xml (Dutch)

* New translations strings.xml (Danish)

* New translations strings.xml (Czech)

* New translations strings.xml (Chinese Traditional)

* New translations strings.xml (Chinese Simplified)

* New translations strings.xml (Catalan)

* New translations strings.xml (Vietnamese)

* New translations strings.xml (French)
2018-01-27 12:39:55 +01:00
f1bb7ba9ad Should fix #174. Added the ability to set the font size of the content of the article reader. 2018-01-27 12:29:14 +01:00
279f229166 Trying jekkyl. 2018-01-21 18:53:00 +01:00
be1794e27b Github page. 2018-01-21 18:23:47 +01:00
4d4a2039c8 Reformated code according to official kotling style. 2018-01-21 18:08:39 +01:00
3013ae4f35 Set theme jekyll-theme-cayman 2018-01-21 17:56:58 +01:00
bb3f7d3786 Page. 2018-01-21 17:54:24 +01:00
f7cc305e44 Changed suffix back to normal. 2018-01-16 22:13:00 +01:00
da17f89148 Building. 2018-01-12 06:26:39 +01:00
ec71ab3c6f Fix issue with list adapter. 2018-01-12 06:24:06 +01:00
0d007f1492 Added logging for StringIndexOutOfBound. 2018-01-12 05:19:49 +01:00
96f8663b8f Simpler (kind of) way to have multiple builds a day) 2018-01-12 05:15:28 +01:00
1a4bc1b301 Refactoring to use #158. 2018-01-12 04:58:43 +01:00
b51ae58a97 A lot of logs to clean after solving an issue. 2018-01-11 21:21:40 +01:00
b126fc32da Fixing the same issue as #158. 2018-01-11 21:10:53 +01:00
b8d234c415 Removed sonar. 2018-01-11 20:53:17 +01:00
2c8902d404 Working on #169.
List isn't reloaded each time.
When new articles arrive, the list is still updated, but the list stays at the same (old) position.
Not sure if I keep this behavior, or try to keep the old position and scroll to it.
2018-01-06 15:37:12 +01:00
80ad65b196 New Crowdin translations (#171)
* New translations strings.xml (French)

* New translations strings.xml (French)
2018-01-06 03:52:23 +01:00
744d9ba72b Contributing to translations. 2018-01-06 03:38:08 +01:00
0c1d708588 Merge pull request #170 from aancel/fix/values-fr-rFR
Update values-fr-rFR/strings.xml
2018-01-06 03:14:21 +01:00
95e79e7c5d Update values-fr-rFR/strings.xml
Fix typos
2018-01-06 01:49:07 +01:00
3ce3260d20 Fixes #165. 2018-01-05 10:51:19 +01:00
641f4f34d3 Fixes #168. 2018-01-04 20:45:25 +01:00
99620cb1c5 Update README.md 2018-01-04 13:32:21 +01:00
8f5f33f5d2 Crowdin fixing Android Studio indentation issue.
* New translations strings.xml (Chinese Simplified)

* New translations strings.xml (Italian)

* New translations strings.xml (Ukrainian)

* New translations strings.xml (Turkish)

* New translations strings.xml (Swedish)

* New translations strings.xml (Spanish)

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

* New translations strings.xml (Russian)

* New translations strings.xml (Romanian)

* New translations strings.xml (Portuguese, Brazilian)

* New translations strings.xml (Portuguese)

* New translations strings.xml (Polish)

* New translations strings.xml (Norwegian)

* New translations strings.xml (Japanese)

* New translations strings.xml (Indonesian)

* New translations strings.xml (Afrikaans)

* New translations strings.xml (Hungarian)

* New translations strings.xml (Hebrew)

* New translations strings.xml (Greek)

* New translations strings.xml (German)

* New translations strings.xml (French)

* New translations strings.xml (Finnish)

* New translations strings.xml (English, Indonesia)

* New translations strings.xml (Dutch)

* New translations strings.xml (Danish)

* New translations strings.xml (Czech)

* New translations strings.xml (Chinese Traditional)

* New translations strings.xml (Arabic)

* New translations strings.xml (Vietnamese)
2018-01-03 19:19:56 +01:00
78e9230b82 Fixes #161. 2018-01-03 19:07:27 +01:00
78aa44c007 Changed from gitter to slack. 2018-01-01 15:04:52 +01:00
53fd944f00 Update README.md 2018-01-01 15:00:04 +01:00
9e6cb4ee3d Fixes #164. Page indicator position. 2018-01-01 07:55:57 +01:00
87ad6f2826 (Again) fixed auto version number. 2018-01-01 07:27:10 +01:00
9050f5a56f Changelog. 2018-01-01 07:03:11 +01:00
3437004082 Multiple crash fixes. 2018-01-01 07:02:19 +01:00
dcf620af87 New translations strings.xml (Chinese Simplified) (#163) 2017-12-27 05:44:58 +01:00
128085a02e New Crowdin translations (#159)
* New translations strings.xml (Afrikaans)

* New translations strings.xml (Korean)

* New translations strings.xml (English, Indonesia)

* New translations strings.xml (Vietnamese)

* New translations strings.xml (Ukrainian)

* New translations strings.xml (Turkish)

* New translations strings.xml (Swedish)

* New translations strings.xml (Spanish)

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

* New translations strings.xml (Russian)

* New translations strings.xml (Romanian)

* New translations strings.xml (Portuguese, Brazilian)

* New translations strings.xml (Portuguese)

* New translations strings.xml (Polish)

* New translations strings.xml (Norwegian)

* New translations strings.xml (Japanese)

* New translations strings.xml (Arabic)

* New translations strings.xml (Italian)

* New translations strings.xml (Hungarian)

* New translations strings.xml (Hebrew)

* New translations strings.xml (Greek)

* New translations strings.xml (German)

* New translations strings.xml (French)

* New translations strings.xml (Finnish)

* New translations strings.xml (Dutch)

* New translations strings.xml (Danish)

* New translations strings.xml (Czech)

* New translations strings.xml (Chinese Traditional)

* New translations strings.xml (Chinese Simplified)

* New translations strings.xml (Catalan)

* New translations strings.xml (Indonesian)

* New translations strings.xml (French)
2017-12-20 06:39:27 +01:00
302040ec25 Fixed #160. 2017-12-20 06:33:10 +01:00
e177c22032 Fixes #157. 2017-12-17 21:30:42 +01:00
a11007113a Maybe fixing IllegalStateException. 2017-12-17 20:59:16 +01:00
5e7897bcf4 Fixes #152. 2017-12-17 20:40:14 +01:00
9559af3637 Closes #154. 2017-12-17 19:51:20 +01:00
4c499abcdb Issue 155 - fix StringIndexOutOfBoundException 2017-12-17 17:12:54 +01:00
0055a503b3 New Crowdin translations (#156)
* New translations strings.xml (Afrikaans)

* New translations strings.xml (Korean)

* New translations strings.xml (English, Indonesia)

* New translations strings.xml (Vietnamese)

* New translations strings.xml (Ukrainian)

* New translations strings.xml (Turkish)

* New translations strings.xml (Swedish)

* New translations strings.xml (Spanish)

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

* New translations strings.xml (Russian)

* New translations strings.xml (Romanian)

* New translations strings.xml (Portuguese, Brazilian)

* New translations strings.xml (Portuguese)

* New translations strings.xml (Polish)

* New translations strings.xml (Norwegian)

* New translations strings.xml (Japanese)

* New translations strings.xml (Arabic)

* New translations strings.xml (Italian)

* New translations strings.xml (Hungarian)

* New translations strings.xml (Hebrew)

* New translations strings.xml (Greek)

* New translations strings.xml (German)

* New translations strings.xml (French)

* New translations strings.xml (Finnish)

* New translations strings.xml (Dutch)

* New translations strings.xml (Danish)

* New translations strings.xml (Czech)

* New translations strings.xml (Chinese Traditional)

* New translations strings.xml (Chinese Simplified)

* New translations strings.xml (Catalan)

* New translations strings.xml (Indonesian)
2017-12-13 10:48:56 +01:00
113 changed files with 2719 additions and 2134 deletions

View File

@ -8,7 +8,7 @@ Please read the guidelines before contributing, and follow them (or try to) when
### What you can do to help. ### What you can do to help.
There are many ways to contribute to this project, you could report bugs, request missing features, suggest enhancements and changes to existing ones. You also can improve the README with useful tips that could help the other users. There are many ways to contribute to this project, you could [translate the app](https://crowdin.com/project/readerforselfoss), report bugs, request missing features, suggest enhancements and changes to existing ones. You also can improve the README with useful tips that could help the other users.
You can fork the repository, and [help me solve some issues](https://github.com/aminecmi/ReaderforSelfoss/issues?q=is%3Aissue+is%3Aopen+label%3A%22Up+For+Grabs%22) or [develop new things](https://github.com/aminecmi/ReaderforSelfoss/issues) You can fork the repository, and [help me solve some issues](https://github.com/aminecmi/ReaderforSelfoss/issues?q=is%3Aissue+is%3Aopen+label%3A%22Up+For+Grabs%22) or [develop new things](https://github.com/aminecmi/ReaderforSelfoss/issues)
@ -28,6 +28,7 @@ Always check if the web version of your instance is working.
### Pull requests ### Pull requests
* Don't create a PR for translations. See [here](https://github.com/aminecmi/ReaderforSelfoss/pull/170#issuecomment-355715654) for an explanation why.
* Please ask before starting to work on an issue. I may be working on it, or someone else could be doing so. * 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.

View File

@ -5,6 +5,7 @@
- [ ] I have updated the documentation accordingly. - [ ] I have updated the documentation accordingly.
- [ ] I have added tests to cover my changes. - [ ] I have added tests to cover my changes.
- [ ] All new and existing tests passed. - [ ] All new and existing tests passed.
- [ ] This is **NOT** translation related. (See [here](https://github.com/aminecmi/ReaderforSelfoss/pull/170#issuecomment-355715654))
This closes issue #XXX This closes issue #XXX

View File

@ -1,8 +1,32 @@
**1.5.7.x** **1.5.7.x**
- Added confirmation to the mark as read and update menues.
- Add to favorites from article viewer.
- Added an option to use a webview in the article viewer (see #149) - Added an option to use a webview in the article viewer (see #149)
- Fixes (#151) - Fixes (#151 #152 #155 #157 #160 #174) and more.
- New year fixes !!!
- Changed page indicator position as it was overlaping content.
- Now using slack instead of gitter.
- Moved completely to a webview to fix #161.
- Fixed typos in French ( Thanks @aancel )
- Updated the Contribution guide about translations.
- Better handling for articles update. (See #169)
- Ability to change the article viewer content font size (see #153)
- Versions updates * 2.
- Added padding to the recyclerview.
**1.5.5.x (didn't last long) AND 1.5.6.x** **1.5.5.x (didn't last long) AND 1.5.6.x**
@ -20,6 +44,8 @@
- Changed versions handling. - Changed versions handling.
- Removed indonesian english as it was causing issues with the english version of the app.
**1.5.4.22** **1.5.4.22**
- You can now scroll through the loaded articles ! - You can now scroll through the loaded articles !

View File

@ -1,11 +1,13 @@
# ReaderForSelfoss # ReaderForSelfoss
[![Crowdin](https://d322cqt584bo4o.cloudfront.net/readerforselfoss/localized.svg)](https://crowdin.com/project/readerforselfoss) [![Gitter chat](https://badges.gitter.im/amine-bou/ReaderForSelfoss.png)](https://gitter.im/amine-bou/ReaderForSelfoss) [![Slack Channel](https://img.shields.io/badge/chat-slack-green.svg)](https://join.slack.com/t/readerforselfoss/shared_invite/enQtMjkyNzc3NjM2Mjc1LTUzZTZhOGM5YjQ1MTI5MWZiODRjMjE1ZDBmMzQxZmQ3NWZhYTNhMTBjNGEwNmE2ZGFjODU5NjUxZjBkMWJmMDQ)
[![Build Status](http://jenkins.amine-bou.fr/job/ReaderForSelfoss/badge/icon)](http://jenkins.amine-bou.fr/job/ReaderForSelfoss/) [![Build Status](http://jenkins.amine-bou.fr/job/ReaderForSelfoss/badge/icon)](http://jenkins.amine-bou.fr/job/ReaderForSelfoss/)
[![Code Triagers Badge](https://www.codetriage.com/aminecmi/readerforselfoss/badges/users.svg)](https://www.codetriage.com/aminecmi/readerforselfoss) [![Code Triagers Badge](https://www.codetriage.com/aminecmi/readerforselfoss/badges/users.svg)](https://www.codetriage.com/aminecmi/readerforselfoss)
[![Crowdin](https://d322cqt584bo4o.cloudfront.net/readerforselfoss/localized.svg)](https://crowdin.com/project/readerforselfoss)
This is the repo of [Reader For Selfoss](https://play.google.com/store/apps/details?id=apps.amine.bou.readerforselfoss&hl=en). 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/)
@ -23,4 +25,4 @@ Check the [Contribution guide](https://github.com/aminecmi/ReaderforSelfoss/blob
- [See what I'm doing](https://github.com/aminecmi/ReaderforSelfoss/projects/1) - [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) - [Help translation the app](https://crowdin.com/project/readerforselfoss)
- [Ask for help](https://gitter.im/amine-bou/ReaderForSelfoss) - [Ask for help](https://join.slack.com/t/readerforselfoss/shared_invite/enQtMjkyNzc3NjM2Mjc1LTUzZTZhOGM5YjQ1MTI5MWZiODRjMjE1ZDBmMzQxZmQ3NWZhYTNhMTBjNGEwNmE2ZGFjODU5NjUxZjBkMWJmMDQ)

View File

@ -12,6 +12,8 @@ ext {
configuration = [ configuration = [
buildDate: new Date() buildDate: new Date()
] ]
// This will make me able to build multiple times a day. May break thinks. I may forget it.
todaysBuilds = "1"
} }
def gitVersion() { def gitVersion() {
@ -20,19 +22,19 @@ def gitVersion() {
} }
def versionCodeFromGit() { def versionCodeFromGit() {
def versionCode = gitVersion() + (ext.configuration.buildDate.format("yyMMD")).toInteger() def dayInYear = ext.configuration.buildDate.format("D").padLeft(3, '0')
def versionCode = gitVersion() + (ext.configuration.buildDate.format("yyMM") + dayInYear + ext.todaysBuilds).toInteger()
println "version code " + versionCode println "version code " + versionCode
return versionCode.toInteger() return versionCode.toInteger()
} }
def versionNameFromGit() { def versionNameFromGit() {
def versionName = gitVersion() + ext.configuration.buildDate.format('yyyyMMddHHmm') def dayInYear = ext.configuration.buildDate.format("D").padLeft(3, '0')
def versionName = gitVersion() + ext.configuration.buildDate.format('yyMM') + dayInYear + ext.todaysBuilds
println "version name " + versionName println "version name " + versionName
return 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'
@ -49,7 +51,7 @@ repositories {
android { android {
compileSdkVersion 27 compileSdkVersion 27
buildToolsVersion '27.0.2' buildToolsVersion '27.0.3'
defaultConfig { defaultConfig {
applicationId "apps.amine.bou.readerforselfoss" applicationId "apps.amine.bou.readerforselfoss"
minSdkVersion 16 minSdkVersion 16
@ -96,6 +98,7 @@ android {
buildConfigField "boolean", "GITHUB_VERSION", "true" buildConfigField "boolean", "GITHUB_VERSION", "true"
} }
storeConfig { storeConfig {
// As jenkins publishes to alpha first, this is the default suffix now.
versionNameSuffix '-store' versionNameSuffix '-store'
dimension "build" dimension "build"
buildConfigField "boolean", "GITHUB_VERSION", "false" buildConfigField "boolean", "GITHUB_VERSION", "false"
@ -105,79 +108,81 @@ android {
dependencies { dependencies {
// Testing // Testing
androidTestCompile 'com.android.support.test.espresso:espresso-core:3.0.1' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
androidTestCompile 'com.android.support.test:runner:1.0.1' androidTestImplementation '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.1' androidTestImplementation '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.1' androidTestImplementation 'com.android.support.test.espresso:espresso-intents:3.0.1'
compile fileTree(dir: 'libs', include: ['*.jar']) implementation fileTree(dir: 'libs', include: ['*.jar'])
compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
// Android Support // Android Support
compile 'com.android.support:appcompat-v7:27.0.2' implementation 'com.android.support:appcompat-v7:27.1.1'
compile 'com.android.support:design:27.0.2' implementation 'com.android.support:design:27.1.1'
compile 'com.android.support:recyclerview-v7:27.0.2' implementation 'com.android.support:recyclerview-v7:27.1.1'
compile 'com.android.support:support-v4:27.0.2' implementation 'com.android.support:support-v4:27.1.1'
compile 'com.android.support:support-vector-drawable:27.0.2' implementation 'com.android.support:support-vector-drawable:27.1.1'
compile 'com.android.support:customtabs:27.0.2' implementation 'com.android.support:customtabs:27.1.1'
compile 'com.android.support:cardview-v7:27.0.2' implementation 'com.android.support:cardview-v7:27.1.1'
compile 'com.android.support.constraint:constraint-layout:1.0.2' implementation 'com.android.support.constraint:constraint-layout:1.0.2'
// Firebase + crashlytics // Firebase + crashlytics
compile 'com.google.firebase:firebase-core:11.6.2' implementation 'com.google.firebase:firebase-core:12.0.1'
compile 'com.google.firebase:firebase-config:11.6.2' implementation 'com.google.firebase:firebase-config:12.0.1'
compile 'com.google.firebase:firebase-invites:11.6.2' implementation 'com.google.firebase:firebase-invites:12.0.1'
compile('com.crashlytics.sdk.android:crashlytics:2.8.0@aar') { implementation('com.crashlytics.sdk.android:crashlytics:2.9.1@aar') {
transitive = true; transitive = true
} }
//multidex //multidex
compile 'com.android.support:multidex:1.0.2' implementation 'com.android.support:multidex:1.0.3'
// Intro // Intro
compile 'agency.tango.android:material-intro-screen:0.0.5' implementation 'agency.tango.android:material-intro-screen:0.0.5'
// About // About
compile('com.mikepenz:aboutlibraries:6.0.0@aar') { implementation('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' implementation 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'com.squareup.okhttp3:logging-interceptor:3.9.0' implementation 'com.squareup.okhttp3:logging-interceptor:3.9.0'
compile 'com.squareup.retrofit2:converter-gson:2.3.0' implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
compile 'com.burgstaller:okhttp-digest:1.12' implementation 'com.burgstaller:okhttp-digest:1.12'
// Material-ish things // Material-ish things
compile 'com.ashokvarma.android:bottom-navigation-bar:2.0.3' implementation 'com.ashokvarma.android:bottom-navigation-bar:2.0.3'
compile 'com.github.jd-alexander:LikeButton:0.2.1' implementation 'com.github.jd-alexander:LikeButton:0.2.1'
compile 'com.amulyakhare:com.amulyakhare.textdrawable:1.0.1' implementation 'com.amulyakhare:com.amulyakhare.textdrawable:1.0.1'
compile 'org.sufficientlysecure:html-textview:3.5'
// glide // glide
compile 'com.github.bumptech.glide:glide:4.1.1' implementation 'com.github.bumptech.glide:glide:4.1.1'
compile 'com.github.bumptech.glide:okhttp3-integration:4.1.1' implementation 'com.github.bumptech.glide:okhttp3-integration:4.1.1'
// Asking politely users to rate the app // Asking politely users to rate the app
compile 'com.github.stkent:amplify:2.1.0' implementation 'com.github.stkent:amplify:2.1.0'
// Drawer // Drawer
implementation 'co.zsmb:materialdrawer-kt:1.2.1' implementation 'co.zsmb:materialdrawer-kt:1.2.1'
compile 'com.anupcowkur:reservoir:3.1.0' implementation 'com.anupcowkur:reservoir:3.1.0'
// Themes // Themes
compile 'com.52inc:scoops:1.0.0' implementation 'com.52inc:scoops:1.0.0'
implementation'com.jrummyapps:colorpicker:2.1.7'
// Github issues reporter // Github issues reporter
compile 'com.heinrichreimersoftware:android-issue-reporter:1.3.1' implementation 'com.heinrichreimersoftware:android-issue-reporter:1.3.1'
compile 'com.github.rubensousa:floatingtoolbar:1.5.1' implementation 'com.github.rubensousa:floatingtoolbar:1.5.1'
// Pager // Pager
compile 'me.relex:circleindicator:1.2.2@aar' implementation 'me.relex:circleindicator:1.2.2@aar'
implementation 'androidx.core:core-ktx:0.3'
} }

View File

@ -48,7 +48,11 @@
#} #}
-dontwarn okio.** -dontwarn okio.**
-dontwarn retrofit2.Platform$Java8 -dontwarn retrofit2.Platform$Java8
-keepattributes Signature -keep class retrofit.** { *; }
-keepclasseswithmembers class * {
@retrofit.http.* <methods>;
}
-keepattributes *Annotation*,Signature
-keepattributes Exceptions -keepattributes Exceptions
-dontwarn okio.** -dontwarn okio.**
-dontwarn javax.annotation.Nullable -dontwarn javax.annotation.Nullable

View File

@ -1,9 +1,15 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="apps.amine.bou.readerforselfoss"> package="apps.amine.bou.readerforselfoss"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<!-- Remove unwanted permissions from Crashlytics.. see https://www.reddit.com/r/androiddev/comments/86c02l/google_play_services_1200_released/dw4ehln/?context=0 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" tools:node="remove" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" tools:node="remove" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" tools:node="remove" />
<!-- For firebase only --> <!-- For firebase only -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.WAKE_LOCK" />
@ -77,6 +83,8 @@
<meta-data android:name="android.webkit.WebView.EnableSafeBrowsing" <meta-data android:name="android.webkit.WebView.EnableSafeBrowsing"
android:value="true" /> android:value="true" />
<meta-data android:name="android.max_aspect" android:value="2.1" />
</application> </application>
</manifest> </manifest>

View File

@ -1,6 +1,7 @@
package apps.amine.bou.readerforselfoss package apps.amine.bou.readerforselfoss
import android.content.Intent import android.content.Intent
import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.preference.PreferenceManager import android.preference.PreferenceManager
import android.support.constraint.ConstraintLayout import android.support.constraint.ConstraintLayout
@ -16,6 +17,8 @@ import android.widget.Toast
import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi import apps.amine.bou.readerforselfoss.api.selfoss.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.themes.AppColors
import apps.amine.bou.readerforselfoss.themes.Toppings
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
@ -23,22 +26,62 @@ import kotlinx.android.synthetic.main.activity_add_source.*
import retrofit2.Call import retrofit2.Call
import retrofit2.Callback import retrofit2.Callback
import retrofit2.Response import retrofit2.Response
import android.graphics.PorterDuff
class AddSourceActivity : AppCompatActivity() { class AddSourceActivity : AppCompatActivity() {
private var mSpoutsValue: String? = null private var mSpoutsValue: String? = null
private lateinit var api: SelfossApi
private lateinit var appColors: AppColors
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
appColors = AppColors(this@AddSourceActivity)
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
Scoop.getInstance().apply(this)
setContentView(R.layout.activity_add_source) setContentView(R.layout.activity_add_source)
// TODO: input bubble cursor
Scoop.getInstance()
.bind(this, Toppings.PRIMARY.value, toolbar)
.bindStatusBar(this, Toppings.PRIMARY_DARK.value)
val drawable = nameInput.background
drawable.setColorFilter(appColors.colorAccent, PorterDuff.Mode.SRC_ATOP)
// TODO: clean
if(Build.VERSION.SDK_INT > 16) {
nameInput.background = drawable
} else{
nameInput.setBackgroundDrawable(drawable)
}
val drawable1 = sourceUri.background
drawable1.setColorFilter(appColors.colorAccent, PorterDuff.Mode.SRC_ATOP)
if(Build.VERSION.SDK_INT > 16) {
sourceUri.background = drawable1
} else{
sourceUri.setBackgroundDrawable(drawable1)
}
val drawable2 = tags.background
drawable2.setColorFilter(appColors.colorAccent, PorterDuff.Mode.SRC_ATOP)
if(Build.VERSION.SDK_INT > 16) {
tags.background = drawable2
} else{
tags.setBackgroundDrawable(drawable2)
}
setSupportActionBar(toolbar) setSupportActionBar(toolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true) supportActionBar?.setDisplayHomeAsUpEnabled(true)
supportActionBar?.setDisplayShowHomeEnabled(true) supportActionBar?.setDisplayShowHomeEnabled(true)
var api: SelfossApi? = null
try { try {
val prefs = PreferenceManager.getDefaultSharedPreferences(this) val prefs = PreferenceManager.getDefaultSharedPreferences(this)
api = SelfossApi( api = SelfossApi(
@ -53,10 +96,15 @@ class AddSourceActivity : AppCompatActivity() {
maybeGetDetailsFromIntentSharing(intent, sourceUri, nameInput) maybeGetDetailsFromIntentSharing(intent, sourceUri, nameInput)
saveBtn.setTextColor(appColors.colorAccent)
saveBtn.setOnClickListener { saveBtn.setOnClickListener {
handleSaveSource(tags, nameInput.text.toString(), sourceUri.text.toString(), api!!) handleSaveSource(tags, nameInput.text.toString(), sourceUri.text.toString(), api!!)
} }
}
override fun onResume() {
super.onResume()
val config = Config(this) val config = Config(this)
if (config.baseUrl.isEmpty() || !config.baseUrl.isBaseUrlValid()) { if (config.baseUrl.isEmpty() || !config.baseUrl.isBaseUrlValid()) {
@ -74,10 +122,12 @@ class AddSourceActivity : AppCompatActivity() {
) { ) {
val spoutsKV = HashMap<String, String>() val spoutsKV = HashMap<String, String>()
spoutsSpinner.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) {
if (view != null) {
val spoutName = (view as TextView).text.toString() val spoutName = (view as TextView).text.toString()
mSpoutsValue = spoutsKV[spoutName] mSpoutsValue = spoutsKV[spoutName]
} }
}
override fun onNothingSelected(adapterView: AdapterView<*>) { override fun onNothingSelected(adapterView: AdapterView<*>) {
mSpoutsValue = null mSpoutsValue = null
@ -95,7 +145,7 @@ class AddSourceActivity : AppCompatActivity() {
val itemsStrings = items.map { it.value.name } val itemsStrings = items.map { it.value.name }
for ((key, value) in items) { for ((key, value) in items) {
spoutsKV.put(value.name, key) spoutsKV[value.name] = key
} }
mProgress.visibility = View.GONE mProgress.visibility = View.GONE
@ -149,7 +199,8 @@ class AddSourceActivity : AppCompatActivity() {
private fun handleSaveSource(tags: EditText, title: String, url: String, api: SelfossApi) { private fun handleSaveSource(tags: EditText, title: String, url: String, api: SelfossApi) {
val sourceDetailsAvailable = title.isEmpty() || url.isEmpty() || mSpoutsValue == null || mSpoutsValue!!.isEmpty() val sourceDetailsAvailable =
title.isEmpty() || url.isEmpty() || mSpoutsValue == null || mSpoutsValue!!.isEmpty()
if (sourceDetailsAvailable) { 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()

View File

@ -10,6 +10,7 @@ import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.preference.PreferenceManager import android.preference.PreferenceManager
import android.support.v4.view.MenuItemCompat import android.support.v4.view.MenuItemCompat
import android.support.v7.app.AlertDialog
import android.support.v7.app.AppCompatActivity import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.DividerItemDecoration import android.support.v7.widget.DividerItemDecoration
import android.support.v7.widget.GridLayoutManager import android.support.v7.widget.GridLayoutManager
@ -17,13 +18,13 @@ import android.support.v7.widget.RecyclerView
import android.support.v7.widget.SearchView import android.support.v7.widget.SearchView
import android.support.v7.widget.StaggeredGridLayoutManager import android.support.v7.widget.StaggeredGridLayoutManager
import android.support.v7.widget.helper.ItemTouchHelper import android.support.v7.widget.helper.ItemTouchHelper
import android.util.Log
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.widget.Toast import android.widget.Toast
import apps.amine.bou.readerforselfoss.adapters.ItemCardAdapter import apps.amine.bou.readerforselfoss.adapters.ItemCardAdapter
import apps.amine.bou.readerforselfoss.adapters.ItemListAdapter import apps.amine.bou.readerforselfoss.adapters.ItemListAdapter
import apps.amine.bou.readerforselfoss.adapters.ItemsAdapter
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.Sources import apps.amine.bou.readerforselfoss.api.selfoss.Sources
@ -32,12 +33,14 @@ import apps.amine.bou.readerforselfoss.api.selfoss.SuccessResponse
import apps.amine.bou.readerforselfoss.api.selfoss.Tag import apps.amine.bou.readerforselfoss.api.selfoss.Tag
import apps.amine.bou.readerforselfoss.settings.SettingsActivity import apps.amine.bou.readerforselfoss.settings.SettingsActivity
import apps.amine.bou.readerforselfoss.themes.AppColors import apps.amine.bou.readerforselfoss.themes.AppColors
import apps.amine.bou.readerforselfoss.themes.Toppings
import apps.amine.bou.readerforselfoss.utils.Config import apps.amine.bou.readerforselfoss.utils.Config
import apps.amine.bou.readerforselfoss.utils.bottombar.maybeShow import apps.amine.bou.readerforselfoss.utils.bottombar.maybeShow
import apps.amine.bou.readerforselfoss.utils.bottombar.removeBadge import apps.amine.bou.readerforselfoss.utils.bottombar.removeBadge
import apps.amine.bou.readerforselfoss.utils.checkApkVersion import apps.amine.bou.readerforselfoss.utils.checkApkVersion
import apps.amine.bou.readerforselfoss.utils.customtabs.CustomTabActivityHelper import apps.amine.bou.readerforselfoss.utils.customtabs.CustomTabActivityHelper
import apps.amine.bou.readerforselfoss.utils.drawer.CustomUrlPrimaryDrawerItem import apps.amine.bou.readerforselfoss.utils.drawer.CustomUrlPrimaryDrawerItem
import apps.amine.bou.readerforselfoss.utils.flattenTags
import apps.amine.bou.readerforselfoss.utils.longHash import apps.amine.bou.readerforselfoss.utils.longHash
import co.zsmb.materialdrawerkt.builders.accountHeader import co.zsmb.materialdrawerkt.builders.accountHeader
import co.zsmb.materialdrawerkt.builders.drawer import co.zsmb.materialdrawerkt.builders.drawer
@ -65,6 +68,7 @@ import com.mikepenz.aboutlibraries.Libs
import com.mikepenz.aboutlibraries.LibsBuilder import com.mikepenz.aboutlibraries.LibsBuilder
import com.mikepenz.materialdrawer.Drawer import com.mikepenz.materialdrawer.Drawer
import com.mikepenz.materialdrawer.holder.BadgeStyle import com.mikepenz.materialdrawer.holder.BadgeStyle
import com.mikepenz.materialdrawer.holder.StringHolder
import com.mikepenz.materialdrawer.model.DividerDrawerItem import com.mikepenz.materialdrawer.model.DividerDrawerItem
import com.mikepenz.materialdrawer.model.PrimaryDrawerItem import com.mikepenz.materialdrawer.model.PrimaryDrawerItem
import com.mikepenz.materialdrawer.model.SecondaryDrawerItem import com.mikepenz.materialdrawer.model.SecondaryDrawerItem
@ -86,8 +90,11 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
private val FAV_SHOWN = 3 private val FAV_SHOWN = 3
private var items: ArrayList<Item> = ArrayList() private var items: ArrayList<Item> = ArrayList()
private var allItems: ArrayList<Item> = ArrayList()
private var clickBehavior = false private var clickBehavior = false
private var debugReadingItems = false private var debugReadingItems = false
private var shouldLogEverything = false
private var internalBrowser = false private var internalBrowser = false
private var articleViewer = false private var articleViewer = false
private var shouldBeCardView = false private var shouldBeCardView = false
@ -104,6 +111,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
private var infiniteScroll: Boolean = false private var infiniteScroll: Boolean = false
private var lastFetchDone: Boolean = false private var lastFetchDone: Boolean = false
private lateinit var tabNewBadge: TextBadgeItem private lateinit var tabNewBadge: TextBadgeItem
private lateinit var tabArchiveBadge: TextBadgeItem private lateinit var tabArchiveBadge: TextBadgeItem
private lateinit var tabStarredBadge: TextBadgeItem private lateinit var tabStarredBadge: TextBadgeItem
@ -119,10 +127,15 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
private var recyclerViewScrollListener: RecyclerView.OnScrollListener? = null private var recyclerViewScrollListener: RecyclerView.OnScrollListener? = null
private lateinit var settings: SharedPreferences private lateinit var settings: SharedPreferences
private var recyclerAdapter: RecyclerView.Adapter<*>? = null
private var badgeNew: Int = -1 private var badgeNew: Int = -1
private var badgeAll: Int = -1 private var badgeAll: Int = -1
private var badgeFavs: Int = -1 private var badgeFavs: Int = -1
private lateinit var tagsBadge: Map<Long, Int>
data class DrawerData(val tags: List<Tag>?, val sources: List<Sources>?) data class DrawerData(val tags: List<Tag>?, val sources: List<Sources>?)
override fun onStart() { override fun onStart() {
@ -131,10 +144,14 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
} }
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
appColors = AppColors(this@HomeActivity)
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
Scoop.getInstance().apply(this)
setContentView(R.layout.activity_home) setContentView(R.layout.activity_home)
handleThemeBinding()
setSupportActionBar(toolBar) setSupportActionBar(toolBar)
if (savedInstanceState == null) { if (savedInstanceState == null) {
Amplify.getSharedInstance().promptIfReady(promptView) Amplify.getSharedInstance().promptIfReady(promptView)
@ -145,23 +162,21 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
customTabActivityHelper = CustomTabActivityHelper() customTabActivityHelper = CustomTabActivityHelper()
settings = getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE)
sharedPref = PreferenceManager.getDefaultSharedPreferences(this) sharedPref = PreferenceManager.getDefaultSharedPreferences(this)
settings = getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE)
api = SelfossApi( api = SelfossApi(
this, this,
this@HomeActivity, this@HomeActivity,
settings.getBoolean("isSelfSignedCert", false), settings.getBoolean("isSelfSignedCert", false),
sharedPref.getBoolean("should_log_everything", false) shouldLogEverything
) )
items = ArrayList() items = ArrayList()
allItems = ArrayList()
appColors = AppColors(this@HomeActivity)
handleBottomBar() handleBottomBar()
handleDrawer() handleDrawer()
reloadLayoutManager()
handleSwipeRefreshLayout() handleSwipeRefreshLayout()
} }
@ -201,11 +216,12 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
): Boolean = false ): Boolean = false
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, swipeDir: Int) { override fun onSwiped(viewHolder: RecyclerView.ViewHolder, swipeDir: Int) {
try { val position = viewHolder.adapterPosition
val i = items[viewHolder.adapterPosition] val i = items.elementAtOrNull(position)
val position = items.indexOf(i)
if (i != null) {
val adapter = recyclerView.adapter val adapter = recyclerView.adapter
when (adapter) { when (adapter) {
is ItemCardAdapter -> adapter.removeItemAtIndex(position) is ItemCardAdapter -> adapter.removeItemAtIndex(position)
is ItemListAdapter -> adapter.removeItemAtIndex(position) is ItemListAdapter -> adapter.removeItemAtIndex(position)
@ -214,6 +230,16 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
if (items.size > 0) { if (items.size > 0) {
badgeNew-- badgeNew--
reloadBadgeContent() reloadBadgeContent()
val tagHashes = i.tags.split(",").map { it.longHash() }
tagsBadge = tagsBadge.map {
if (tagHashes.contains(it.key)) {
(it.key to (it.value - 1))
} else {
(it.key to it.value)
}
}.toMap()
reloadTagsBadges()
} else { } else {
tabNewBadge.hide() tabNewBadge.hide()
} }
@ -239,14 +265,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
offsetOverride = lastVisibleItem offsetOverride = lastVisibleItem
) )
} }
} catch (e: IndexOutOfBoundsException) {
Crashlytics.setUserIdentifier(userIdentifier)
Crashlytics.log(
100,
"SWIPE_INDEX_OUT_OF_BOUND",
"IndexOutOfBoundsException when swiping"
)
Crashlytics.logException(e)
} }
} }
} }
@ -259,27 +277,27 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
tabNewBadge = TextBadgeItem() tabNewBadge = TextBadgeItem()
.setText("") .setText("")
.setHideOnSelect(false).hide(false) .setHideOnSelect(false).hide(false)
.setBackgroundColor(appColors.primary) .setBackgroundColor(appColors.colorPrimary)
tabArchiveBadge = TextBadgeItem() tabArchiveBadge = TextBadgeItem()
.setText("") .setText("")
.setHideOnSelect(false).hide(false) .setHideOnSelect(false).hide(false)
.setBackgroundColor(appColors.primary) .setBackgroundColor(appColors.colorPrimary)
tabStarredBadge = TextBadgeItem() tabStarredBadge = TextBadgeItem()
.setText("") .setText("")
.setHideOnSelect(false).hide(false) .setHideOnSelect(false).hide(false)
.setBackgroundColor(appColors.primary) .setBackgroundColor(appColors.colorPrimary)
val tabNew = val tabNew =
BottomNavigationItem( BottomNavigationItem(
R.drawable.ic_fiber_new_black_24dp, R.drawable.ic_fiber_new_black_24dp,
getString(R.string.tab_new) getString(R.string.tab_new)
).setActiveColor(appColors.accent) ).setActiveColor(appColors.colorAccent)
.setBadgeItem(tabNewBadge) .setBadgeItem(tabNewBadge)
val tabArchive = val tabArchive =
BottomNavigationItem( BottomNavigationItem(
R.drawable.ic_archive_black_24dp, R.drawable.ic_archive_black_24dp,
getString(R.string.tab_read) getString(R.string.tab_read)
).setActiveColor(appColors.dark) ).setActiveColor(appColors.colorAccentDark)
.setBadgeItem(tabArchiveBadge) .setBadgeItem(tabArchiveBadge)
val tabStarred = val tabStarred =
BottomNavigationItem( BottomNavigationItem(
@ -302,6 +320,9 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
// TODO: Make this the only appcolors init
appColors = AppColors(this@HomeActivity)
handleDrawerItems() handleDrawerItems()
sharedPref = PreferenceManager.getDefaultSharedPreferences(this) sharedPref = PreferenceManager.getDefaultSharedPreferences(this)
@ -314,6 +335,18 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
handleSharedPrefs() handleSharedPrefs()
handleThemeUpdate()
reloadLayoutManager()
if (!infiniteScroll) {
recyclerView.setHasFixedSize(true)
} else {
handleInfiniteScroll()
}
handleBottomBarActions()
getElementsAccordingToTab() getElementsAccordingToTab()
} }
@ -324,6 +357,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
private fun handleSharedPrefs() { private fun handleSharedPrefs() {
debugReadingItems = sharedPref.getBoolean("read_debug", false) debugReadingItems = sharedPref.getBoolean("read_debug", false)
shouldLogEverything = sharedPref.getBoolean("should_log_everything", false)
clickBehavior = sharedPref.getBoolean("tab_on_tap", false) clickBehavior = sharedPref.getBoolean("tab_on_tap", false)
internalBrowser = sharedPref.getBoolean("prefer_internal_browser", true) internalBrowser = sharedPref.getBoolean("prefer_internal_browser", true)
articleViewer = sharedPref.getBoolean("prefer_article_viewer", true) articleViewer = sharedPref.getBoolean("prefer_article_viewer", true)
@ -337,6 +371,19 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
infiniteScroll = sharedPref.getBoolean("infinite_loading", false) infiniteScroll = sharedPref.getBoolean("infinite_loading", false)
} }
private fun handleThemeBinding() {
Scoop.getInstance()
.bind(this, Toppings.PRIMARY.value, toolBar)
.bindStatusBar(this, Toppings.PRIMARY_DARK.value)
}
private fun handleThemeUpdate() {
Scoop.getInstance()
.update(Toppings.PRIMARY.value, appColors.colorPrimary)
.update(Toppings.PRIMARY_DARK.value, appColors.colorPrimaryDark)
}
private fun handleDrawer() { private fun handleDrawer() {
displayAccountHeader = displayAccountHeader =
PreferenceManager.getDefaultSharedPreferences(this) PreferenceManager.getDefaultSharedPreferences(this)
@ -408,6 +455,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
} }
private fun handleDrawerItems() { private fun handleDrawerItems() {
tagsBadge = emptyMap()
fun handleDrawerData(maybeDrawerData: DrawerData?, loadedFromCache: Boolean = false) { fun handleDrawerData(maybeDrawerData: DrawerData?, loadedFromCache: Boolean = false) {
fun handleTags(maybeTags: List<Tag>?) { fun handleTags(maybeTags: List<Tag>?) {
if (maybeTags == null) { if (maybeTags == null) {
@ -419,29 +467,38 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
) )
} }
} else { } else {
for (tag in maybeTags) { tagsBadge = maybeTags.map {
val gd = GradientDrawable() val gd = GradientDrawable()
gd.setColor(Color.parseColor(tag.color)) val color = try {
Color.parseColor(it.color)
} catch (e: IllegalArgumentException) {
appColors.colorPrimary
}
gd.setColor(color)
gd.shape = GradientDrawable.RECTANGLE gd.shape = GradientDrawable.RECTANGLE
gd.setSize(30, 30) gd.setSize(30, 30)
gd.cornerRadius = 30F gd.cornerRadius = 30F
drawer.addItem( drawer.addItem(
PrimaryDrawerItem() PrimaryDrawerItem()
.withName(tag.tag) .withName(it.tag)
.withIdentifier(tag.tag.longHash()) .withIdentifier(it.tag.longHash())
.withIcon(gd) .withIcon(gd)
.withBadge("${tag.unread}") .withBadge("${it.unread}")
.withBadgeStyle( .withBadgeStyle(
BadgeStyle().withTextColor(Color.WHITE) BadgeStyle().withTextColor(Color.WHITE)
.withColor(appColors.accent) .withColor(appColors.colorAccent)
) )
.withOnDrawerItemClickListener { _, _, _ -> .withOnDrawerItemClickListener { _, _, _ ->
maybeTagFilter = tag allItems = ArrayList()
maybeTagFilter = it
getElementsAccordingToTab() getElementsAccordingToTab()
false false
} }
) )
}
(it.tag.longHash() to it.unread)
}.toMap()
} }
} }
@ -462,6 +519,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
.withIdentifier(tag.id.toLong()) .withIdentifier(tag.id.toLong())
.withIcon(tag.getIcon(this@HomeActivity)) .withIcon(tag.getIcon(this@HomeActivity))
.withOnDrawerItemClickListener { _, _, _ -> .withOnDrawerItemClickListener { _, _, _ ->
allItems = ArrayList()
maybeSourceFilter = tag maybeSourceFilter = tag
getElementsAccordingToTab() getElementsAccordingToTab()
false false
@ -480,6 +538,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
.withIdentifier(DRAWER_ID_FILTERS) .withIdentifier(DRAWER_ID_FILTERS)
.withBadge(getString(R.string.drawer_action_clear)) .withBadge(getString(R.string.drawer_action_clear))
.withOnDrawerItemClickListener { _, _, _ -> .withOnDrawerItemClickListener { _, _, _ ->
allItems = ArrayList()
maybeSourceFilter = null maybeSourceFilter = null
maybeTagFilter = null maybeTagFilter = null
getElementsAccordingToTab() getElementsAccordingToTab()
@ -602,7 +661,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
) )
) )
val resultType = object : TypeToken<DrawerData>() {}.type //NOSONAR val resultType = object : TypeToken<DrawerData>() {}.type
Reservoir.getAsync( Reservoir.getAsync(
"drawerData", resultType, object : ReservoirGetCallback<DrawerData> { "drawerData", resultType, object : ReservoirGetCallback<DrawerData> {
override fun onSuccess(maybeDrawerData: DrawerData?) { override fun onSuccess(maybeDrawerData: DrawerData?) {
@ -617,48 +676,68 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
} }
private fun reloadLayoutManager() { private fun reloadLayoutManager() {
val mLayoutManager: RecyclerView.LayoutManager val currentManager = recyclerView.layoutManager
val layoutManager: RecyclerView.LayoutManager
// This will only update the layout manager if settings changed
when (currentManager) {
is StaggeredGridLayoutManager ->
if (!shouldBeCardView) {
layoutManager = GridLayoutManager(this, calculateNoOfColumns())
recyclerView.layoutManager = layoutManager
}
is GridLayoutManager ->
if (shouldBeCardView) { if (shouldBeCardView) {
mLayoutManager = StaggeredGridLayoutManager( layoutManager = StaggeredGridLayoutManager(
calculateNoOfColumns(), calculateNoOfColumns(),
StaggeredGridLayoutManager.VERTICAL StaggeredGridLayoutManager.VERTICAL
) )
mLayoutManager.gapStrategy = StaggeredGridLayoutManager.GAP_HANDLING_MOVE_ITEMS_BETWEEN_SPANS layoutManager.gapStrategy =
StaggeredGridLayoutManager.GAP_HANDLING_MOVE_ITEMS_BETWEEN_SPANS
recyclerView.layoutManager = layoutManager
}
else ->
if (currentManager == null) {
if (!shouldBeCardView) {
layoutManager = GridLayoutManager(this, calculateNoOfColumns())
recyclerView.layoutManager = layoutManager
} else { } else {
mLayoutManager = GridLayoutManager(this, calculateNoOfColumns()) layoutManager = StaggeredGridLayoutManager(
calculateNoOfColumns(),
StaggeredGridLayoutManager.VERTICAL
)
layoutManager.gapStrategy =
StaggeredGridLayoutManager.GAP_HANDLING_MOVE_ITEMS_BETWEEN_SPANS
recyclerView.layoutManager = layoutManager
} }
recyclerView.layoutManager = mLayoutManager
if (!infiniteScroll) {
recyclerView.setHasFixedSize(true)
} else { } else {
handleInfiniteScroll() }
}
} }
handleBottomBarActions(mLayoutManager) private fun handleBottomBarActions() {
}
private fun handleBottomBarActions(mLayoutManager: RecyclerView.LayoutManager) {
bottomBar.setTabSelectedListener(object : BottomNavigationBar.OnTabSelectedListener { bottomBar.setTabSelectedListener(object : BottomNavigationBar.OnTabSelectedListener {
override fun onTabUnselected(position: Int) = Unit override fun onTabUnselected(position: Int) = Unit
override fun onTabReselected(position: Int) = override fun onTabReselected(position: Int) {
when (mLayoutManager) { val layoutManager = recyclerView.adapter
when (layoutManager) {
is StaggeredGridLayoutManager -> is StaggeredGridLayoutManager ->
if (mLayoutManager.findFirstCompletelyVisibleItemPositions(null)[0] == 0) { if (layoutManager.findFirstCompletelyVisibleItemPositions(null)[0] == 0) {
getElementsAccordingToTab() getElementsAccordingToTab()
} else { } else {
mLayoutManager.scrollToPositionWithOffset(0, 0) layoutManager.scrollToPositionWithOffset(0, 0)
} }
is GridLayoutManager -> is GridLayoutManager ->
if (mLayoutManager.findFirstCompletelyVisibleItemPosition() == 0) { if (layoutManager.findFirstCompletelyVisibleItemPosition() == 0) {
getElementsAccordingToTab() getElementsAccordingToTab()
} else { } else {
mLayoutManager.scrollToPositionWithOffset(0, 0) layoutManager.scrollToPositionWithOffset(0, 0)
} }
else -> Unit else -> Unit
} }
}
override fun onTabSelected(position: Int) { override fun onTabSelected(position: Int) {
offset = 0 offset = 0
@ -733,25 +812,26 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
call: (String?, Long?, String?) -> Call<List<Item>> call: (String?, Long?, String?) -> Call<List<Item>>
) { ) {
fun handleItemsResponse(response: Response<List<Item>>) { fun handleItemsResponse(response: Response<List<Item>>) {
val didUpdate = (response.body() != items) val shouldUpdate = (response.body() != items)
if (response.body() != null) { if (response.body() != null) {
if (response.body() != items) { if (shouldUpdate) {
if (appendResults) {
items.addAll(response.body() as ArrayList<Item>)
} else {
items = response.body() as ArrayList<Item> items = response.body() as ArrayList<Item>
items.forEach {
if (!allItems.contains(it)) allItems.add(it)
} }
} }
} else { } else {
if (!appendResults) { if (!appendResults) {
items = ArrayList() items = ArrayList()
allItems = ArrayList()
} }
} }
if (didUpdate) { if (shouldUpdate) {
handleListResult(appendResults) handleListResult(appendResults)
} }
mayBeEmpty() if (!appendResults) mayBeEmpty()
swipeRefreshLayout.isRefreshing = false swipeRefreshLayout.isRefreshing = false
} }
@ -830,11 +910,9 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
} }
} }
reloadLayoutManager() if (recyclerAdapter == null) {
val mAdapter: RecyclerView.Adapter<*>
if (shouldBeCardView) { if (shouldBeCardView) {
mAdapter = recyclerAdapter =
ItemCardAdapter( ItemCardAdapter(
this, this,
items, items,
@ -848,7 +926,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
userIdentifier userIdentifier
) )
} else { } else {
mAdapter = recyclerAdapter =
ItemListAdapter( ItemListAdapter(
this, this,
items, items,
@ -858,7 +936,8 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
internalBrowser, internalBrowser,
articleViewer, articleViewer,
debugReadingItems, debugReadingItems,
userIdentifier userIdentifier,
appColors
) )
recyclerView.addItemDecoration( recyclerView.addItemDecoration(
@ -868,11 +947,13 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
) )
) )
} }
recyclerView.adapter = mAdapter recyclerView.adapter = recyclerAdapter
mAdapter.notifyDataSetChanged() } else {
if (!appendResults) {
if (appendResults) { (recyclerAdapter as ItemsAdapter<*>).updateAllItems(items)
recyclerView.scrollToPosition(firstVisible!!) } else {
(recyclerAdapter as ItemsAdapter<*>).addItemsAtEnd(items)
}
} }
reloadBadges() reloadBadges()
@ -924,6 +1005,13 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
} }
} }
private fun reloadTagsBadges() {
tagsBadge.forEach {
drawer.updateBadge(it.key, StringHolder("${it.value}"))
}
drawer.resetDrawerContent()
}
private fun calculateNoOfColumns(): Int { private fun calculateNoOfColumns(): Int {
val displayMetrics = resources.displayMetrics val displayMetrics = resources.displayMetrics
val dpWidth = displayMetrics.widthPixels / displayMetrics.density val dpWidth = displayMetrics.widthPixels / displayMetrics.density
@ -972,9 +1060,20 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
return true return true
} }
private fun needsConfirmation(titleRes: Int, messageRes: Int, doFn: () -> Unit) {
AlertDialog.Builder(this@HomeActivity)
.setMessage(messageRes)
.setTitle(titleRes)
.setPositiveButton(android.R.string.ok) { _, _ -> doFn() }
.setNegativeButton(android.R.string.cancel) { _, _ -> }
.create()
.show()
}
override fun onOptionsItemSelected(item: MenuItem): Boolean { override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) { when (item.itemId) {
R.id.refresh -> { R.id.refresh -> {
needsConfirmation(R.string.menu_home_refresh, R.string.refresh_dialog_message, {
api.update().enqueue(object : Callback<String> { api.update().enqueue(object : Callback<String> {
override fun onResponse( override fun onResponse(
call: Call<String>, call: Call<String>,
@ -996,13 +1095,27 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
} }
}) })
Toast.makeText(this, R.string.refresh_in_progress, Toast.LENGTH_SHORT).show() Toast.makeText(this, R.string.refresh_in_progress, Toast.LENGTH_SHORT).show()
})
return true return true
} }
R.id.readAll -> { R.id.readAll -> {
if (elementsShown == UNREAD_SHOWN) { if (elementsShown == UNREAD_SHOWN) {
needsConfirmation(R.string.readAll, R.string.markall_dialog_message, {
swipeRefreshLayout.isRefreshing = false swipeRefreshLayout.isRefreshing = false
val ids = items.map { it.id } val ids = allItems.map { it.id }
val itemsByTag: Map<Long, Int> =
allItems.flattenTags()
.groupBy { it.tags.longHash() }
.map { it.key to it.value.size }
.toMap()
fun readAllDebug(e: Throwable) {
Crashlytics.setUserIdentifier(userIdentifier)
Crashlytics.log(100, "READ_ALL_ERROR", e.message)
Crashlytics.logException(e)
}
if (ids.isNotEmpty()) {
api.readAll(ids).enqueue(object : Callback<SuccessResponse> { api.readAll(ids).enqueue(object : Callback<SuccessResponse> {
override fun onResponse( override fun onResponse(
call: Call<SuccessResponse>, call: Call<SuccessResponse>,
@ -1015,12 +1128,31 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
Toast.LENGTH_SHORT Toast.LENGTH_SHORT
).show() ).show()
tabNewBadge.removeBadge() tabNewBadge.removeBadge()
tagsBadge = itemsByTag.map {
(it.key to ((tagsBadge[it.key] ?: it.value) - it.value))
}.toMap()
reloadTagsBadges()
getElementsAccordingToTab()
} else { } else {
Toast.makeText( Toast.makeText(
this@HomeActivity, this@HomeActivity,
R.string.all_posts_not_read, R.string.all_posts_not_read,
Toast.LENGTH_SHORT Toast.LENGTH_SHORT
).show() ).show()
if (debugReadingItems) {
readAllDebug(
Throwable(
"Got response, but : response.body() (${response.body()}) != null && response.body()!!.isSuccess (${response.body()?.isSuccess})." +
"Request url was (${call.request().url()}), ids were $ids"
)
)
}
} }
swipeRefreshLayout.isRefreshing = false swipeRefreshLayout.isRefreshing = false
@ -1033,9 +1165,15 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
Toast.LENGTH_SHORT Toast.LENGTH_SHORT
).show() ).show()
swipeRefreshLayout.isRefreshing = false swipeRefreshLayout.isRefreshing = false
if (debugReadingItems) {
readAllDebug(t)
}
} }
}) })
items = ArrayList() items = ArrayList()
allItems = ArrayList()
}
if (items.isEmpty()) { if (items.isEmpty()) {
Toast.makeText( Toast.makeText(
this@HomeActivity, this@HomeActivity,
@ -1044,6 +1182,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
).show() ).show()
} }
handleListResult() handleListResult()
})
} }
return true return true
} }
@ -1052,7 +1191,8 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
} }
R.id.action_share_the_app -> { R.id.action_share_the_app -> {
if (GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(this) == ConnectionResult.SUCCESS) { if (GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(this) == ConnectionResult.SUCCESS) {
val share = AppInviteInvitation.IntentBuilder(getString(R.string.invitation_title)) val share =
AppInviteInvitation.IntentBuilder(getString(R.string.invitation_title))
.setMessage(getString(R.string.invitation_message)) .setMessage(getString(R.string.invitation_message))
.setDeepLink(Uri.parse("https://ymbh5.app.goo.gl/qbvQ")) .setDeepLink(Uri.parse("https://ymbh5.app.goo.gl/qbvQ"))
.setCallToActionText(getString(R.string.invitation_cta)) .setCallToActionText(getString(R.string.invitation_cta))

View File

@ -17,10 +17,10 @@ import android.widget.TextView
import android.widget.Toast 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.SuccessResponse import apps.amine.bou.readerforselfoss.api.selfoss.SuccessResponse
import apps.amine.bou.readerforselfoss.themes.AppColors
import apps.amine.bou.readerforselfoss.utils.Config import apps.amine.bou.readerforselfoss.utils.Config
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.google.firebase.analytics.FirebaseAnalytics import com.google.firebase.analytics.FirebaseAnalytics
import com.mikepenz.aboutlibraries.Libs import com.mikepenz.aboutlibraries.Libs
import com.mikepenz.aboutlibraries.LibsBuilder import com.mikepenz.aboutlibraries.LibsBuilder
@ -41,10 +41,13 @@ class LoginActivity : AppCompatActivity() {
private lateinit var firebaseAnalytics: FirebaseAnalytics private lateinit var firebaseAnalytics: FirebaseAnalytics
private lateinit var userIdentifier: String private lateinit var userIdentifier: String
private var logErrors: Boolean = false private var logErrors: Boolean = false
private lateinit var appColors: AppColors
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
appColors = AppColors(this@LoginActivity)
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
Scoop.getInstance().apply(this)
setContentView(R.layout.activity_login) setContentView(R.layout.activity_login)
setSupportActionBar(toolbar) setSupportActionBar(toolbar)

View File

@ -87,19 +87,7 @@ 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, false)
.addFlavor(getString(R.string.teal_orange_theme), R.style.NoBarTealOrange)
.addFlavor(getString(R.string.teal_orange_dark_theme), R.style.NoBarTealOrangeDark)
.addFlavor(getString(R.string.cyan_pink_theme), R.style.NoBarCyanPink)
.addFlavor(getString(R.string.cyan_pink_dark_theme), R.style.NoBarCyanPinkDark)
.addFlavor(getString(R.string.grey_orange_theme), R.style.NoBarGreyOrange)
.addFlavor(getString(R.string.grey_orange_dark_theme), R.style.NoBarGreyOrangeDark)
.addFlavor(getString(R.string.blue_amber_theme), R.style.NoBarBlueAmber)
.addFlavor(getString(R.string.blue_amber_dark_theme), R.style.NoBarBlueAmberDark)
.addFlavor(getString(R.string.indigo_pink_theme), R.style.NoBarIndigoPink)
.addFlavor(getString(R.string.indigo_pink_dark_theme), R.style.NoBarIndigoPinkDark)
.addFlavor(getString(R.string.red_teal_theme), R.style.NoBarRedTeal)
.addFlavor(getString(R.string.red_teal_dark_theme), R.style.NoBarRedTealDark)
.setSharedPreferences(PreferenceManager.getDefaultSharedPreferences(this)) .setSharedPreferences(PreferenceManager.getDefaultSharedPreferences(this))
.initialize() .initialize()
} }

View File

@ -1,20 +1,26 @@
package apps.amine.bou.readerforselfoss package apps.amine.bou.readerforselfoss
import android.content.Context import android.content.Context
import android.content.res.Resources
import android.os.Bundle import android.os.Bundle
import android.preference.PreferenceManager import android.preference.PreferenceManager
import android.support.v4.app.FragmentManager import android.support.v4.app.FragmentManager
import android.support.v4.app.FragmentStatePagerAdapter import android.support.v4.app.FragmentStatePagerAdapter
import android.support.v4.view.ViewPager import android.support.v4.view.ViewPager
import android.support.v7.app.AppCompatActivity import android.support.v7.app.AppCompatActivity
import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import android.widget.Toast
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.fragments.ArticleFragment import apps.amine.bou.readerforselfoss.fragments.ArticleFragment
import apps.amine.bou.readerforselfoss.themes.AppColors
import apps.amine.bou.readerforselfoss.themes.Toppings
import apps.amine.bou.readerforselfoss.transformers.DepthPageTransformer import apps.amine.bou.readerforselfoss.transformers.DepthPageTransformer
import apps.amine.bou.readerforselfoss.utils.Config import apps.amine.bou.readerforselfoss.utils.Config
import apps.amine.bou.readerforselfoss.utils.succeeded import apps.amine.bou.readerforselfoss.utils.succeeded
import apps.amine.bou.readerforselfoss.utils.toggleStar
import com.crashlytics.android.Crashlytics import com.crashlytics.android.Crashlytics
import com.ftinc.scoop.Scoop import com.ftinc.scoop.Scoop
import kotlinx.android.synthetic.main.activity_reader.* import kotlinx.android.synthetic.main.activity_reader.*
@ -26,14 +32,38 @@ import retrofit2.Response
class ReaderActivity : AppCompatActivity() { class ReaderActivity : AppCompatActivity() {
private var markOnScroll: Boolean = false private var markOnScroll: Boolean = false
private var debugReadingItems: Boolean = false
private var currentItem: Int = 0
private lateinit var userIdentifier: String
private var useWebview: Boolean = false private lateinit var api: SelfossApi
private lateinit var toolbarMenu: Menu
private fun showMenuItem(willAddToFavorite: Boolean) {
toolbarMenu.findItem(R.id.save).isVisible = willAddToFavorite
toolbarMenu.findItem(R.id.unsave).isVisible = !willAddToFavorite
}
private fun canFavorite() {
showMenuItem(true)
}
private fun canRemoveFromFavorite() {
showMenuItem(false)
}
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
val appColors = AppColors(this@ReaderActivity)
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
Scoop.getInstance().apply(this)
setContentView(R.layout.activity_reader) setContentView(R.layout.activity_reader)
Scoop.getInstance()
.bind(this, Toppings.PRIMARY.value, toolBar)
.bindStatusBar(this, Toppings.PRIMARY_DARK.value)
setSupportActionBar(toolBar) setSupportActionBar(toolBar)
supportActionBar?.setDisplayHomeAsUpEnabled(true) supportActionBar?.setDisplayHomeAsUpEnabled(true)
supportActionBar?.setDisplayShowHomeEnabled(true) supportActionBar?.setDisplayShowHomeEnabled(true)
@ -41,51 +71,51 @@ class ReaderActivity : AppCompatActivity() {
val settings = getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE) val settings = getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE)
val sharedPref = PreferenceManager.getDefaultSharedPreferences(this) val sharedPref = PreferenceManager.getDefaultSharedPreferences(this)
val debugReadingItems = sharedPref.getBoolean("read_debug", false) debugReadingItems = sharedPref.getBoolean("read_debug", false)
val userIdentifier = sharedPref.getString("unique_id", "") userIdentifier = sharedPref.getString("unique_id", "")
markOnScroll = sharedPref.getBoolean("mark_on_scroll", false) markOnScroll = sharedPref.getBoolean("mark_on_scroll", false)
useWebview = sharedPref.getBoolean("prefer_webview_in_article_viewer", false)
if (allItems.isEmpty()) { if (allItems.isEmpty()) {
Crashlytics.setUserIdentifier(userIdentifier)
Crashlytics.log(
100,
"READER_ITEMS_EMPTY",
"Items empty when trying to open the Article Reader. Was (static) companion object field set ?"
)
Crashlytics.logException(Exception("Empty items on Reader Activity."))
finish() finish()
} }
val api = SelfossApi( api = SelfossApi(
this, this,
this@ReaderActivity, this@ReaderActivity,
settings.getBoolean("isSelfSignedCert", false), settings.getBoolean("isSelfSignedCert", false),
sharedPref.getBoolean("should_log_everything", false) sharedPref.getBoolean("should_log_everything", false)
) )
val currentItem = intent.getIntExtra("currentItem", 0) currentItem = intent.getIntExtra("currentItem", 0)
var adapter = ScreenSlidePagerAdapter(supportFragmentManager) pager.adapter = ScreenSlidePagerAdapter(supportFragmentManager)
pager.adapter = adapter
pager.currentItem = currentItem pager.currentItem = currentItem
}
override fun onResume() {
super.onResume()
(pager.adapter as ScreenSlidePagerAdapter).notifyDataSetChanged()
pager.setPageTransformer(true, DepthPageTransformer()) pager.setPageTransformer(true, DepthPageTransformer())
(indicator as CircleIndicator).setViewPager(pager) (indicator as CircleIndicator).setViewPager(pager)
if (markOnScroll) {
pager.addOnPageChangeListener( pager.addOnPageChangeListener(
object : ViewPager.SimpleOnPageChangeListener() { object : ViewPager.SimpleOnPageChangeListener() {
var isLastItem = false var isLastItem = false
override fun onPageSelected(position: Int) { override fun onPageSelected(position: Int) {
isLastItem = (position === (allItems.size - 1)) isLastItem = (position === (allItems.size - 1))
if (allItems[position].starred) {
canRemoveFromFavorite()
} else {
canFavorite()
}
} }
override fun onPageScrollStateChanged(state: Int) { override fun onPageScrollStateChanged(state: Int) {
if (state === ViewPager.SCROLL_STATE_DRAGGING || (state === ViewPager.SCROLL_STATE_IDLE && isLastItem)) { if (markOnScroll && (state === ViewPager.SCROLL_STATE_DRAGGING || (state === ViewPager.SCROLL_STATE_IDLE && isLastItem))) {
api.markItem(allItems[pager.currentItem].id).enqueue( api.markItem(allItems[pager.currentItem].id).enqueue(
object : Callback<SuccessResponse> { object : Callback<SuccessResponse> {
override fun onResponse( override fun onResponse(
@ -132,7 +162,6 @@ class ReaderActivity : AppCompatActivity() {
} }
) )
} }
}
override fun onPause() { override fun onPause() {
super.onPause() super.onPause()
@ -146,22 +175,83 @@ class ReaderActivity : AppCompatActivity() {
oldInstanceState!!.clear() oldInstanceState!!.clear()
} }
private inner class ScreenSlidePagerAdapter(fm: FragmentManager) : FragmentStatePagerAdapter(fm) { private inner class ScreenSlidePagerAdapter(fm: FragmentManager) :
FragmentStatePagerAdapter(fm) {
override fun getCount(): Int { override fun getCount(): Int {
return allItems.size return allItems.size
} }
override fun getItem(position: Int): ArticleFragment { override fun getItem(position: Int): ArticleFragment {
return ArticleFragment.newInstance(position, allItems, useWebview) return ArticleFragment.newInstance(position, allItems)
} }
} }
override fun onCreateOptionsMenu(menu: Menu): Boolean {
val inflater = menuInflater
inflater.inflate(R.menu.reader_menu, menu)
toolbarMenu = menu
if (!allItems.isEmpty() && allItems[currentItem].starred) {
canRemoveFromFavorite()
} else {
canFavorite()
}
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean { override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) { when (item.itemId) {
android.R.id.home -> { android.R.id.home -> {
onBackPressed() onBackPressed()
return true return true
} }
R.id.save -> {
api.starrItem(allItems[pager.currentItem].id)
.enqueue(object : Callback<SuccessResponse> {
override fun onResponse(
call: Call<SuccessResponse>,
response: Response<SuccessResponse>
) {
allItems[pager.currentItem] = allItems[pager.currentItem].toggleStar()
canRemoveFromFavorite()
}
override fun onFailure(
call: Call<SuccessResponse>,
t: Throwable
) {
Toast.makeText(
baseContext,
R.string.cant_mark_favortie,
Toast.LENGTH_SHORT
).show()
}
})
}
R.id.unsave -> {
api.unstarrItem(allItems[pager.currentItem].id)
.enqueue(object : Callback<SuccessResponse> {
override fun onResponse(
call: Call<SuccessResponse>,
response: Response<SuccessResponse>
) {
allItems[pager.currentItem] = allItems[pager.currentItem].toggleStar()
canFavorite()
}
override fun onFailure(
call: Call<SuccessResponse>,
t: Throwable
) {
Toast.makeText(
baseContext,
R.string.cant_unmark_favortie,
Toast.LENGTH_SHORT
).show()
}
})
}
} }
return super.onOptionsItemSelected(item) return super.onOptionsItemSelected(item)
} }

View File

@ -1,6 +1,7 @@
package apps.amine.bou.readerforselfoss package apps.amine.bou.readerforselfoss
import android.content.Intent import android.content.Intent
import android.content.res.ColorStateList
import android.os.Bundle import android.os.Bundle
import android.preference.PreferenceManager import android.preference.PreferenceManager
import android.support.v7.app.AppCompatActivity import android.support.v7.app.AppCompatActivity
@ -9,6 +10,8 @@ import android.widget.Toast
import apps.amine.bou.readerforselfoss.adapters.SourcesListAdapter import apps.amine.bou.readerforselfoss.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 apps.amine.bou.readerforselfoss.themes.AppColors
import apps.amine.bou.readerforselfoss.themes.Toppings
import com.ftinc.scoop.Scoop import com.ftinc.scoop.Scoop
import kotlinx.android.synthetic.main.activity_sources.* import kotlinx.android.synthetic.main.activity_sources.*
import retrofit2.Call import retrofit2.Call
@ -17,14 +20,25 @@ import retrofit2.Response
class SourcesActivity : AppCompatActivity() { class SourcesActivity : AppCompatActivity() {
private lateinit var appColors: AppColors
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
appColors = AppColors(this@SourcesActivity)
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
Scoop.getInstance().apply(this)
setContentView(R.layout.activity_sources) setContentView(R.layout.activity_sources)
Scoop.getInstance()
.bind(this, Toppings.PRIMARY.value, toolbar)
.bindStatusBar(this, Toppings.PRIMARY_DARK.value)
setSupportActionBar(toolbar) setSupportActionBar(toolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true) supportActionBar?.setDisplayHomeAsUpEnabled(true)
supportActionBar?.setDisplayShowHomeEnabled(true) supportActionBar?.setDisplayShowHomeEnabled(true)
fab.rippleColor = appColors.colorAccentDark
fab.backgroundTintList = ColorStateList.valueOf(appColors.colorAccent)
} }
override fun onStop() { override fun onStop() {

View File

@ -2,8 +2,6 @@ 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.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
@ -11,7 +9,6 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.ImageView.ScaleType import android.widget.ImageView.ScaleType
import android.widget.TextView
import android.widget.Toast import android.widget.Toast
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
@ -26,12 +23,10 @@ import apps.amine.bou.readerforselfoss.utils.openInBrowserAsNewTask
import apps.amine.bou.readerforselfoss.utils.openItemUrl import apps.amine.bou.readerforselfoss.utils.openItemUrl
import apps.amine.bou.readerforselfoss.utils.shareLink import apps.amine.bou.readerforselfoss.utils.shareLink
import apps.amine.bou.readerforselfoss.utils.sourceAndDateText import apps.amine.bou.readerforselfoss.utils.sourceAndDateText
import apps.amine.bou.readerforselfoss.utils.succeeded
import apps.amine.bou.readerforselfoss.utils.toTextDrawableString import apps.amine.bou.readerforselfoss.utils.toTextDrawableString
import com.amulyakhare.textdrawable.TextDrawable import com.amulyakhare.textdrawable.TextDrawable
import com.amulyakhare.textdrawable.util.ColorGenerator import com.amulyakhare.textdrawable.util.ColorGenerator
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.crashlytics.android.Crashlytics
import com.like.LikeButton import com.like.LikeButton
import com.like.OnLikeListener import com.like.OnLikeListener
import kotlinx.android.synthetic.main.card_item.view.* import kotlinx.android.synthetic.main.card_item.view.*
@ -40,20 +35,21 @@ import retrofit2.Callback
import retrofit2.Response import retrofit2.Response
class ItemCardAdapter( class ItemCardAdapter(
private val app: Activity, override val app: Activity,
private val items: ArrayList<Item>, override var items: ArrayList<Item>,
private val api: SelfossApi, override val api: SelfossApi,
private val helper: CustomTabActivityHelper, private val helper: CustomTabActivityHelper,
private val internalBrowser: Boolean, private val internalBrowser: Boolean,
private val articleViewer: Boolean, private val articleViewer: Boolean,
private val fullHeightCards: Boolean, private val fullHeightCards: Boolean,
private val appColors: AppColors, override val appColors: AppColors,
val debugReadingItems: Boolean, override val debugReadingItems: Boolean,
val userIdentifier: String override val userIdentifier: String
) : RecyclerView.Adapter<ItemCardAdapter.ViewHolder>() { ) : ItemsAdapter<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() 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 CardView val v = LayoutInflater.from(c).inflate(R.layout.card_item, parent, false) as CardView
@ -67,6 +63,8 @@ class ItemCardAdapter(
holder.mView.favButton.isLiked = itm.starred holder.mView.favButton.isLiked = itm.starred
holder.mView.title.text = Html.fromHtml(itm.title) holder.mView.title.text = Html.fromHtml(itm.title)
holder.mView.title.setLinkTextColor(appColors.colorAccent)
holder.mView.sourceTitleAndDate.text = itm.sourceAndDateText() holder.mView.sourceTitleAndDate.text = itm.sourceAndDateText()
if (!fullHeightCards) { if (!fullHeightCards) {
@ -103,89 +101,9 @@ class ItemCardAdapter(
return items.size return items.size
} }
private fun doUnmark(i: Item, position: Int) {
val s = Snackbar
.make(
app.findViewById(R.id.coordLayout),
R.string.marked_as_read,
Snackbar.LENGTH_LONG
)
.setAction(R.string.undo_string) {
items.add(position, i)
notifyItemInserted(position)
api.unmarkItem(i.id).enqueue(object : Callback<SuccessResponse> {
override fun onResponse(
call: Call<SuccessResponse>,
response: Response<SuccessResponse>
) {
}
override fun onFailure(call: Call<SuccessResponse>, t: Throwable) {
items.remove(i)
notifyItemRemoved(position)
doUnmark(i, position)
}
})
}
val view = s.view
val tv: TextView = view.findViewById(android.support.design.R.id.snackbar_text)
tv.setTextColor(Color.WHITE)
s.show()
}
fun removeItemAtIndex(position: Int) {
val i = items[position]
items.remove(i)
notifyItemRemoved(position)
api.markItem(i.id).enqueue(object : Callback<SuccessResponse> {
override fun onResponse(
call: Call<SuccessResponse>,
response: Response<SuccessResponse>
) {
if (!response.succeeded() && debugReadingItems) {
val message =
"message: ${response.message()} " +
"response isSuccess: ${response.isSuccessful} " +
"response code: ${response.code()} " +
"response message: ${response.message()} " +
"response errorBody: ${response.errorBody()?.string()} " +
"body success: ${response.body()?.success} " +
"body isSuccess: ${response.body()?.isSuccess}"
Crashlytics.setUserIdentifier(userIdentifier)
Crashlytics.log(100, "READ_DEBUG_SUCCESS", message)
Crashlytics.logException(Exception("Was success, but did it work ?"))
Toast.makeText(c, message, Toast.LENGTH_LONG).show()
}
doUnmark(i, position)
}
override fun onFailure(call: Call<SuccessResponse>, t: Throwable) {
if (debugReadingItems) {
Crashlytics.setUserIdentifier(userIdentifier)
Crashlytics.log(100, "READ_DEBUG_ERROR", t.message)
Crashlytics.logException(t)
Toast.makeText(c, t.message, Toast.LENGTH_LONG).show()
}
Toast.makeText(
app,
app.getString(R.string.cant_mark_read),
Toast.LENGTH_SHORT
).show()
items.add(i)
notifyItemInserted(position)
}
})
}
inner class ViewHolder(val mView: CardView) : RecyclerView.ViewHolder(mView) { inner class ViewHolder(val mView: CardView) : RecyclerView.ViewHolder(mView) {
init { init {
mView.setCardBackgroundColor(appColors.cardBackground) mView.setCardBackgroundColor(appColors.cardBackgroundColor)
handleClickListeners() handleClickListeners()
handleCustomTabActions() handleCustomTabActions()
} }

View File

@ -2,21 +2,19 @@ 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.support.constraint.ConstraintLayout import android.support.constraint.ConstraintLayout
import android.support.design.widget.Snackbar
import android.support.v7.widget.RecyclerView import android.support.v7.widget.RecyclerView
import android.text.Html import android.text.Html
import android.util.TypedValue 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.TextView
import android.widget.Toast import android.widget.Toast
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.utils.buildCustomTabsIntent 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
@ -25,10 +23,9 @@ import apps.amine.bou.readerforselfoss.utils.openInBrowserAsNewTask
import apps.amine.bou.readerforselfoss.utils.openItemUrl import apps.amine.bou.readerforselfoss.utils.openItemUrl
import apps.amine.bou.readerforselfoss.utils.shareLink import apps.amine.bou.readerforselfoss.utils.shareLink
import apps.amine.bou.readerforselfoss.utils.sourceAndDateText 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.TextDrawable
import com.amulyakhare.textdrawable.util.ColorGenerator import com.amulyakhare.textdrawable.util.ColorGenerator
import com.crashlytics.android.Crashlytics
import com.like.LikeButton import com.like.LikeButton
import com.like.OnLikeListener import com.like.OnLikeListener
import kotlinx.android.synthetic.main.list_item.view.* import kotlinx.android.synthetic.main.list_item.view.*
@ -39,16 +36,17 @@ import java.util.*
import kotlin.collections.ArrayList import kotlin.collections.ArrayList
class ItemListAdapter( class ItemListAdapter(
private val app: Activity, override val app: Activity,
private val items: ArrayList<Item>, override var items: ArrayList<Item>,
private val api: SelfossApi, override 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, override val debugReadingItems: Boolean,
val userIdentifier: String override val userIdentifier: String,
) : RecyclerView.Adapter<ItemListAdapter.ViewHolder>() { override val appColors: AppColors
) : ItemsAdapter<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))
@ -66,9 +64,10 @@ class ItemListAdapter(
val itm = items[position] val itm = items[position]
holder.mView.favButton.isLiked = itm.starred
holder.mView.title.text = Html.fromHtml(itm.title) holder.mView.title.text = Html.fromHtml(itm.title)
holder.mView.title.setLinkTextColor(appColors.colorAccent)
holder.mView.sourceTitleAndDate.text = itm.sourceAndDateText() holder.mView.sourceTitleAndDate.text = itm.sourceAndDateText()
if (itm.getThumbnail(c).isEmpty()) { if (itm.getThumbnail(c).isEmpty()) {
@ -92,14 +91,13 @@ class ItemListAdapter(
if (itm.getIcon(c).isEmpty()) { if (itm.getIcon(c).isEmpty()) {
val color = generator.getColor(itm.sourcetitle) val color = generator.getColor(itm.sourcetitle)
val textDrawable = StringBuilder()
for (s in itm.sourcetitle.split(" ".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()) {
textDrawable.append(s[0])
}
val builder = TextDrawable.builder().round() val drawable =
TextDrawable
.builder()
.round()
.build(itm.sourcetitle.toTextDrawableString(), color)
val drawable = builder.build(textDrawable.toString(), color)
holder.mView.itemImage.setImageDrawable(drawable) holder.mView.itemImage.setImageDrawable(drawable)
} else { } else {
c.circularBitmapDrawable(itm.getIcon(c), holder.mView.itemImage) c.circularBitmapDrawable(itm.getIcon(c), holder.mView.itemImage)
@ -108,96 +106,22 @@ class ItemListAdapter(
c.bitmapCenterCrop(itm.getThumbnail(c), holder.mView.itemImage) c.bitmapCenterCrop(itm.getThumbnail(c), holder.mView.itemImage)
} }
// TODO: maybe handle this differently. It crashes when changing tab
try {
if (bars[position]) { if (bars[position]) {
holder.mView.actionBar.visibility = View.VISIBLE holder.mView.actionBar.visibility = View.VISIBLE
} else { } else {
holder.mView.actionBar.visibility = View.GONE holder.mView.actionBar.visibility = View.GONE
} }
} catch (e: IndexOutOfBoundsException) {
holder.mView.actionBar.visibility = View.GONE
}
holder.mView.favButton.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) {
val s = Snackbar
.make(
app.findViewById(R.id.coordLayout),
R.string.marked_as_read,
Snackbar.LENGTH_LONG
)
.setAction(R.string.undo_string) {
items.add(position, i)
notifyItemInserted(position)
api.unmarkItem(i.id).enqueue(object : Callback<SuccessResponse> {
override fun onResponse(
call: Call<SuccessResponse>,
response: Response<SuccessResponse>
) {
}
override fun onFailure(call: Call<SuccessResponse>, t: Throwable) {
items.remove(i)
notifyItemRemoved(position)
doUnmark(i, position)
}
})
}
val view = s.view
val tv: TextView = view.findViewById(android.support.design.R.id.snackbar_text)
tv.setTextColor(Color.WHITE)
s.show()
}
fun removeItemAtIndex(position: Int) {
val i = items[position]
items.remove(i)
notifyItemRemoved(position)
api.markItem(i.id).enqueue(object : Callback<SuccessResponse> {
override fun onResponse(
call: Call<SuccessResponse>,
response: Response<SuccessResponse>
) {
if (!response.succeeded() && debugReadingItems) {
val message =
"message: ${response.message()} " +
"response isSuccess: ${response.isSuccessful} " +
"response code: ${response.code()} " +
"response message: ${response.message()} " +
"response errorBody: ${response.errorBody()?.string()} " +
"body success: ${response.body()?.success} " +
"body isSuccess: ${response.body()?.isSuccess}"
Crashlytics.setUserIdentifier(userIdentifier)
Crashlytics.log(100, "READ_DEBUG_SUCCESS", message)
Crashlytics.logException(Exception("Was success, but did it work ?"))
Toast.makeText(c, message, Toast.LENGTH_LONG).show()
}
doUnmark(i, position)
}
override fun onFailure(call: Call<SuccessResponse>, t: Throwable) {
if (debugReadingItems) {
Crashlytics.setUserIdentifier(userIdentifier)
Crashlytics.log(100, "READ_DEBUG_ERROR", t.message)
Crashlytics.logException(t)
Toast.makeText(c, t.message, Toast.LENGTH_LONG).show()
}
Toast.makeText(
app,
app.getString(R.string.cant_mark_read),
Toast.LENGTH_SHORT
).show()
items.add(i)
notifyItemInserted(position)
}
})
}
inner class ViewHolder(val mView: ConstraintLayout) : RecyclerView.ViewHolder(mView) { inner class ViewHolder(val mView: ConstraintLayout) : RecyclerView.ViewHolder(mView) {
init { init {

View File

@ -0,0 +1,123 @@
package apps.amine.bou.readerforselfoss.adapters
import android.app.Activity
import android.graphics.Color
import android.support.design.widget.Snackbar
import android.support.v7.widget.RecyclerView
import android.widget.TextView
import android.widget.Toast
import apps.amine.bou.readerforselfoss.R
import apps.amine.bou.readerforselfoss.api.selfoss.Item
import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi
import apps.amine.bou.readerforselfoss.api.selfoss.SuccessResponse
import apps.amine.bou.readerforselfoss.themes.AppColors
import apps.amine.bou.readerforselfoss.utils.succeeded
import com.crashlytics.android.Crashlytics
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
abstract class ItemsAdapter<VH : RecyclerView.ViewHolder?> : RecyclerView.Adapter<VH>() {
abstract var items: ArrayList<Item>
abstract val api: SelfossApi
abstract val debugReadingItems: Boolean
abstract val userIdentifier: String
abstract val app: Activity
abstract val appColors: AppColors
fun updateAllItems(newItems: ArrayList<Item>) {
items = newItems
notifyDataSetChanged()
}
private fun doUnmark(i: Item, position: Int) {
val s = Snackbar
.make(
app.findViewById(R.id.coordLayout),
R.string.marked_as_read,
Snackbar.LENGTH_LONG
)
.setAction(R.string.undo_string) {
items.add(position, i)
notifyItemInserted(position)
api.unmarkItem(i.id).enqueue(object : Callback<SuccessResponse> {
override fun onResponse(
call: Call<SuccessResponse>,
response: Response<SuccessResponse>
) {
}
override fun onFailure(call: Call<SuccessResponse>, t: Throwable) {
items.remove(i)
notifyItemRemoved(position)
doUnmark(i, position)
}
})
}
val view = s.view
val tv: TextView = view.findViewById(android.support.design.R.id.snackbar_text)
tv.setTextColor(Color.WHITE)
s.show()
}
fun removeItemAtIndex(position: Int) {
val i = items[position]
items.remove(i)
notifyItemRemoved(position)
api.markItem(i.id).enqueue(object : Callback<SuccessResponse> {
override fun onResponse(
call: Call<SuccessResponse>,
response: Response<SuccessResponse>
) {
if (!response.succeeded() && debugReadingItems) {
val message =
"message: ${response.message()} " +
"response isSuccess: ${response.isSuccessful} " +
"response code: ${response.code()} " +
"response message: ${response.message()} " +
"response errorBody: ${response.errorBody()?.string()} " +
"body success: ${response.body()?.success} " +
"body isSuccess: ${response.body()?.isSuccess}"
Crashlytics.setUserIdentifier(userIdentifier)
Crashlytics.log(100, "READ_DEBUG_SUCCESS", message)
Crashlytics.logException(Exception("Was success, but did it work ?"))
Toast.makeText(app.baseContext, message, Toast.LENGTH_LONG).show()
}
doUnmark(i, position)
}
override fun onFailure(call: Call<SuccessResponse>, t: Throwable) {
if (debugReadingItems) {
Crashlytics.setUserIdentifier(userIdentifier)
Crashlytics.log(100, "READ_DEBUG_ERROR", t.message)
Crashlytics.logException(t)
Toast.makeText(app.baseContext, t.message, Toast.LENGTH_LONG).show()
}
Toast.makeText(
app,
app.getString(R.string.cant_mark_read),
Toast.LENGTH_SHORT
).show()
items.add(i)
notifyItemInserted(position)
}
})
}
fun addItemAtIndex(item: Item, position: Int) {
items.add(position, item)
notifyItemInserted(position)
}
fun addItemsAtEnd(newItems: List<Item>) {
val oldSize = items.size
items.addAll(newItems)
notifyItemRangeInserted(oldSize, newItems.size)
}
}

View File

@ -6,9 +6,9 @@ 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,
@ -20,7 +20,8 @@ class ParsedContent(
companion object { companion object {
@JvmField @JvmField
val CREATOR: Parcelable.Creator<ParsedContent> = object : Parcelable.Creator<ParsedContent> { 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)
} }

View File

@ -66,11 +66,12 @@ data class Item(
@SerializedName("title") val title: String, @SerializedName("title") val title: String,
@SerializedName("content") val content: String, @SerializedName("content") val content: String,
@SerializedName("unread") val unread: Boolean, @SerializedName("unread") val unread: Boolean,
@SerializedName("starred") val starred: Boolean, @SerializedName("starred") var starred: Boolean,
@SerializedName("thumbnail") val thumbnail: String, @SerializedName("thumbnail") val thumbnail: String,
@SerializedName("icon") val icon: String, @SerializedName("icon") val icon: String,
@SerializedName("link") val link: String, @SerializedName("link") val link: String,
@SerializedName("sourcetitle") val sourcetitle: String @SerializedName("sourcetitle") val sourcetitle: String,
@SerializedName("tags") val tags: String
) : Parcelable { ) : Parcelable {
var config: Config? = null var config: Config? = null
@ -92,7 +93,8 @@ data class Item(
thumbnail = source.readString(), thumbnail = source.readString(),
icon = source.readString(), icon = source.readString(),
link = source.readString(), link = source.readString(),
sourcetitle = source.readString() sourcetitle = source.readString(),
tags = source.readString()
) )
override fun describeContents() = 0 override fun describeContents() = 0
@ -108,6 +110,7 @@ data class Item(
dest.writeString(icon) dest.writeString(icon)
dest.writeString(link) dest.writeString(link)
dest.writeString(sourcetitle) dest.writeString(sourcetitle)
dest.writeString(tags)
} }
fun getIcon(app: Context): String { fun getIcon(app: Context): String {
@ -127,7 +130,8 @@ data class Item(
// 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
stringUrl = 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("&amp;url=")) { if (link.contains("&amp;url=")) {
link.substringAfter("&amp;url=") link.substringAfter("&amp;url=")
} else { } else {
@ -144,7 +148,7 @@ data class Item(
// handle url not starting with http // handle url not starting with http
if (stringUrl.startsWith("//")) { if (stringUrl.startsWith("//")) {
stringUrl = "http:" + stringUrl stringUrl = "http:$stringUrl"
} }
return stringUrl return stringUrl

View File

@ -1,16 +1,20 @@
package apps.amine.bou.readerforselfoss.fragments package apps.amine.bou.readerforselfoss.fragments
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences import android.content.SharedPreferences
import android.content.res.ColorStateList
import android.graphics.drawable.ColorDrawable
import android.net.Uri
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.preference.PreferenceManager import android.preference.PreferenceManager
import android.support.customtabs.CustomTabsIntent import android.support.customtabs.CustomTabsIntent
import android.support.design.widget.FloatingActionButton import android.support.design.widget.FloatingActionButton
import android.support.v4.app.Fragment import android.support.v4.app.Fragment
import android.support.v4.content.ContextCompat
import android.support.v4.widget.NestedScrollView import android.support.v4.widget.NestedScrollView
import android.text.Html import android.support.v7.app.AlertDialog
import android.text.method.LinkMovementMethod
import android.util.TypedValue
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
@ -21,24 +25,29 @@ import apps.amine.bou.readerforselfoss.R
import apps.amine.bou.readerforselfoss.api.mercury.MercuryApi import apps.amine.bou.readerforselfoss.api.mercury.MercuryApi
import apps.amine.bou.readerforselfoss.api.mercury.ParsedContent import apps.amine.bou.readerforselfoss.api.mercury.ParsedContent
import apps.amine.bou.readerforselfoss.api.selfoss.Item import apps.amine.bou.readerforselfoss.api.selfoss.Item
import apps.amine.bou.readerforselfoss.themes.AppColors
import apps.amine.bou.readerforselfoss.utils.buildCustomTabsIntent import apps.amine.bou.readerforselfoss.utils.buildCustomTabsIntent
import apps.amine.bou.readerforselfoss.utils.customtabs.CustomTabActivityHelper import apps.amine.bou.readerforselfoss.utils.customtabs.CustomTabActivityHelper
import apps.amine.bou.readerforselfoss.utils.isEmptyOrNullOrNullString import apps.amine.bou.readerforselfoss.utils.isEmptyOrNullOrNullString
import apps.amine.bou.readerforselfoss.utils.openItemUrl import apps.amine.bou.readerforselfoss.utils.openItemUrl
import apps.amine.bou.readerforselfoss.utils.shareLink import apps.amine.bou.readerforselfoss.utils.shareLink
import apps.amine.bou.readerforselfoss.utils.sourceAndDateText import apps.amine.bou.readerforselfoss.utils.sourceAndDateText
import apps.amine.bou.readerforselfoss.utils.toPx
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions import com.bumptech.glide.request.RequestOptions
import com.crashlytics.android.Crashlytics import com.crashlytics.android.Crashlytics
import com.ftinc.scoop.Scoop
import com.github.rubensousa.floatingtoolbar.FloatingToolbar import com.github.rubensousa.floatingtoolbar.FloatingToolbar
import kotlinx.android.synthetic.main.fragment_article.view.* import kotlinx.android.synthetic.main.fragment_article.view.*
import org.sufficientlysecure.htmltextview.HtmlHttpImageGetter
import retrofit2.Call import retrofit2.Call
import retrofit2.Callback import retrofit2.Callback
import retrofit2.Response import retrofit2.Response
import java.net.MalformedURLException
import java.net.URL
class ArticleFragment : Fragment() { class ArticleFragment : Fragment() {
private lateinit var pageNumber: Number private lateinit var pageNumber: Number
private var fontSize: Int = 14
private lateinit var allItems: ArrayList<Item> private lateinit var allItems: ArrayList<Item>
private lateinit var mCustomTabActivityHelper: CustomTabActivityHelper private lateinit var mCustomTabActivityHelper: CustomTabActivityHelper
private lateinit var url: String private lateinit var url: String
@ -46,9 +55,10 @@ class ArticleFragment : Fragment() {
private lateinit var contentSource: String private lateinit var contentSource: String
private lateinit var contentImage: String private lateinit var contentImage: String
private lateinit var contentTitle: String private lateinit var contentTitle: String
private var showMalformedUrl: Boolean = false
private lateinit var editor: SharedPreferences.Editor
private lateinit var fab: FloatingActionButton private lateinit var fab: FloatingActionButton
private lateinit var appColors: AppColors
private var useWebview: Boolean = false
override fun onStop() { override fun onStop() {
super.onStop() super.onStop()
@ -56,14 +66,17 @@ class ArticleFragment : Fragment() {
} }
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
appColors = AppColors(activity!!)
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
pageNumber = arguments!!.getInt(ARG_POSITION) pageNumber = arguments!!.getInt(ARG_POSITION)
allItems = arguments!!.getParcelableArrayList(ARG_ITEMS) allItems = arguments!!.getParcelableArrayList(ARG_ITEMS)
useWebview = arguments!!.getBoolean(ARG_WEBVIEW)
} }
private lateinit var rootView: ViewGroup private lateinit var rootView: ViewGroup
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,
container: ViewGroup?, container: ViewGroup?,
@ -72,6 +85,8 @@ class ArticleFragment : Fragment() {
rootView = inflater rootView = inflater
.inflate(R.layout.fragment_article, container, false) as ViewGroup .inflate(R.layout.fragment_article, container, false) as ViewGroup
val context: Context = activity!!
url = allItems[pageNumber.toInt()].getLinkDecoded() url = allItems[pageNumber.toInt()].getLinkDecoded()
contentText = allItems[pageNumber.toInt()].content contentText = allItems[pageNumber.toInt()].content
contentTitle = allItems[pageNumber.toInt()].title contentTitle = allItems[pageNumber.toInt()].title
@ -79,20 +94,31 @@ class ArticleFragment : Fragment() {
contentSource = allItems[pageNumber.toInt()].sourceAndDateText() contentSource = allItems[pageNumber.toInt()].sourceAndDateText()
fab = rootView.fab fab = rootView.fab
val mFloatingToolbar: FloatingToolbar = rootView.floatingToolbar
mFloatingToolbar.attachFab(fab) fab.backgroundTintList = ColorStateList.valueOf(appColors.colorAccent)
fab.rippleColor = appColors.colorAccentDark
val floatingToolbar: FloatingToolbar = rootView.floatingToolbar
floatingToolbar.attachFab(fab)
floatingToolbar.background = ColorDrawable(appColors.colorAccent)
val customTabsIntent = activity!!.buildCustomTabsIntent() val customTabsIntent = activity!!.buildCustomTabsIntent()
mCustomTabActivityHelper = CustomTabActivityHelper() mCustomTabActivityHelper = CustomTabActivityHelper()
mCustomTabActivityHelper.bindCustomTabsService(activity) mCustomTabActivityHelper.bindCustomTabsService(activity)
val prefs = PreferenceManager.getDefaultSharedPreferences(activity) val prefs = PreferenceManager.getDefaultSharedPreferences(activity)
editor = prefs.edit()
fontSize = prefs.getString("reader_font_size", "14").toInt()
showMalformedUrl = prefs.getBoolean("show_error_malformed_url", true)
mFloatingToolbar.setClickListener(
floatingToolbar.setClickListener(
object : FloatingToolbar.ItemClickListener { object : FloatingToolbar.ItemClickListener {
override fun onItemClick(item: MenuItem) { override fun onItemClick(item: MenuItem) {
when (item.itemId) { when (item.itemId) {
R.id.more_action -> getContentFromMercury(customTabsIntent, prefs) R.id.more_action -> getContentFromMercury(customTabsIntent, prefs, context)
R.id.share_action -> activity!!.shareLink(url) R.id.share_action -> activity!!.shareLink(url)
R.id.open_action -> activity!!.openItemUrl( R.id.open_action -> activity!!.openItemUrl(
allItems, allItems,
@ -112,23 +138,19 @@ class ArticleFragment : Fragment() {
} }
) )
rootView.source.text = contentSource
if (contentText.isEmptyOrNullOrNullString()) { if (contentText.isEmptyOrNullOrNullString()) {
getContentFromMercury(customTabsIntent, prefs) getContentFromMercury(customTabsIntent, prefs, context)
} else { } else {
rootView.source.text = contentSource
rootView.titleView.text = contentTitle rootView.titleView.text = contentTitle
if (!useWebview) { htmlToWebview(contentText, prefs, context)
htmlToTextview(contentText, customTabsIntent, prefs)
} else {
htmlToWebview(contentText)
}
if (!contentImage.isEmptyOrNullOrNullString()) { if (!contentImage.isEmptyOrNullOrNullString()) {
rootView.imageView.visibility = View.VISIBLE rootView.imageView.visibility = View.VISIBLE
Glide Glide
.with(activity!!.baseContext) .with(context)
.asBitmap() .asBitmap()
.load(contentImage) .load(contentImage)
.apply(RequestOptions.fitCenterTransform()) .apply(RequestOptions.fitCenterTransform())
@ -143,21 +165,18 @@ class ArticleFragment : Fragment() {
if (scrollY > oldScrollY) { if (scrollY > oldScrollY) {
fab.hide() fab.hide()
} else { } else {
if (mFloatingToolbar.isShowing) mFloatingToolbar.hide() else fab.show() if (floatingToolbar.isShowing) floatingToolbar.hide() else fab.show()
} }
} }
) )
if (!useWebview) {
rootView.content.movementMethod = LinkMovementMethod.getInstance()
}
return rootView return rootView
} }
private fun getContentFromMercury( private fun getContentFromMercury(
customTabsIntent: CustomTabsIntent, customTabsIntent: CustomTabsIntent,
prefs: SharedPreferences prefs: SharedPreferences,
context: Context
) { ) {
rootView.progressBar.visibility = View.VISIBLE rootView.progressBar.visibility = View.VISIBLE
val parser = MercuryApi( val parser = MercuryApi(
@ -171,40 +190,105 @@ class ArticleFragment : Fragment() {
call: Call<ParsedContent>, call: Call<ParsedContent>,
response: Response<ParsedContent> response: Response<ParsedContent>
) { ) {
if (response.body() != null && response.body()!!.content != null && response.body()!!.content.isNotEmpty()) { // TODO: clean all the following after finding the mercury content issue
rootView.source.text = response.body()!!.domain try {
if (response.body() != null && response.body()!!.content != null && !response.body()!!.content.isNullOrEmpty()) {
try {
rootView.titleView.text = response.body()!!.title rootView.titleView.text = response.body()!!.title
url = response.body()!!.url url = response.body()!!.url
} catch (e: Exception) {
if (response.body()!!.content != null && !response.body()!!.content.isEmpty()) { Crashlytics.setUserIdentifier(prefs.getString("unique_id", ""))
if (!useWebview) { Crashlytics.log(
htmlToTextview( 100,
response.body()!!.content, "MERCURY_CONTENT_EXCEPTION",
customTabsIntent, "source titleView or url issues"
prefs
) )
} else { Crashlytics.logException(e)
htmlToWebview(response.body()!!.content)
}
} }
if (response.body()!!.lead_image_url != null && !response.body()!!.lead_image_url.isEmpty()) { try {
htmlToWebview(response.body()!!.content.orEmpty(), prefs, context)
} catch (e: Exception) {
Crashlytics.setUserIdentifier(prefs.getString("unique_id", ""))
Crashlytics.log(
100,
"MERCURY_CONTENT_EXCEPTION",
"Webview issue ${e.message}"
)
Crashlytics.logException(e)
}
try {
if (response.body()!!.lead_image_url != null && !response.body()!!.lead_image_url.isNullOrEmpty()) {
rootView.imageView.visibility = View.VISIBLE rootView.imageView.visibility = View.VISIBLE
try {
Glide Glide
.with(activity!!.baseContext) .with(context)
.asBitmap() .asBitmap()
.load(response.body()!!.lead_image_url) .load(response.body()!!.lead_image_url)
.apply(RequestOptions.fitCenterTransform()) .apply(RequestOptions.fitCenterTransform())
.into(rootView.imageView) .into(rootView.imageView)
} catch (e: Exception) {
Crashlytics.setUserIdentifier(
prefs.getString(
"unique_id",
""
)
)
Crashlytics.log(
100,
"MERCURY_CONTENT_EXCEPTION",
"Glide issue with image ${response.body()!!.lead_image_url}"
)
Crashlytics.logException(e)
}
} else { } else {
rootView.imageView.visibility = View.GONE rootView.imageView.visibility = View.GONE
} }
} catch (e: Exception) {
Crashlytics.setUserIdentifier(prefs.getString("unique_id", ""))
Crashlytics.log(
100,
"MERCURY_CONTENT_EXCEPTION",
"Glide or image issue"
)
Crashlytics.logException(e)
}
try {
rootView.nestedScrollView.scrollTo(0, 0) rootView.nestedScrollView.scrollTo(0, 0)
rootView.progressBar.visibility = View.GONE rootView.progressBar.visibility = View.GONE
} catch (e: Exception) {
Crashlytics.setUserIdentifier(prefs.getString("unique_id", ""))
Crashlytics.log(
100,
"MERCURY_CONTENT_EXCEPTION",
"Scroll or visibility issues"
)
Crashlytics.logException(e)
}
} else { } else {
try {
openInBrowserAfterFailing(customTabsIntent) openInBrowserAfterFailing(customTabsIntent)
} catch (e: Exception) {
Crashlytics.setUserIdentifier(prefs.getString("unique_id", ""))
Crashlytics.log(
100,
"MERCURY_CONTENT_EXCEPTION",
"Browser after failing issue"
)
Crashlytics.logException(e)
}
}
} catch (e: Exception) {
Crashlytics.setUserIdentifier(prefs.getString("unique_id", ""))
Crashlytics.log(
100,
"MERCURY_CONTENT_EXCEPTION",
"UNCAUGHT (?) Fatal Exception on mercury response"
)
Crashlytics.logException(e)
} }
} }
@ -216,59 +300,121 @@ class ArticleFragment : Fragment() {
) )
} }
private fun htmlToTextview( private fun htmlToWebview(c: String, prefs: SharedPreferences, context: Context) {
c: String,
customTabsIntent: CustomTabsIntent,
prefs: SharedPreferences
) {
try {
rootView.content.visibility = View.VISIBLE
rootView.content.text = Html.fromHtml(
c,
HtmlHttpImageGetter(rootView.content, null, true),
null
)
} 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 htmlToWebview(c: String) { val stringColor = String.format("#%06X", 0xFFFFFF and appColors.colorAccent)
val attrBackground = TypedValue()
activity!!.baseContext.theme.resolveAttribute(
android.R.attr.colorBackground,
attrBackground,
true
)
val defaultColor = TypedValue()
activity!!.baseContext.theme.resolveAttribute(
android.R.attr.colorAccent,
defaultColor,
true
)
val accentColor = fab.backgroundTintList?.defaultColor ?: defaultColor.data
val stringColor = String.format("#%06X", 0xFFFFFF and accentColor)
rootView.webcontent.visibility = View.VISIBLE rootView.webcontent.visibility = View.VISIBLE
rootView.webcontent.setBackgroundColor(attrBackground.data) val (textColor, backgroundColor) = if (appColors.isDarkTheme) {
rootView.webcontent.setBackgroundColor(
ContextCompat.getColor(
context,
R.color.dark_webview
)
)
Pair(ContextCompat.getColor(context, R.color.dark_webview_text), ContextCompat.getColor(context, R.color.light_webview_text))
} else {
rootView.webcontent.setBackgroundColor(
ContextCompat.getColor(
context,
R.color.light_webview
)
)
Pair(ContextCompat.getColor(context, R.color.light_webview_text), ContextCompat.getColor(context, R.color.dark_webview_text))
}
val stringTextColor = String.format("#%06X", 0xFFFFFF and textColor)
val stringBackgroundColor = String.format("#%06X", 0xFFFFFF and backgroundColor)
rootView.webcontent.settings.useWideViewPort = true rootView.webcontent.settings.useWideViewPort = true
rootView.webcontent.settings.loadWithOverviewMode = true rootView.webcontent.settings.loadWithOverviewMode = true
rootView.webcontent.settings.javaScriptEnabled = false rootView.webcontent.settings.javaScriptEnabled = false
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
rootView.webcontent.settings.layoutAlgorithm = WebSettings.LayoutAlgorithm.TEXT_AUTOSIZING rootView.webcontent.settings.layoutAlgorithm =
WebSettings.LayoutAlgorithm.TEXT_AUTOSIZING
} else { } else {
rootView.webcontent.settings.layoutAlgorithm = WebSettings.LayoutAlgorithm.SINGLE_COLUMN rootView.webcontent.settings.layoutAlgorithm = WebSettings.LayoutAlgorithm.SINGLE_COLUMN
} }
rootView.webcontent.loadData( var baseUrl: String? = null
"<style>img{display: inline-block;height: auto; width: 100%; max-width: 100%;} a{color: $stringColor}</style>$c",
try {
val itemUrl = URL(url)
baseUrl = itemUrl.protocol + "://" + itemUrl.host
} catch (e: MalformedURLException) {
if (showMalformedUrl) {
val alertDialog = AlertDialog.Builder(context).create()
alertDialog.setTitle("Error")
alertDialog.setMessage("You are encountering a bug that I can't solve. Can you please contact me to solve the issue, please ?")
alertDialog.setButton(
AlertDialog.BUTTON_POSITIVE,
"Send mail",
{ dialog, _ ->
// This won't be translated because it should only be temporary.
val to = BuildConfig.FEEDBACK_EMAIL
val subject= "[MalformedURLException]"
val body= "Please specify the source, item and spout you are using for the url below : \n ${e.message}"
val mailTo = "mailto:" + to + "?&subject=" + Uri.encode(subject) + "&body=" + Uri.encode(body)
val emailIntent = Intent(Intent.ACTION_VIEW)
emailIntent.data = Uri.parse(mailTo)
startActivity(emailIntent)
dialog.dismiss()
}
)
alertDialog.setButton(
AlertDialog.BUTTON_NEUTRAL,
"Not now",
{ dialog, _ -> dialog.dismiss() }
)
alertDialog.setButton(
AlertDialog.BUTTON_NEGATIVE,
"Don't show anymore.",
{ dialog, _ ->
editor.putBoolean("show_error_malformed_url", false)
editor.apply()
dialog.dismiss()
}
)
alertDialog.show()
}
}
rootView.webcontent.loadDataWithBaseURL(
baseUrl,
"""<style>
|img {
| display: inline-block;
| height: auto;
| width: 100%;
| max-width: 100%;
|}
|a {
| color: $stringColor !important;
|}
|*:not(a) {
| color: $stringTextColor;
|}
|* {
| font-size: ${fontSize.toPx}px;
| text-align: justify;
| word-break: break-word;
| overflow:hidden;
|}
|a, pre, code {
| text-align: left;
|}
|pre, code {
| white-space: pre-wrap;
| width:100%;
| background-color: $stringBackgroundColor;
|}</style>$c""".trimMargin(),
"text/html; charset=utf-8", "text/html; charset=utf-8",
"utf-8" "utf-8",
null
) )
} }
@ -286,22 +432,21 @@ class ArticleFragment : Fragment() {
} }
companion object { companion object {
private val ARG_POSITION = "position" private const val ARG_POSITION = "position"
private val ARG_ITEMS = "items" private const val ARG_ITEMS = "items"
private val ARG_WEBVIEW = "userWebview"
fun newInstance( fun newInstance(
position: Int, position: Int,
allItems: ArrayList<Item>, allItems: ArrayList<Item>
webview: Boolean
): ArticleFragment { ): ArticleFragment {
val fragment = ArticleFragment() val fragment = ArticleFragment()
val args = Bundle() val args = Bundle()
args.putInt(ARG_POSITION, position) args.putInt(ARG_POSITION, position)
args.putBoolean(ARG_WEBVIEW, webview)
args.putParcelableArrayList(ARG_ITEMS, allItems) args.putParcelableArrayList(ARG_ITEMS, allItems)
fragment.arguments = args fragment.arguments = args
return fragment return fragment
} }
} }
} }

View File

@ -16,23 +16,27 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import apps.amine.bou.readerforselfoss.R;
import com.ftinc.scoop.Scoop; import com.ftinc.scoop.Scoop;
import apps.amine.bou.readerforselfoss.R;
import apps.amine.bou.readerforselfoss.themes.AppColors;
import apps.amine.bou.readerforselfoss.themes.Toppings;
/** /**
* A {@link PreferenceActivity} which implements and proxies the necessary calls * 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 { //NOSONAR public abstract class AppCompatPreferenceActivity extends PreferenceActivity {
private AppCompatDelegate mDelegate; private AppCompatDelegate mDelegate;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
new AppColors(this);
getDelegate().installViewFactory(); getDelegate().installViewFactory();
getDelegate().onCreate(savedInstanceState); getDelegate().onCreate(savedInstanceState);
Scoop.getInstance().apply(this);
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
} }
@ -43,6 +47,12 @@ public abstract class AppCompatPreferenceActivity extends PreferenceActivity { /
LinearLayout root = (LinearLayout) findViewById(android.R.id.list).getParent().getParent().getParent(); LinearLayout root = (LinearLayout) findViewById(android.R.id.list).getParent().getParent().getParent();
AppBarLayout bar = (AppBarLayout) LayoutInflater.from(this).inflate(R.layout.settings_toolbar, root, false); AppBarLayout bar = (AppBarLayout) LayoutInflater.from(this).inflate(R.layout.settings_toolbar, root, false);
Toolbar toolbar = bar.findViewById(R.id.toolbar); Toolbar toolbar = bar.findViewById(R.id.toolbar);
// TODO: all switches
Scoop.getInstance()
.bind(this, Toppings.PRIMARY.getValue(), toolbar)
.bindStatusBar(this, Toppings.PRIMARY_DARK.getValue());
setSupportActionBar(toolbar); setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true); getSupportActionBar().setDisplayShowHomeEnabled(true);

View File

@ -1,8 +1,6 @@
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;
@ -22,15 +20,23 @@ import android.preference.PreferenceFragment;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.preference.SwitchPreference; import android.preference.SwitchPreference;
import android.support.v7.app.ActionBar; import android.support.v7.app.ActionBar;
import android.text.Editable;
import android.text.InputFilter; import android.text.InputFilter;
import android.text.Spanned; import android.text.Spanned;
import android.text.TextWatcher;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem; import android.view.MenuItem;
import android.widget.Toast; import android.widget.Toast;
import com.ftinc.scoop.ui.ScoopSettingsActivity;
import java.util.List;
import apps.amine.bou.readerforselfoss.BuildConfig; import apps.amine.bou.readerforselfoss.BuildConfig;
import apps.amine.bou.readerforselfoss.R; import apps.amine.bou.readerforselfoss.R;
import apps.amine.bou.readerforselfoss.themes.AppColors;
import apps.amine.bou.readerforselfoss.utils.Config; import apps.amine.bou.readerforselfoss.utils.Config;
import com.ftinc.scoop.ui.ScoopSettingsActivity;
/** /**
@ -44,7 +50,7 @@ import com.ftinc.scoop.ui.ScoopSettingsActivity;
* href="http://developer.android.com/guide/topics/ui/settings.html">Settings * 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 { //NOSONAR public class SettingsActivity extends AppCompatPreferenceActivity {
/** /**
* 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.
@ -90,6 +96,7 @@ public class SettingsActivity extends AppCompatPreferenceActivity { //NOSONAR
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
new AppColors(this);
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setupActionBar(); setupActionBar();
} }
@ -130,8 +137,10 @@ public class SettingsActivity extends AppCompatPreferenceActivity { //NOSONAR
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)
|| ArticleViewerPreferenceFragment.class.getName().equals(fragmentName)
|| DebugPreferenceFragment.class.getName().equals(fragmentName) || DebugPreferenceFragment.class.getName().equals(fragmentName)
|| LinksPreferenceFragment.class.getName().equals(fragmentName); || LinksPreferenceFragment.class.getName().equals(fragmentName)
|| ThemePreferenceFragment.class.getName().equals(fragmentName);
} }
/** /**
@ -187,6 +196,56 @@ public class SettingsActivity extends AppCompatPreferenceActivity { //NOSONAR
} }
} }
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static class ArticleViewerPreferenceFragment extends PreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_viewer);
setHasOptionsMenu(true);
final EditTextPreference fontSize = (EditTextPreference) findPreference("reader_font_size");
fontSize.getEditText().addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
@Override
public void afterTextChanged(Editable editable) {
try {
fontSize.getEditText().setTextSize(Integer.parseInt(editable.toString()));
} catch (NumberFormatException e) {}
}
});
fontSize.getEditText().setFilters(new InputFilter[]{
new InputFilter() {
@Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
try {
int input = Integer.parseInt(dest.toString() + source.toString());
if (input > 0)
return null;
} catch (NumberFormatException nfe) {}
return "";
}
}
});
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
getActivity().finish();
return true;
}
return super.onOptionsItemSelected(item);
}
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB) @TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static class DebugPreferenceFragment extends PreferenceFragment { public static class DebugPreferenceFragment extends PreferenceFragment {
@Override @Override
@ -195,7 +254,7 @@ public class SettingsActivity extends AppCompatPreferenceActivity { //NOSONAR
addPreferencesFromResource(R.xml.pref_debug); addPreferencesFromResource(R.xml.pref_debug);
setHasOptionsMenu(true); setHasOptionsMenu(true);
SharedPreferences pref = getActivity().getSharedPreferences(Config.Companion.getSettingsName(), Context.MODE_PRIVATE); SharedPreferences pref = getActivity().getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE);
final String id = pref.getString("unique_id", "..."); final String id = pref.getString("unique_id", "...");
final Preference identifier = findPreference("debug_identifier"); final Preference identifier = findPreference("debug_identifier");
@ -205,12 +264,15 @@ public class SettingsActivity extends AppCompatPreferenceActivity { //NOSONAR
identifier.setOnPreferenceClickListener(new OnPreferenceClickListener() { identifier.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override @Override
public boolean onPreferenceClick(Preference preference) { public boolean onPreferenceClick(Preference preference) {
if (clipboard != null) {
ClipData clip = ClipData.newPlainText("Selfoss unique id", id); ClipData clip = ClipData.newPlainText("Selfoss unique id", id);
clipboard.setPrimaryClip(clip); clipboard.setPrimaryClip(clip);
Toast.makeText(getActivity(), R.string.unique_id_to_clipboard, Toast.LENGTH_LONG).show(); Toast.makeText(getActivity(), R.string.unique_id_to_clipboard, Toast.LENGTH_LONG).show();
return true; return true;
} }
return false;
}
}); });
identifier.setTitle(id); identifier.setTitle(id);
} }
@ -279,14 +341,38 @@ public class SettingsActivity extends AppCompatPreferenceActivity { //NOSONAR
} }
} }
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static class ThemePreferenceFragment extends PreferenceFragment {
@Override @Override
public void onHeaderClick(Header header, int position) { public void onCreate(Bundle savedInstanceState) {
super.onHeaderClick(header, position); super.onCreate(savedInstanceState);
if (header.id == R.id.theme_change) { addPreferencesFromResource(R.xml.pref_theme);
Intent intent = ScoopSettingsActivity.createIntent(getApplicationContext()); setHasOptionsMenu(true);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); }
getApplicationContext().startActivity(intent);
finish(); @Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
getActivity().finish();
return true;
} else if (id == R.id.clear) {
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(getActivity());
SharedPreferences.Editor editor = pref.edit();
editor.remove("color_primary");
editor.remove("color_primary_dark");
editor.remove("color_accent");
editor.remove("color_accent_dark");
editor.remove("dark_theme");
editor.apply();
getActivity().finish();
}
return super.onOptionsItemSelected(item);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.settings_theme, menu);
} }
} }

View File

@ -2,49 +2,65 @@ package apps.amine.bou.readerforselfoss.themes
import android.app.Activity import android.app.Activity
import android.content.Context import android.content.Context
import android.preference.PreferenceManager
import android.support.annotation.ColorInt import android.support.annotation.ColorInt
import android.support.v7.view.ContextThemeWrapper
import android.util.TypedValue import android.util.TypedValue
import apps.amine.bou.readerforselfoss.R import apps.amine.bou.readerforselfoss.R
import android.view.LayoutInflater
import android.view.ViewGroup
class AppColors(a: Activity) { class AppColors(a: Activity) {
@ColorInt val accent: Int
@ColorInt val dark: Int @ColorInt val colorPrimary: Int
@ColorInt val primary: Int @ColorInt val colorPrimaryDark: Int
@ColorInt val cardBackground: Int @ColorInt val colorAccent: Int
@ColorInt val windowBackground: Int @ColorInt val colorAccentDark: Int
@ColorInt val cardBackgroundColor: Int
val isDarkTheme: Boolean val isDarkTheme: Boolean
init { init {
val sharedPref = PreferenceManager.getDefaultSharedPreferences(a)
colorPrimary =
sharedPref.getInt(
"color_primary",
a.resources.getColor(R.color.colorPrimary)
)
colorPrimaryDark =
sharedPref.getInt(
"color_primary_dark",
a.resources.getColor(R.color.colorPrimaryDark)
)
colorAccent =
sharedPref.getInt(
"color_accent",
a.resources.getColor(R.color.colorAccent)
)
colorAccentDark =
sharedPref.getInt(
"color_accent_dark",
a.resources.getColor(R.color.colorAccentDark)
)
isDarkTheme =
sharedPref.getBoolean(
"dark_theme",
false
)
if (isDarkTheme) {
a.setTheme(R.style.NoBarDark)
} else {
a.setTheme(R.style.NoBar)
}
val wrapper = Context::class.java val wrapper = Context::class.java
val method = wrapper!!.getMethod("getThemeResId") val method = wrapper!!.getMethod("getThemeResId")
method.isAccessible = true method.isAccessible = true
isDarkTheme = when (method.invoke(a.baseContext)) {
R.style.NoBarTealOrangeDark,
R.style.NoBarDark,
R.style.NoBarBlueAmberDark,
R.style.NoBarGreyOrangeDark,
R.style.NoBarIndigoPinkDark,
R.style.NoBarRedTealDark,
R.style.NoBarCyanPinkDark -> true
else -> false
}
val typedAccent = TypedValue()
val typedAccentDark = TypedValue()
val typedPrimary = TypedValue()
val typedCardBackground = TypedValue() val typedCardBackground = TypedValue()
val typedWindowBackground = TypedValue()
a.theme.resolveAttribute(R.attr.colorAccent, typedAccent, true)
a.theme.resolveAttribute(R.attr.colorAccent, typedAccent, true)
a.theme.resolveAttribute(R.attr.colorPrimary, typedPrimary, true)
a.theme.resolveAttribute(R.attr.cardBackgroundColor, typedCardBackground, true) a.theme.resolveAttribute(R.attr.cardBackgroundColor, typedCardBackground, true)
a.theme.resolveAttribute(android.R.attr.colorBackground, typedWindowBackground, true)
accent = typedAccent.data cardBackgroundColor = typedCardBackground.data
dark = typedAccentDark.data
primary = typedPrimary.data
cardBackground = typedCardBackground.data
windowBackground = typedWindowBackground.data
} }
} }

View File

@ -0,0 +1,8 @@
package apps.amine.bou.readerforselfoss.themes
enum class Toppings(val value: Int) {
PRIMARY(1),
PRIMARY_DARK(2),
ACCENT(3),
ACCENT_DARK(4)
}

View File

@ -26,7 +26,7 @@ class Config(c: Context) {
get() = settings.getString("httpPassword", "") get() = settings.getString("httpPassword", "")
companion object { companion object {
val settingsName = "paramsselfoss" const val settingsName = "paramsselfoss"
fun logoutAndRedirect( fun logoutAndRedirect(
c: Context, c: Context,

View File

@ -7,7 +7,7 @@ import javax.net.ssl.SSLContext
import javax.net.ssl.TrustManager import javax.net.ssl.TrustManager
import javax.net.ssl.X509TrustManager import javax.net.ssl.X509TrustManager
fun getUnsafeHttpClient() = fun getUnsafeHttpClient(): OkHttpClient.Builder =
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 {

View File

@ -2,14 +2,24 @@ package apps.amine.bou.readerforselfoss.utils
import android.text.format.DateUtils import android.text.format.DateUtils
import apps.amine.bou.readerforselfoss.api.selfoss.Item import apps.amine.bou.readerforselfoss.api.selfoss.Item
import com.crashlytics.android.Crashlytics
import java.text.ParseException 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()).filter { !it.isEmpty() }.toTypedArray()) {
try {
textDrawable.append(s[0]) textDrawable.append(s[0])
} catch (e: StringIndexOutOfBoundsException) {
Crashlytics.log(
100,
"TEXT_DRAWABLE_INDEX_OUT_OF_BOUND",
this + " produces ${e.message}"
)
Crashlytics.logException(e)
}
} }
return textDrawable.toString() return textDrawable.toString()
} }
@ -29,3 +39,17 @@ fun Item.sourceAndDateText(): String {
return this.sourcetitle + formattedDate return this.sourcetitle + formattedDate
} }
fun Item.toggleStar(): Item {
this.starred = !this.starred
return this
}
fun List<Item>.flattenTags(): List<Item> =
this.flatMap {
val item = it
val tags: List<String> = it.tags.split(",")
tags.map {
item.copy(tags = it.trim())
}
}

View File

@ -11,6 +11,7 @@ class ScrollAwareFABBehavior(
attrs: AttributeSet attrs: AttributeSet
) : CoordinatorLayout.Behavior<FloatingActionButton>() { ) : CoordinatorLayout.Behavior<FloatingActionButton>() {
override fun onStartNestedScroll( override fun onStartNestedScroll(
coordinatorLayout: CoordinatorLayout, coordinatorLayout: CoordinatorLayout,
child: FloatingActionButton, child: FloatingActionButton,

View File

@ -0,0 +1,9 @@
package apps.amine.bou.readerforselfoss.utils
import android.content.res.Resources
val Int.toPx: Int
get() = (this * Resources.getSystem().displayMetrics.density).toInt()
val Int.toDp: Int
get() = (this / Resources.getSystem().displayMetrics.density).toInt()

View File

@ -1,8 +1,6 @@
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;
@ -11,6 +9,8 @@ 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.
*/ */
@ -48,6 +48,7 @@ public class CustomTabActivityHelper implements ServiceConnectionCallback {
/** /**
* Unbinds the Activity from the Custom Tabs Service. * Unbinds the Activity from the Custom Tabs Service.
*
* @param activity the activity that is connected to the service. * @param activity the activity that is connected to the service.
*/ */
public void unbindCustomTabsService(Activity activity) { public void unbindCustomTabsService(Activity activity) {
@ -74,6 +75,7 @@ public class CustomTabActivityHelper implements ServiceConnectionCallback {
/** /**
* Register a Callback to be called when connected or disconnected from the Custom Tabs Service. * Register a Callback to be called when connected or disconnected from the Custom Tabs Service.
*
* @param connectionCallback * @param connectionCallback
*/ */
public void setConnectionCallback(ConnectionCallback connectionCallback) { public void setConnectionCallback(ConnectionCallback connectionCallback) {
@ -82,6 +84,7 @@ public class CustomTabActivityHelper implements ServiceConnectionCallback {
/** /**
* Binds the Activity to the Custom Tabs Service. * Binds the Activity to the Custom Tabs Service.
*
* @param activity the activity to be binded to the service. * @param activity the activity to be binded to the service.
*/ */
public void bindCustomTabsService(Activity activity) { public void bindCustomTabsService(Activity activity) {
@ -95,16 +98,15 @@ public class CustomTabActivityHelper implements ServiceConnectionCallback {
} }
/** /**
* @see {@link CustomTabsSession#mayLaunchUrl(Uri, Bundle, List)}.
* @return true if call to mayLaunchUrl was accepted. * @return true if call to mayLaunchUrl was accepted.
* @see {@link CustomTabsSession#mayLaunchUrl(Uri, Bundle, List)}.
*/ */
public boolean mayLaunchUrl(Uri uri, Bundle extras, List<Bundle> otherLikelyBundles) { public boolean mayLaunchUrl(Uri uri, Bundle extras, List<Bundle> otherLikelyBundles) {
if (mClient == null) return false; if (mClient == null) return false;
CustomTabsSession session = getSession(); CustomTabsSession session = getSession();
if (session == null) return false; return session != null && session.mayLaunchUrl(uri, extras, otherLikelyBundles);
return session.mayLaunchUrl(uri, extras, otherLikelyBundles);
} }
@Override @Override
@ -142,7 +144,6 @@ public class CustomTabActivityHelper implements ServiceConnectionCallback {
*/ */
public interface CustomTabFallback { public interface CustomTabFallback {
/** /**
*
* @param activity The Activity that wants to open the Uri. * @param activity The Activity that wants to open the Uri.
* @param uri The uri to be opened by the fallback. * @param uri The uri to be opened by the fallback.
*/ */

View File

@ -1,9 +1,6 @@
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;
@ -14,6 +11,9 @@ import android.support.customtabs.CustomTabsService;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import java.util.ArrayList;
import java.util.List;
import apps.amine.bou.readerforselfoss.utils.customtabs.helpers.KeepAliveService; import apps.amine.bou.readerforselfoss.utils.customtabs.helpers.KeepAliveService;
@SuppressWarnings("ALL") @SuppressWarnings("ALL")
@ -28,7 +28,8 @@ class CustomTabsHelper {
private static String sPackageNameToUse; private static String sPackageNameToUse;
private CustomTabsHelper() {} private CustomTabsHelper() {
}
public static void addKeepAliveExtra(Context context, Intent intent) { public static void addKeepAliveExtra(Context context, Intent intent) {
Intent keepAliveIntent = new Intent().setClassName( Intent keepAliveIntent = new Intent().setClassName(
@ -40,7 +41,7 @@ class CustomTabsHelper {
* Goes through all apps that handle VIEW intents and have a warmup service. Picks * Goes through all apps that handle VIEW intents and have a warmup service. Picks
* the one chosen by the user if there is one, otherwise makes a best effort to return a * the one chosen by the user if there is one, otherwise makes a best effort to return a
* valid package name. * valid package name.
* * <p>
* This is <strong>not</strong> threadsafe. * This is <strong>not</strong> threadsafe.
* *
* @param context {@link Context} to use for accessing {@link PackageManager}. * @param context {@link Context} to use for accessing {@link PackageManager}.
@ -94,6 +95,7 @@ class CustomTabsHelper {
/** /**
* Used to check whether there is a specialized handler for a given intent. * Used to check whether there is a specialized handler for a given intent.
*
* @param intent The intent to check with. * @param intent The intent to check with.
* @return Whether there is a specialized handler for the given intent. * @return Whether there is a specialized handler for the given intent.
*/ */

View File

@ -1,12 +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

View File

@ -7,6 +7,7 @@ import android.support.customtabs.CustomTabsClient;
public interface ServiceConnectionCallback { public interface ServiceConnectionCallback {
/** /**
* Called when the service is connected. * Called when the service is connected.
*
* @param client a CustomTabsClient * @param client a CustomTabsClient
*/ */
void onServiceConnected(CustomTabsClient client); void onServiceConnected(CustomTabsClient client);

View File

@ -15,7 +15,8 @@ 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)
return this as T return this as T

View File

@ -10,7 +10,9 @@ 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
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()

Binary file not shown.

After

Width:  |  Height:  |  Size: 206 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 551 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 352 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 684 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 255 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 986 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 311 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -1,12 +1,15 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout <ScrollView xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:app="http://schemas.android.com/apk/res-auto"
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"
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.AddSourceActivity" tools:context="apps.amine.bou.readerforselfoss.AddSourceActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"> android:orientation="vertical">
<android.support.design.widget.AppBarLayout <android.support.design.widget.AppBarLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
@ -21,16 +24,14 @@
</android.support.design.widget.AppBarLayout> </android.support.design.widget.AppBarLayout>
<android.support.constraint.ConstraintLayout <android.support.constraint.ConstraintLayout
android:paddingBottom="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin" android:paddingTop="@dimen/activity_vertical_margin"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_width="match_parent">
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
@ -119,19 +120,20 @@
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginBottom="16dp" android:layout_marginBottom="16dp"
app:layout_constraintVertical_bias="0.0"/> app:layout_constraintVertical_bias="0.0"/>
</android.support.constraint.ConstraintLayout> </android.support.constraint.ConstraintLayout>
<ProgressBar <ProgressBar
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/progress" android:id="@+id/progress"
app:layout_constraintTop_toTopOf="parent" style="?android:attr/progressBarStyleLarge"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintTop_toTopOf="parent"
android:visibility="visible"/> tools:visibility="gone" />
</android.support.constraint.ConstraintLayout>
</LinearLayout> </LinearLayout>
</ScrollView>

View File

@ -88,12 +88,14 @@
android:textAppearance="@style/TextAppearance.AppCompat.Headline" android:textAppearance="@style/TextAppearance.AppCompat.Headline"
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/recyclerView" 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"
android:clipToPadding="false" android:clipToPadding="false"
android:paddingBottom="60dp"
android:scrollbars="vertical" android:scrollbars="vertical"
app:layout_behavior="@string/appbar_scrolling_view_behavior" /> app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</LinearLayout> </LinearLayout>

View File

@ -115,6 +115,7 @@
android:visibility="gone"> android:visibility="gone">
<EditText <EditText
android:inputType="text"
android:id="@+id/httpLoginView" android:id="@+id/httpLoginView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"

View File

@ -1,7 +1,6 @@
<?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.constraint.ConstraintLayout 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"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
@ -26,6 +25,7 @@
android:id="@+id/pager" android:id="@+id/pager"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="0dp"
android:paddingTop="20dp"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
@ -37,8 +37,8 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="20dp" android:layout_height="20dp"
android:background="#55000000" android:background="#55000000"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.0" app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" /> app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="@+id/pager" />
</android.support.constraint.ConstraintLayout> </android.support.constraint.ConstraintLayout>

View File

@ -1,13 +1,11 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout <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"
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.SourcesActivity" tools:context="apps.amine.bou.readerforselfoss.SourcesActivity">
xmlns:fab="http://schemas.android.com/apk/res-auto">
<android.support.design.widget.AppBarLayout <android.support.design.widget.AppBarLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">

View File

@ -70,20 +70,6 @@
app:layout_constraintTop_toBottomOf="@+id/source" app:layout_constraintTop_toBottomOf="@+id/source"
tools:visibility="visible" /> tools:visibility="visible" />
<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"
android:visibility="gone"/>
</android.support.constraint.ConstraintLayout> </android.support.constraint.ConstraintLayout>
</android.support.v4.widget.NestedScrollView> </android.support.v4.widget.NestedScrollView>
@ -101,16 +87,12 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize" android:layout_height="?attr/actionBarSize"
android:layout_gravity="bottom" android:layout_gravity="bottom"
app:floatingItemBackground="?attr/colorAccent"
app:floatingMenu="@menu/reader_toolbar" /> app:floatingMenu="@menu/reader_toolbar" />
<android.support.design.widget.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_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_gravity="end|bottom|right" android:layout_gravity="end|bottom|right"
android:layout_marginBottom="16dp" android:layout_marginBottom="16dp"
android:layout_marginEnd="16dp" android:layout_marginEnd="16dp"

View File

@ -7,18 +7,11 @@
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"
app:layout_constraintBottom_toTopOf="@+id/guideline4" app:layout_constraintBottom_toBottomOf="@+id/actionBar"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
@ -26,24 +19,21 @@
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_marginStart="16dp" android:layout_marginStart="16dp"
android:layout_marginTop="16dp" android:layout_marginTop="8dp"
android:ellipsize="end"
android:fontFamily="sans-serif" android:fontFamily="sans-serif"
android:gravity="start" android:gravity="start"
android:maxLines="3" 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_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0" app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toEndOf="@+id/itemImage" app:layout_constraintStart_toEndOf="@+id/itemImage"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0"
tools:text="Titre" /> tools:text="Titre" />
<TextView <TextView
@ -53,13 +43,15 @@
android:layout_marginBottom="8dp" android:layout_marginBottom="8dp"
android:layout_marginEnd="16dp" android:layout_marginEnd="16dp"
android:layout_marginStart="16dp" android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:gravity="start" android:gravity="start"
android:textAlignment="viewStart" android:textAlignment="viewStart"
android:textSize="14sp" android:textSize="14sp"
app:layout_constraintBottom_toTopOf="@+id/guideline4" app:layout_constraintBottom_toBottomOf="@+id/actionBar"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0" app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toEndOf="@+id/itemImage" app:layout_constraintStart_toEndOf="@+id/itemImage"
app:layout_constraintTop_toBottomOf="@+id/title"
tools:text="Google Actualité Il y a 5h" /> tools:text="Google Actualité Il y a 5h" />
<RelativeLayout <RelativeLayout
@ -71,8 +63,6 @@
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/guideline4"
app:layout_constraintVertical_bias="1.0"
tools:visibility="visible"> tools:visibility="visible">
<com.like.LikeButton <com.like.LikeButton

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/unsave"
android:icon="@drawable/heart_on"
android:title="@string/remove_to_favs_reader"
android:visible="true"
app:showAsAction="ifRoom" />
<item
android:id="@+id/save"
android:icon="@drawable/heart_off"
android:title="@string/add_to_favs_reader"
android:visible="true"
app:showAsAction="ifRoom" />
</menu>

View File

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<menu xmlns:tools="http://schemas.android.com/tools" <menu 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">
<item <item

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/clear"
android:icon="@drawable/ic_history"
android:title="@string/drawer_action_clear"
app:showAsAction="ifRoom" />
</menu>

View File

@ -158,8 +158,13 @@
<string name="reader_action_more">Read more</string> <string name="reader_action_more">Read more</string>
<string name="reader_action_open">Open in browser</string> <string name="reader_action_open">Open in browser</string>
<string name="reader_action_share">Share</string> <string name="reader_action_share">Share</string>
<string name="pref_switch_actions_pager_scroll">Mark articles as read when swiping between articles.</string> <string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
<string name="prefer_webview_in_article_viewer_title">Use a webview in the article viewer.</string> <string name="add_to_favs_reader">Add to favorites</string>
<string name="prefer_webview_in_article_viewer_on">Using the webview for the content of the article viewer. Urls, gifs and images will be better handled, but may be slower.</string> <string name="remove_to_favs_reader">Remove from favorites</string>
<string name="prefer_webview_in_article_viewer_off">The content of the article will be displayed as simple text with links and images. Urls may not work, and gifs won\'t load.</string> <string name="pref_content_reader_font_size">Article reader content font size</string>
<string name="pref_header_viewer">Article viewer</string>
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
<string name="markall_dialog_message">This will mark all the items as read.</string>
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
</resources> </resources>

View File

@ -158,8 +158,13 @@
<string name="reader_action_more">Read more</string> <string name="reader_action_more">Read more</string>
<string name="reader_action_open">Open in browser</string> <string name="reader_action_open">Open in browser</string>
<string name="reader_action_share">Share</string> <string name="reader_action_share">Share</string>
<string name="pref_switch_actions_pager_scroll">Mark articles as read when swiping between articles.</string> <string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
<string name="prefer_webview_in_article_viewer_title">Use a webview in the article viewer.</string> <string name="add_to_favs_reader">Add to favorites</string>
<string name="prefer_webview_in_article_viewer_on">Using the webview for the content of the article viewer. Urls, gifs and images will be better handled, but may be slower.</string> <string name="remove_to_favs_reader">Remove from favorites</string>
<string name="prefer_webview_in_article_viewer_off">The content of the article will be displayed as simple text with links and images. Urls may not work, and gifs won\'t load.</string> <string name="pref_content_reader_font_size">Article reader content font size</string>
<string name="pref_header_viewer">Article viewer</string>
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
<string name="markall_dialog_message">This will mark all the items as read.</string>
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
</resources> </resources>

View File

@ -158,8 +158,13 @@
<string name="reader_action_more">Read more</string> <string name="reader_action_more">Read more</string>
<string name="reader_action_open">Open in browser</string> <string name="reader_action_open">Open in browser</string>
<string name="reader_action_share">Share</string> <string name="reader_action_share">Share</string>
<string name="pref_switch_actions_pager_scroll">Mark articles as read when swiping between articles.</string> <string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
<string name="prefer_webview_in_article_viewer_title">Use a webview in the article viewer.</string> <string name="add_to_favs_reader">Add to favorites</string>
<string name="prefer_webview_in_article_viewer_on">Using the webview for the content of the article viewer. Urls, gifs and images will be better handled, but may be slower.</string> <string name="remove_to_favs_reader">Remove from favorites</string>
<string name="prefer_webview_in_article_viewer_off">The content of the article will be displayed as simple text with links and images. Urls may not work, and gifs won\'t load.</string> <string name="pref_content_reader_font_size">Article reader content font size</string>
<string name="pref_header_viewer">Article viewer</string>
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
<string name="markall_dialog_message">This will mark all the items as read.</string>
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
</resources> </resources>

View File

@ -158,8 +158,13 @@
<string name="reader_action_more">Read more</string> <string name="reader_action_more">Read more</string>
<string name="reader_action_open">Open in browser</string> <string name="reader_action_open">Open in browser</string>
<string name="reader_action_share">Share</string> <string name="reader_action_share">Share</string>
<string name="pref_switch_actions_pager_scroll">Mark articles as read when swiping between articles.</string> <string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
<string name="prefer_webview_in_article_viewer_title">Use a webview in the article viewer.</string> <string name="add_to_favs_reader">Add to favorites</string>
<string name="prefer_webview_in_article_viewer_on">Using the webview for the content of the article viewer. Urls, gifs and images will be better handled, but may be slower.</string> <string name="remove_to_favs_reader">Remove from favorites</string>
<string name="prefer_webview_in_article_viewer_off">The content of the article will be displayed as simple text with links and images. Urls may not work, and gifs won\'t load.</string> <string name="pref_content_reader_font_size">Article reader content font size</string>
<string name="pref_header_viewer">Article viewer</string>
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
<string name="markall_dialog_message">This will mark all the items as read.</string>
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
</resources> </resources>

View File

@ -158,8 +158,13 @@
<string name="reader_action_more">Read more</string> <string name="reader_action_more">Read more</string>
<string name="reader_action_open">Open in browser</string> <string name="reader_action_open">Open in browser</string>
<string name="reader_action_share">Share</string> <string name="reader_action_share">Share</string>
<string name="pref_switch_actions_pager_scroll">Mark articles as read when swiping between articles.</string> <string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
<string name="prefer_webview_in_article_viewer_title">Use a webview in the article viewer.</string> <string name="add_to_favs_reader">Add to favorites</string>
<string name="prefer_webview_in_article_viewer_on">Using the webview for the content of the article viewer. Urls, gifs and images will be better handled, but may be slower.</string> <string name="remove_to_favs_reader">Remove from favorites</string>
<string name="prefer_webview_in_article_viewer_off">The content of the article will be displayed as simple text with links and images. Urls may not work, and gifs won\'t load.</string> <string name="pref_content_reader_font_size">Article reader content font size</string>
<string name="pref_header_viewer">Article viewer</string>
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
<string name="markall_dialog_message">This will mark all the items as read.</string>
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
</resources> </resources>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!--Generated by crowdin.com--> <!--Generated by crowdin.com-->
<resources xmlns:tools="http://schemas.android.com/tools"> <resources xmlns:tools="http://schemas.android.com/tools">
<string name="app_name">"Reader für Selfoss"</string> <string name="app_name">"Reader für selfoss"</string>
<string name="title_activity_login">"Anmelden"</string> <string name="title_activity_login">"Anmelden"</string>
<string name="prompt_password">"Passwort"</string> <string name="prompt_password">"Passwort"</string>
<string name="prompt_http_password">"HTTP Passwort"</string> <string name="prompt_http_password">"HTTP Passwort"</string>
@ -33,7 +33,7 @@
<string name="cant_get_read">"Gelese Artikel können nicht abgerufen werden"</string> <string name="cant_get_read">"Gelese Artikel können nicht abgerufen werden"</string>
<string name="nothing_here">"Keine Einträge vorhanden"</string> <string name="nothing_here">"Keine Einträge vorhanden"</string>
<string name="tab_new">"Neu"</string> <string name="tab_new">"Neu"</string>
<string name="tab_read">"All"</string> <string name="tab_read">"Alle"</string>
<string name="tab_favs">"Favoriten"</string> <string name="tab_favs">"Favoriten"</string>
<string name="action_about">"Über"</string> <string name="action_about">"Über"</string>
<string name="marked_as_read">"Artikel gelesen"</string> <string name="marked_as_read">"Artikel gelesen"</string>
@ -138,7 +138,7 @@
<string name="login_menu_debug">Debug</string> <string name="login_menu_debug">Debug</string>
<string name="self_hosted_cert_switch">Verwenden Sie einen selbst gehostetes Zertifikat?</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="self_signed_cert_warning">Due to security reasons, self signed certificates are not supported by default. By activating this, I\'ll not be responsible of any security problem you encounter.</string>
<string name="pref_selfoss_category">Selfoss Api</string> <string name="pref_selfoss_category">selfoss API</string>
<string name="pref_api_items_number_title">Loaded items number</string> <string name="pref_api_items_number_title">Loaded items number</string>
<string name="read_debug_title">Read articles appearing as unread ?</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_off">No log when marking an item as read</string>
@ -153,13 +153,18 @@
<string name="pref_general_infinite_loading_title">Load more articles on scroll</string> <string name="pref_general_infinite_loading_title">Load more articles on scroll</string>
<string name="translation">Übersetzung</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="cant_open_invalid_url">The item url is invalid. I\'m looking into solving this issue so the app won\'t crash.</string>
<string name="drawer_report_bug">Report a bug</string> <string name="drawer_report_bug">Melde einen Fehler</string>
<string name="items_number_should_be_number">The items number should be an integer.</string> <string name="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_more">Read more</string>
<string name="reader_action_open">Open in browser</string> <string name="reader_action_open">Im Browser öffnen</string>
<string name="reader_action_share">Share</string> <string name="reader_action_share">Teilen</string>
<string name="pref_switch_actions_pager_scroll">Mark articles as read when swiping between articles.</string> <string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
<string name="prefer_webview_in_article_viewer_title">Use a webview in the article viewer.</string> <string name="add_to_favs_reader">Zu Favoriten hinzufügen</string>
<string name="prefer_webview_in_article_viewer_on">Using the webview for the content of the article viewer. Urls, gifs and images will be better handled, but may be slower.</string> <string name="remove_to_favs_reader">Remove from favorites</string>
<string name="prefer_webview_in_article_viewer_off">The content of the article will be displayed as simple text with links and images. Urls may not work, and gifs won\'t load.</string> <string name="pref_content_reader_font_size">Article reader content font size</string>
<string name="pref_header_viewer">Article viewer</string>
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
<string name="markall_dialog_message">This will mark all the items as read.</string>
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
</resources> </resources>

View File

@ -158,8 +158,13 @@
<string name="reader_action_more">Read more</string> <string name="reader_action_more">Read more</string>
<string name="reader_action_open">Open in browser</string> <string name="reader_action_open">Open in browser</string>
<string name="reader_action_share">Share</string> <string name="reader_action_share">Share</string>
<string name="pref_switch_actions_pager_scroll">Mark articles as read when swiping between articles.</string> <string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
<string name="prefer_webview_in_article_viewer_title">Use a webview in the article viewer.</string> <string name="add_to_favs_reader">Add to favorites</string>
<string name="prefer_webview_in_article_viewer_on">Using the webview for the content of the article viewer. Urls, gifs and images will be better handled, but may be slower.</string> <string name="remove_to_favs_reader">Remove from favorites</string>
<string name="prefer_webview_in_article_viewer_off">The content of the article will be displayed as simple text with links and images. Urls may not work, and gifs won\'t load.</string> <string name="pref_content_reader_font_size">Article reader content font size</string>
<string name="pref_header_viewer">Article viewer</string>
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
<string name="markall_dialog_message">This will mark all the items as read.</string>
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
</resources> </resources>

View File

@ -1,165 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--Generated by crowdin.com-->
<resources xmlns:tools="http://schemas.android.com/tools">
<string name="app_name">"Reader for Selfoss"</string>
<string name="title_activity_login">"Log in"</string>
<string name="prompt_password">"Password"</string>
<string name="prompt_http_password">"HTTP Password"</string>
<string name="action_sign_in">"Go"</string>
<string name="error_invalid_password">"Password not long enough"</string>
<string name="error_field_required">"Field required"</string>
<string name="prompt_url">"Url"</string>
<string name="withLoginSwitch">"Login required ?"</string>
<string name="withHttpLoginSwitch">"HTTP Login required ?"</string>
<string name="login_url_problem">"Oops. You may need to add a \"/\" at the end of the url."</string>
<string name="prompt_login">"Username"</string>
<string name="prompt_http_login">"HTTP Username"</string>
<string name="label_share">"Share"</string>
<string name="readAll">"Read all"</string>
<string name="action_disconnect">"Disconnect"</string>
<string name="title_activity_settings">"Settings"</string>
<string name="pref_header_general">"General"</string>
<string name="pref_switch_actions_tap_title">"Tap action on the articles"</string>
<string name="add_source_hint_tags">"Tag1, Tag2, Tag3"</string>
<string name="add_source_hint_url">"Link"</string>
<string name="add_source_hint_name">"Name"</string>
<string name="add_source">"Add a source"</string>
<string name="add_source_save">"Save"</string>
<string name="wrong_infos">"Check your details again."</string>
<string name="all_posts_not_read">"All posts weren't read"</string>
<string name="all_posts_read">"All posts were read"</string>
<string name="cant_get_favs">"Can't get favorites"</string>
<string name="cant_get_new_elements">"Can't get new articles"</string>
<string name="cant_get_read">"Can't get read articles"</string>
<string name="nothing_here">"Nothing here"</string>
<string name="tab_new">"New"</string>
<string name="tab_read">"All"</string>
<string name="tab_favs">"Favorites"</string>
<string name="action_about">"About"</string>
<string name="marked_as_read">"Item read"</string>
<string name="undo_string">"Undo"</string>
<string name="addStringNoUrl">"Log in to add sources."</string>
<string name="cant_get_sources">"Can't get sources list."</string>
<string name="cant_create_source">"Can't create source."</string>
<string name="cant_get_spouts">"Can't get spouts list."</string>
<string name="form_not_complete">"The form is not complete"</string>
<string name="pref_header_links">"Links"</string>
<string name="issue_tracker_link">"Issue Tracker"</string>
<string name="issue_tracker_summary">"Report a bug or ask for a new feature"</string>
<string name="warning_wrong_url">"WARNING"</string>
<string name="pref_switch_card_view_title">"Card View"</string>
<string name="cant_mark_favortie">"Can't mark article as favorite"</string>
<string name="cant_unmark_favortie">"Can't remove item from favorite"</string>
<string name="share">"Share"</string>
<string name="rating_prompt_title">"Enjoying the app ?"</string>
<string name="rating_prompt_yes">"Yes !"</string>
<string name="rating_prompt_no">"Not really …"</string>
<string name="rating_prompt_feedback_title">"Can you tell us why ?"</string>
<string name="rating_prompt_feedback_yes">"OK !"</string>
<string name="rating_prompt_feedback_no">"Not now."</string>
<string name="rating_prompt_rating_title">"Great ! Can you rate us on the Store ?"</string>
<string name="rating_prompt_rating_yes">"Sure !"</string>
<string name="rating_prompt_rating_no">"Not right now."</string>
<string name="rating_prompt_thanks">"Thanks, your feedback help enhance the app !"</string>
<string name="switch_unread_count">"Display the unread count as a badge for the bottom bar."</string>
<string name="switch_unread_count_title">"Display unread count"</string>
<string name="display_all_counts_title">"Display count for favorite and read"</string>
<string name="menu_share_the_app">"Invite friends"</string>
<string name="invitation_title">"Try this app for your Selfoss RSS feeds !"</string>
<string name="invitation_message">"I use this app for my Selfoss RSS feeds. You may like it too !"</string>
<string name="invitation_cta">"Try the app"</string>
<string name="text_wrong_url">"You seem to be trying to use an invalid URL. Make sure it is correct, and if the problem persists, contact me (via the store contact link). Please note that the app needs you to be using Selfoss. You can't access RSS feeds without it."</string>
<string name="pref_general_internal_browser_title">"Open links inside the app"</string>
<string name="pref_general_internal_browser_on">"Articles will open inside the app"</string>
<string name="pref_general_internal_browser_off">"Articles will open with your default browser"</string>
<string name="prefer_article_viewer_title">"Use the article viewer"</string>
<string name="prefer_article_viewer_on">"Will use the article viewer instead of the internal browser"</string>
<string name="prefer_article_viewer_off">"Will use the internal browser instead of the article viewer"</string>
<string name="pref_general_category_links">"Link handling"</string>
<string name="pref_general_category_displaying">"Displaying"</string>
<string name="pref_general_category_actions">"Actions"</string>
<string name="pref_switch_card_view_on">"The articles will be displayed as cards"</string>
<string name="pref_switch_card_view_off">"The articles will be displayed as a list"</string>
<string name="pref_switch_actions_tap_on">"Displays the action bar under the article"</string>
<string name="pref_switch_actions_tap_off">"When selecting an article it will open in your selected browser"</string>
<string name="menu_home_refresh">"Update remote"</string>
<string name="refresh_success_response">"The remote is updated, you can now reload the articles list"</string>
<string name="refresh_failer_message">"The update didn't work, try again later, or check your selfoss logs."</string>
<string name="refresh_in_progress">"Refresh in progress"</string>
<string name="new_apk_available_title">"A new APK is available."</string>
<string name="new_apk_available_message">"A new APK is available to download on the official repository."</string>
<string name="new_apk_available_get">"Download now"</string>
<string name="new_apk_available_no">"Ignore version"</string>
<string name="intro_hello_title">"Hi there !"</string>
<string name="intro_hello_message">"Thanks for downloading the app !"</string>
<string name="intro_needs_selfoss_title">"Before you start…"</string>
<string name="intro_needs_selfoss_message">"You can't use the app without a Selfoss instance."</string>
<string name="intro_needs_selfoss_link">"What is Selfoss ?"</string>
<string name="intro_all_set_title">"All set !"</string>
<string name="intro_all_set_message">"You are ready to use the app. Don't forget to go to the settings page to configure your app, and where you'll find some useful links."</string>
<string name="card_height_title">Full height cards</string>
<string name="card_height_on">Cards height will adjust to its content</string>
<string name="card_height_off">Card height will be fixed</string>
<string name="source_code">Source code</string>
<string name="cant_mark_read">Can\'t mark article as read</string>
<string name="drawer_error_loading_tags">Error loading tags…</string>
<string name="drawer_error_loading_sources">Error loading sources…</string>
<string name="drawer_item_filters">Filters</string>
<string name="drawer_action_clear">clear</string>
<string name="drawer_item_tags">Tags</string>
<string name="drawer_item_sources">Sources</string>
<string name="drawer_action_edit">edit</string>
<string name="cache_drawer_error" tools:keep="@string/cache_drawer_error">Couldn\'t cache your drawer data</string>
<string name="no_tags_loaded">No tags loaded</string>
<string name="no_sources_loaded">No sources loaded</string>
<string name="drawer_loading">Loading …</string>
<string name="menu_home_search">Search</string>
<string name="can_delete_source">Can\'t delete the source…</string>
<string name="base_url_error">There was an issue when trying to communicate with your Selfoss Instance. If the issue persists, please get in touch with me.</string>
<string name="pref_header_theme">Themes</string>
<string name="default_theme">Default</string>
<string name="teal_orange_theme">Teal/Orange/Light</string>
<string name="cyan_pink_theme">Cyan/Pink/Light</string>
<string name="grey_orange_theme">Grey/Orange/Light</string>
<string name="blue_amber_theme">Blue/Amber/Light</string>
<string name="indigo_pink_theme">Indigo/Pink/Light</string>
<string name="red_teal_theme">Red/Teal/Light</string>
<string name="teal_orange_dark_theme">Teal/Orange/Dark</string>
<string name="cyan_pink_dark_theme">Cyan/Pink/Dark</string>
<string name="default_dark_theme">Default/Dark</string>
<string name="grey_orange_dark_theme">Grey/Orange/Dark</string>
<string name="blue_amber_dark_theme">Blue/Amber/Dark</string>
<string name="indigo_pink_dark_theme">Indigo/Pink/Dark</string>
<string name="red_teal_dark_theme">Red/Teal/Dark</string>
<string name="pref_header_debug">Debug</string>
<string name="login_debug_title">Activate to log login errors</string>
<string name="login_debug_on">Any error on the login page will be logged</string>
<string name="login_debug_off">No log on the login page</string>
<string name="login_menu_debug">Debug</string>
<string name="self_hosted_cert_switch">Using a self hosted certificate ?</string>
<string name="self_signed_cert_warning">Due to security reasons, self signed certificates are not supported by default. By activating this, I\'ll not be responsible of any security problem you encounter.</string>
<string name="pref_selfoss_category">Selfoss Api</string>
<string name="pref_api_items_number_title">Loaded items number</string>
<string name="read_debug_title">Read articles appearing as unread ?</string>
<string name="read_debug_off">No log when marking an item as read</string>
<string name="read_debug_on">Api calls will be logged when marking an article as read</string>
<string name="summary_debug_identifier">Debug identifier</string>
<string name="unique_id_to_clipboard">Identifier copied to your clipboard</string>
<string name="display_header_drawer_summary">Display a header with the selfoss instance url on the lateral drawer.</string>
<string name="display_header_drawer_title">Account header</string>
<string name="login_everything_title">Logging every api calls</string>
<string name="login_everything_on">This will log every api call for debug purpose.</string>
<string name="login_everything_off">No api call will be logged</string>
<string name="pref_general_infinite_loading_title">Load more articles on scroll</string>
<string name="translation">Translation</string>
<string name="cant_open_invalid_url">The item url is invalid. I\'m looking into solving this issue so the app won\'t crash.</string>
<string name="drawer_report_bug">Report a bug</string>
<string name="items_number_should_be_number">The items number should be an integer.</string>
<string name="reader_action_more">Read more</string>
<string name="reader_action_open">Open in browser</string>
<string name="reader_action_share">Share</string>
<string name="pref_switch_actions_pager_scroll">Mark articles as read when swiping between articles.</string>
<string name="prefer_webview_in_article_viewer_title">Use a webview in the article viewer.</string>
<string name="prefer_webview_in_article_viewer_on">Using the webview for the content of the article viewer. Urls, gifs and images will be better handled, but may be slower.</string>
<string name="prefer_webview_in_article_viewer_off">The content of the article will be displayed as simple text with links and images. Urls may not work, and gifs won\'t load.</string>
</resources>

View File

@ -158,8 +158,13 @@
<string name="reader_action_more">Leer más</string> <string name="reader_action_more">Leer más</string>
<string name="reader_action_open">Abrir en el navegador</string> <string name="reader_action_open">Abrir en el navegador</string>
<string name="reader_action_share">Compartir</string> <string name="reader_action_share">Compartir</string>
<string name="pref_switch_actions_pager_scroll">Mark articles as read when swiping between articles.</string> <string name="pref_switch_actions_pager_scroll_on">Marcar artículos como leidos al desplazarse entre ellos.</string>
<string name="prefer_webview_in_article_viewer_title">Use a webview in the article viewer.</string> <string name="add_to_favs_reader">Añadir a Favoritos</string>
<string name="prefer_webview_in_article_viewer_on">Using the webview for the content of the article viewer. Urls, gifs and images will be better handled, but may be slower.</string> <string name="remove_to_favs_reader">Eliminar de favoritos</string>
<string name="prefer_webview_in_article_viewer_off">The content of the article will be displayed as simple text with links and images. Urls may not work, and gifs won\'t load.</string> <string name="pref_content_reader_font_size">Tamaño de la fuente</string>
<string name="pref_header_viewer">Visor de artículos</string>
<string name="refresh_dialog_message">Esto actualizará su instancia de Selfoss.</string>
<string name="markall_dialog_message">Esto marcará todos los artículos como leídos.</string>
<string name="pref_switch_actions_pager_scroll">Marcar como leído al arrastrar</string>
<string name="pref_switch_actions_pager_scroll_off">No marca artículos como leídos al arrastrar.</string>
</resources> </resources>

View File

@ -158,8 +158,13 @@
<string name="reader_action_more">Read more</string> <string name="reader_action_more">Read more</string>
<string name="reader_action_open">Open in browser</string> <string name="reader_action_open">Open in browser</string>
<string name="reader_action_share">Share</string> <string name="reader_action_share">Share</string>
<string name="pref_switch_actions_pager_scroll">Mark articles as read when swiping between articles.</string> <string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
<string name="prefer_webview_in_article_viewer_title">Use a webview in the article viewer.</string> <string name="add_to_favs_reader">Add to favorites</string>
<string name="prefer_webview_in_article_viewer_on">Using the webview for the content of the article viewer. Urls, gifs and images will be better handled, but may be slower.</string> <string name="remove_to_favs_reader">Remove from favorites</string>
<string name="prefer_webview_in_article_viewer_off">The content of the article will be displayed as simple text with links and images. Urls may not work, and gifs won\'t load.</string> <string name="pref_content_reader_font_size">Article reader content font size</string>
<string name="pref_header_viewer">Article viewer</string>
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
<string name="markall_dialog_message">This will mark all the items as read.</string>
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
</resources> </resources>

View File

@ -43,8 +43,8 @@
<string name="cant_create_source">"Impossible de créer la source."</string> <string name="cant_create_source">"Impossible de créer la source."</string>
<string name="cant_get_spouts">"Impossible de récupérer vos Spouts pour rajouter des sources"</string> <string name="cant_get_spouts">"Impossible de récupérer vos Spouts pour rajouter des sources"</string>
<string name="form_not_complete">"Il manque des données. Terminez le formulaire."</string> <string name="form_not_complete">"Il manque des données. Terminez le formulaire."</string>
<string name="pref_header_links">"Liens utils"</string> <string name="pref_header_links">"Liens utiles"</string>
<string name="issue_tracker_link">"Suivie des problèmes"</string> <string name="issue_tracker_link">"Suivi des problèmes"</string>
<string name="issue_tracker_summary">"Pour signaler un bug ou demander une nouvelle fonctionnalité"</string> <string name="issue_tracker_summary">"Pour signaler un bug ou demander une nouvelle fonctionnalité"</string>
<string name="warning_wrong_url">"ATTENTION"</string> <string name="warning_wrong_url">"ATTENTION"</string>
<string name="pref_switch_card_view_title">"Card View"</string> <string name="pref_switch_card_view_title">"Card View"</string>
@ -68,7 +68,7 @@
<string name="invitation_title">"Essaye cette application pour les flux RSS Selfoss !"</string> <string name="invitation_title">"Essaye cette application pour les flux RSS Selfoss !"</string>
<string name="invitation_message">"J'utilise cette applications pour mon flux RSS Selfoss. Tu aimeras peut être !"</string> <string name="invitation_message">"J'utilise cette applications pour mon flux RSS Selfoss. Tu aimeras peut être !"</string>
<string name="invitation_cta">"Essayer maintenant"</string> <string name="invitation_cta">"Essayer maintenant"</string>
<string name="text_wrong_url">"Vous semblez essayer de vous connceter avec une URL invalide. Assurez-vous que c'est la bonne, et si le problème persiste, contactez-moi via le lien du play store. Notez aussi que l'application ne peut fonctionner sans l'application web Selfoss. Vous ne pouvez pas utiliser l'application pour accéder directement aux flux RSS."</string> <string name="text_wrong_url">"Vous semblez essayer de vous connecter avec une URL invalide. Assurez-vous que c'est la bonne, et si le problème persiste, contactez-moi via le lien du play store. Notez aussi que l'application ne peut fonctionner sans l'application web Selfoss. Vous ne pouvez pas utiliser l'application pour accéder directement aux flux RSS."</string>
<string name="pref_general_internal_browser_title">"Ouvrir les liens dans l'application"</string> <string name="pref_general_internal_browser_title">"Ouvrir les liens dans l'application"</string>
<string name="pref_general_internal_browser_on">"Les articles s'ouvriront dans l'application"</string> <string name="pref_general_internal_browser_on">"Les articles s'ouvriront dans l'application"</string>
<string name="pref_general_internal_browser_off">"Les articles s'ouvriront dans votre naviguateur par défaut"</string> <string name="pref_general_internal_browser_off">"Les articles s'ouvriront dans votre naviguateur par défaut"</string>
@ -81,7 +81,7 @@
<string name="pref_switch_card_view_on">"Les articles seront affichés en forme de carte"</string> <string name="pref_switch_card_view_on">"Les articles seront affichés en forme de carte"</string>
<string name="pref_switch_card_view_off">"Les articles seront affichés en liste"</string> <string name="pref_switch_card_view_off">"Les articles seront affichés en liste"</string>
<string name="pref_switch_actions_tap_on">"Afficher la barre d'action sous l'article"</string> <string name="pref_switch_actions_tap_on">"Afficher la barre d'action sous l'article"</string>
<string name="pref_switch_actions_tap_off">"Le clique sur un article l'ouvrira dans le naviguateur selectionné"</string> <string name="pref_switch_actions_tap_off">"Le clic sur un article l'ouvrira dans le navigateur sélectionné"</string>
<string name="menu_home_refresh">"Mettre à jour"</string> <string name="menu_home_refresh">"Mettre à jour"</string>
<string name="refresh_success_response">"Mise à jour effectuée."</string> <string name="refresh_success_response">"Mise à jour effectuée."</string>
<string name="refresh_failer_message">"La mise à jour n'a pas fonctionné. Vérifiez vos logs selfoss."</string> <string name="refresh_failer_message">"La mise à jour n'a pas fonctionné. Vérifiez vos logs selfoss."</string>
@ -132,12 +132,12 @@
<string name="indigo_pink_dark_theme">Indigo/Rose/Foncé</string> <string name="indigo_pink_dark_theme">Indigo/Rose/Foncé</string>
<string name="red_teal_dark_theme">Rouge/Sarcelle/Foncé</string> <string name="red_teal_dark_theme">Rouge/Sarcelle/Foncé</string>
<string name="pref_header_debug">Debug</string> <string name="pref_header_debug">Debug</string>
<string name="login_debug_title">Activez pour logguer toutes les erreurs de connexion</string> <string name="login_debug_title">Activez pour loguer toutes les erreurs de connexion</string>
<string name="login_debug_on">Toutes les erreurs de connexion vont être loguées</string> <string name="login_debug_on">Toutes les erreurs de connexion vont être loguées</string>
<string name="login_debug_off">Aucune erreur de connexion ne sera loguée</string> <string name="login_debug_off">Aucune erreur de connexion ne sera loguée</string>
<string name="login_menu_debug">Debug</string> <string name="login_menu_debug">Debug</string>
<string name="self_hosted_cert_switch">Certificat auto-signé ?</string> <string name="self_hosted_cert_switch">Certificat auto-signé ?</string>
<string name="self_signed_cert_warning">Pour des raisons de sécurités, les certificats auto-signés sont désactivés par défaut. En les activant, je ne serais pas responsable de quelconques problèmes de sécurité rencontrés.</string> <string name="self_signed_cert_warning">Pour des raisons de sécurité, les certificats auto-signés sont désactivés par défaut. En les activant, je ne serais pas responsable de quelconques problèmes de sécurité rencontrés.</string>
<string name="pref_selfoss_category">Api Selfoss</string> <string name="pref_selfoss_category">Api Selfoss</string>
<string name="pref_api_items_number_title">Nombre d\'articles chargés</string> <string name="pref_api_items_number_title">Nombre d\'articles chargés</string>
<string name="read_debug_title">Des articles lus marqués comme non lus ?</string> <string name="read_debug_title">Des articles lus marqués comme non lus ?</string>
@ -158,8 +158,13 @@
<string name="reader_action_more">Lire plus</string> <string name="reader_action_more">Lire plus</string>
<string name="reader_action_open">Ouvrir</string> <string name="reader_action_open">Ouvrir</string>
<string name="reader_action_share">Partager</string> <string name="reader_action_share">Partager</string>
<string name="pref_switch_actions_pager_scroll">Marquer les articles comme lus à la navigation dans le lecteur d\'article.</string> <string name="pref_switch_actions_pager_scroll_on">Marquer les articles comme lus à la navigation dans le lecteur d\'article.</string>
<string name="prefer_webview_in_article_viewer_title">Use a webview in the article viewer.</string> <string name="add_to_favs_reader">Ajouter aux favoris</string>
<string name="prefer_webview_in_article_viewer_on">Using the webview for the content of the article viewer. Urls, gifs and images will be better handled, but may be slower.</string> <string name="remove_to_favs_reader">Supprimer des favoris</string>
<string name="prefer_webview_in_article_viewer_off">The content of the article will be displayed as simple text with links and images. Urls may not work, and gifs won\'t load.</string> <string name="pref_content_reader_font_size">Taille du texte du contenu du lecteur d\'articles</string>
<string name="pref_header_viewer">Lecteur d\'articles</string>
<string name="refresh_dialog_message">En validant, votre instance Selfoss sera mise à jour.</string>
<string name="markall_dialog_message">Marquer tous les éléments comme lus ?</string>
<string name="pref_switch_actions_pager_scroll">Marquer comme lu à la navigation.</string>
<string name="pref_switch_actions_pager_scroll_off">Ne pas marquer les articles comme lus à la navigation.</string>
</resources> </resources>

View File

@ -158,8 +158,13 @@
<string name="reader_action_more">Read more</string> <string name="reader_action_more">Read more</string>
<string name="reader_action_open">Open in browser</string> <string name="reader_action_open">Open in browser</string>
<string name="reader_action_share">Share</string> <string name="reader_action_share">Share</string>
<string name="pref_switch_actions_pager_scroll">Mark articles as read when swiping between articles.</string> <string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
<string name="prefer_webview_in_article_viewer_title">Use a webview in the article viewer.</string> <string name="add_to_favs_reader">Add to favorites</string>
<string name="prefer_webview_in_article_viewer_on">Using the webview for the content of the article viewer. Urls, gifs and images will be better handled, but may be slower.</string> <string name="remove_to_favs_reader">Remove from favorites</string>
<string name="prefer_webview_in_article_viewer_off">The content of the article will be displayed as simple text with links and images. Urls may not work, and gifs won\'t load.</string> <string name="pref_content_reader_font_size">Article reader content font size</string>
<string name="pref_header_viewer">Article viewer</string>
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
<string name="markall_dialog_message">This will mark all the items as read.</string>
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
</resources> </resources>

View File

@ -158,8 +158,13 @@
<string name="reader_action_more">Baca lebih lanjut</string> <string name="reader_action_more">Baca lebih lanjut</string>
<string name="reader_action_open">Buka di peramban</string> <string name="reader_action_open">Buka di peramban</string>
<string name="reader_action_share">Bagikan</string> <string name="reader_action_share">Bagikan</string>
<string name="pref_switch_actions_pager_scroll">Mark articles as read when swiping between articles.</string> <string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
<string name="prefer_webview_in_article_viewer_title">Use a webview in the article viewer.</string> <string name="add_to_favs_reader">Add to favorites</string>
<string name="prefer_webview_in_article_viewer_on">Using the webview for the content of the article viewer. Urls, gifs and images will be better handled, but may be slower.</string> <string name="remove_to_favs_reader">Remove from favorites</string>
<string name="prefer_webview_in_article_viewer_off">The content of the article will be displayed as simple text with links and images. Urls may not work, and gifs won\'t load.</string> <string name="pref_content_reader_font_size">Article reader content font size</string>
<string name="pref_header_viewer">Article viewer</string>
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
<string name="markall_dialog_message">This will mark all the items as read.</string>
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
</resources> </resources>

View File

@ -158,8 +158,13 @@
<string name="reader_action_more">Read more</string> <string name="reader_action_more">Read more</string>
<string name="reader_action_open">Open in browser</string> <string name="reader_action_open">Open in browser</string>
<string name="reader_action_share">Share</string> <string name="reader_action_share">Share</string>
<string name="pref_switch_actions_pager_scroll">Mark articles as read when swiping between articles.</string> <string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
<string name="prefer_webview_in_article_viewer_title">Use a webview in the article viewer.</string> <string name="add_to_favs_reader">Add to favorites</string>
<string name="prefer_webview_in_article_viewer_on">Using the webview for the content of the article viewer. Urls, gifs and images will be better handled, but may be slower.</string> <string name="remove_to_favs_reader">Remove from favorites</string>
<string name="prefer_webview_in_article_viewer_off">The content of the article will be displayed as simple text with links and images. Urls may not work, and gifs won\'t load.</string> <string name="pref_content_reader_font_size">Article reader content font size</string>
<string name="pref_header_viewer">Article viewer</string>
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
<string name="markall_dialog_message">This will mark all the items as read.</string>
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
</resources> </resources>

View File

@ -158,8 +158,13 @@
<string name="reader_action_more">Read more</string> <string name="reader_action_more">Read more</string>
<string name="reader_action_open">Open in browser</string> <string name="reader_action_open">Open in browser</string>
<string name="reader_action_share">Share</string> <string name="reader_action_share">Share</string>
<string name="pref_switch_actions_pager_scroll">Mark articles as read when swiping between articles.</string> <string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
<string name="prefer_webview_in_article_viewer_title">Use a webview in the article viewer.</string> <string name="add_to_favs_reader">Add to favorites</string>
<string name="prefer_webview_in_article_viewer_on">Using the webview for the content of the article viewer. Urls, gifs and images will be better handled, but may be slower.</string> <string name="remove_to_favs_reader">Remove from favorites</string>
<string name="prefer_webview_in_article_viewer_off">The content of the article will be displayed as simple text with links and images. Urls may not work, and gifs won\'t load.</string> <string name="pref_content_reader_font_size">Article reader content font size</string>
<string name="pref_header_viewer">Article viewer</string>
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
<string name="markall_dialog_message">This will mark all the items as read.</string>
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
</resources> </resources>

View File

@ -158,8 +158,13 @@
<string name="reader_action_more">Read more</string> <string name="reader_action_more">Read more</string>
<string name="reader_action_open">Open in browser</string> <string name="reader_action_open">Open in browser</string>
<string name="reader_action_share">Share</string> <string name="reader_action_share">Share</string>
<string name="pref_switch_actions_pager_scroll">Mark articles as read when swiping between articles.</string> <string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
<string name="prefer_webview_in_article_viewer_title">Use a webview in the article viewer.</string> <string name="add_to_favs_reader">Add to favorites</string>
<string name="prefer_webview_in_article_viewer_on">Using the webview for the content of the article viewer. Urls, gifs and images will be better handled, but may be slower.</string> <string name="remove_to_favs_reader">Remove from favorites</string>
<string name="prefer_webview_in_article_viewer_off">The content of the article will be displayed as simple text with links and images. Urls may not work, and gifs won\'t load.</string> <string name="pref_content_reader_font_size">Article reader content font size</string>
<string name="pref_header_viewer">Article viewer</string>
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
<string name="markall_dialog_message">This will mark all the items as read.</string>
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
</resources> </resources>

View File

@ -158,8 +158,13 @@
<string name="reader_action_more">Read more</string> <string name="reader_action_more">Read more</string>
<string name="reader_action_open">Open in browser</string> <string name="reader_action_open">Open in browser</string>
<string name="reader_action_share">Share</string> <string name="reader_action_share">Share</string>
<string name="pref_switch_actions_pager_scroll">Mark articles as read when swiping between articles.</string> <string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
<string name="prefer_webview_in_article_viewer_title">Use a webview in the article viewer.</string> <string name="add_to_favs_reader">Add to favorites</string>
<string name="prefer_webview_in_article_viewer_on">Using the webview for the content of the article viewer. Urls, gifs and images will be better handled, but may be slower.</string> <string name="remove_to_favs_reader">Remove from favorites</string>
<string name="prefer_webview_in_article_viewer_off">The content of the article will be displayed as simple text with links and images. Urls may not work, and gifs won\'t load.</string> <string name="pref_content_reader_font_size">Article reader content font size</string>
<string name="pref_header_viewer">Article viewer</string>
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
<string name="markall_dialog_message">This will mark all the items as read.</string>
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
</resources> </resources>

View File

@ -158,8 +158,13 @@
<string name="reader_action_more">Lees meer</string> <string name="reader_action_more">Lees meer</string>
<string name="reader_action_open">Openen in browser</string> <string name="reader_action_open">Openen in browser</string>
<string name="reader_action_share">Delen</string> <string name="reader_action_share">Delen</string>
<string name="pref_switch_actions_pager_scroll">Mark articles as read when swiping between articles.</string> <string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
<string name="prefer_webview_in_article_viewer_title">Use a webview in the article viewer.</string> <string name="add_to_favs_reader">Add to favorites</string>
<string name="prefer_webview_in_article_viewer_on">Using the webview for the content of the article viewer. Urls, gifs and images will be better handled, but may be slower.</string> <string name="remove_to_favs_reader">Remove from favorites</string>
<string name="prefer_webview_in_article_viewer_off">The content of the article will be displayed as simple text with links and images. Urls may not work, and gifs won\'t load.</string> <string name="pref_content_reader_font_size">Article reader content font size</string>
<string name="pref_header_viewer">Article viewer</string>
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
<string name="markall_dialog_message">This will mark all the items as read.</string>
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
</resources> </resources>

View File

@ -158,8 +158,13 @@
<string name="reader_action_more">Read more</string> <string name="reader_action_more">Read more</string>
<string name="reader_action_open">Open in browser</string> <string name="reader_action_open">Open in browser</string>
<string name="reader_action_share">Share</string> <string name="reader_action_share">Share</string>
<string name="pref_switch_actions_pager_scroll">Mark articles as read when swiping between articles.</string> <string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
<string name="prefer_webview_in_article_viewer_title">Use a webview in the article viewer.</string> <string name="add_to_favs_reader">Add to favorites</string>
<string name="prefer_webview_in_article_viewer_on">Using the webview for the content of the article viewer. Urls, gifs and images will be better handled, but may be slower.</string> <string name="remove_to_favs_reader">Remove from favorites</string>
<string name="prefer_webview_in_article_viewer_off">The content of the article will be displayed as simple text with links and images. Urls may not work, and gifs won\'t load.</string> <string name="pref_content_reader_font_size">Article reader content font size</string>
<string name="pref_header_viewer">Article viewer</string>
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
<string name="markall_dialog_message">This will mark all the items as read.</string>
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
</resources> </resources>

View File

@ -158,8 +158,13 @@
<string name="reader_action_more">Read more</string> <string name="reader_action_more">Read more</string>
<string name="reader_action_open">Open in browser</string> <string name="reader_action_open">Open in browser</string>
<string name="reader_action_share">Share</string> <string name="reader_action_share">Share</string>
<string name="pref_switch_actions_pager_scroll">Mark articles as read when swiping between articles.</string> <string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
<string name="prefer_webview_in_article_viewer_title">Use a webview in the article viewer.</string> <string name="add_to_favs_reader">Add to favorites</string>
<string name="prefer_webview_in_article_viewer_on">Using the webview for the content of the article viewer. Urls, gifs and images will be better handled, but may be slower.</string> <string name="remove_to_favs_reader">Remove from favorites</string>
<string name="prefer_webview_in_article_viewer_off">The content of the article will be displayed as simple text with links and images. Urls may not work, and gifs won\'t load.</string> <string name="pref_content_reader_font_size">Article reader content font size</string>
<string name="pref_header_viewer">Article viewer</string>
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
<string name="markall_dialog_message">This will mark all the items as read.</string>
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
</resources> </resources>

View File

@ -158,8 +158,13 @@
<string name="reader_action_more">Leia mais</string> <string name="reader_action_more">Leia mais</string>
<string name="reader_action_open">Abrir no navegador</string> <string name="reader_action_open">Abrir no navegador</string>
<string name="reader_action_share">Compartilhar</string> <string name="reader_action_share">Compartilhar</string>
<string name="pref_switch_actions_pager_scroll">Mark articles as read when swiping between articles.</string> <string name="pref_switch_actions_pager_scroll_on">Se esta configuração estiver ativada, os artigos serão marcados como lidos ao deslizar para a esquerda e para a direita no leitor do artigo.</string>
<string name="prefer_webview_in_article_viewer_title">Use a webview in the article viewer.</string> <string name="add_to_favs_reader">Adicionar aos favoritos</string>
<string name="prefer_webview_in_article_viewer_on">Using the webview for the content of the article viewer. Urls, gifs and images will be better handled, but may be slower.</string> <string name="remove_to_favs_reader">Remover dos favoritos</string>
<string name="prefer_webview_in_article_viewer_off">The content of the article will be displayed as simple text with links and images. Urls may not work, and gifs won\'t load.</string> <string name="pref_content_reader_font_size">Tamanho da fonte do conteúdo do leitor de artigos</string>
<string name="pref_header_viewer">Visualizador de artigos</string>
<string name="refresh_dialog_message">Isso atualizará sua instância do Selfoss.</string>
<string name="markall_dialog_message">Isso marcará todos os itens como lidos.</string>
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
</resources> </resources>

View File

@ -158,8 +158,13 @@
<string name="reader_action_more">Ler mais</string> <string name="reader_action_more">Ler mais</string>
<string name="reader_action_open">Abrir no browser</string> <string name="reader_action_open">Abrir no browser</string>
<string name="reader_action_share">Compartilhar</string> <string name="reader_action_share">Compartilhar</string>
<string name="pref_switch_actions_pager_scroll">Artigos de marca como lida quando passar entre artigos.</string> <string name="pref_switch_actions_pager_scroll_on">Artigos de marca como lida quando passar entre artigos.</string>
<string name="prefer_webview_in_article_viewer_title">Use a webview in the article viewer.</string> <string name="add_to_favs_reader">Add to favorites</string>
<string name="prefer_webview_in_article_viewer_on">Using the webview for the content of the article viewer. Urls, gifs and images will be better handled, but may be slower.</string> <string name="remove_to_favs_reader">Remove from favorites</string>
<string name="prefer_webview_in_article_viewer_off">The content of the article will be displayed as simple text with links and images. Urls may not work, and gifs won\'t load.</string> <string name="pref_content_reader_font_size">Article reader content font size</string>
<string name="pref_header_viewer">Article viewer</string>
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
<string name="markall_dialog_message">This will mark all the items as read.</string>
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
</resources> </resources>

View File

@ -158,8 +158,13 @@
<string name="reader_action_more">Read more</string> <string name="reader_action_more">Read more</string>
<string name="reader_action_open">Open in browser</string> <string name="reader_action_open">Open in browser</string>
<string name="reader_action_share">Share</string> <string name="reader_action_share">Share</string>
<string name="pref_switch_actions_pager_scroll">Mark articles as read when swiping between articles.</string> <string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
<string name="prefer_webview_in_article_viewer_title">Use a webview in the article viewer.</string> <string name="add_to_favs_reader">Add to favorites</string>
<string name="prefer_webview_in_article_viewer_on">Using the webview for the content of the article viewer. Urls, gifs and images will be better handled, but may be slower.</string> <string name="remove_to_favs_reader">Remove from favorites</string>
<string name="prefer_webview_in_article_viewer_off">The content of the article will be displayed as simple text with links and images. Urls may not work, and gifs won\'t load.</string> <string name="pref_content_reader_font_size">Article reader content font size</string>
<string name="pref_header_viewer">Article viewer</string>
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
<string name="markall_dialog_message">This will mark all the items as read.</string>
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
</resources> </resources>

View File

@ -158,8 +158,13 @@
<string name="reader_action_more">Read more</string> <string name="reader_action_more">Read more</string>
<string name="reader_action_open">Open in browser</string> <string name="reader_action_open">Open in browser</string>
<string name="reader_action_share">Share</string> <string name="reader_action_share">Share</string>
<string name="pref_switch_actions_pager_scroll">Mark articles as read when swiping between articles.</string> <string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
<string name="prefer_webview_in_article_viewer_title">Use a webview in the article viewer.</string> <string name="add_to_favs_reader">Add to favorites</string>
<string name="prefer_webview_in_article_viewer_on">Using the webview for the content of the article viewer. Urls, gifs and images will be better handled, but may be slower.</string> <string name="remove_to_favs_reader">Remove from favorites</string>
<string name="prefer_webview_in_article_viewer_off">The content of the article will be displayed as simple text with links and images. Urls may not work, and gifs won\'t load.</string> <string name="pref_content_reader_font_size">Article reader content font size</string>
<string name="pref_header_viewer">Article viewer</string>
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
<string name="markall_dialog_message">This will mark all the items as read.</string>
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
</resources> </resources>

View File

@ -158,8 +158,13 @@
<string name="reader_action_more">Read more</string> <string name="reader_action_more">Read more</string>
<string name="reader_action_open">Open in browser</string> <string name="reader_action_open">Open in browser</string>
<string name="reader_action_share">Share</string> <string name="reader_action_share">Share</string>
<string name="pref_switch_actions_pager_scroll">Mark articles as read when swiping between articles.</string> <string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
<string name="prefer_webview_in_article_viewer_title">Use a webview in the article viewer.</string> <string name="add_to_favs_reader">Add to favorites</string>
<string name="prefer_webview_in_article_viewer_on">Using the webview for the content of the article viewer. Urls, gifs and images will be better handled, but may be slower.</string> <string name="remove_to_favs_reader">Remove from favorites</string>
<string name="prefer_webview_in_article_viewer_off">The content of the article will be displayed as simple text with links and images. Urls may not work, and gifs won\'t load.</string> <string name="pref_content_reader_font_size">Article reader content font size</string>
<string name="pref_header_viewer">Article viewer</string>
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
<string name="markall_dialog_message">This will mark all the items as read.</string>
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
</resources> </resources>

View File

@ -158,8 +158,13 @@
<string name="reader_action_more">Read more</string> <string name="reader_action_more">Read more</string>
<string name="reader_action_open">Open in browser</string> <string name="reader_action_open">Open in browser</string>
<string name="reader_action_share">Share</string> <string name="reader_action_share">Share</string>
<string name="pref_switch_actions_pager_scroll">Mark articles as read when swiping between articles.</string> <string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
<string name="prefer_webview_in_article_viewer_title">Use a webview in the article viewer.</string> <string name="add_to_favs_reader">Add to favorites</string>
<string name="prefer_webview_in_article_viewer_on">Using the webview for the content of the article viewer. Urls, gifs and images will be better handled, but may be slower.</string> <string name="remove_to_favs_reader">Remove from favorites</string>
<string name="prefer_webview_in_article_viewer_off">The content of the article will be displayed as simple text with links and images. Urls may not work, and gifs won\'t load.</string> <string name="pref_content_reader_font_size">Article reader content font size</string>
<string name="pref_header_viewer">Article viewer</string>
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
<string name="markall_dialog_message">This will mark all the items as read.</string>
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
</resources> </resources>

View File

@ -158,8 +158,13 @@
<string name="reader_action_more">Daha fazlasını görüntüle</string> <string name="reader_action_more">Daha fazlasını görüntüle</string>
<string name="reader_action_open">Tarayıcıda aç</string> <string name="reader_action_open">Tarayıcıda aç</string>
<string name="reader_action_share">Paylaş</string> <string name="reader_action_share">Paylaş</string>
<string name="pref_switch_actions_pager_scroll">Mark articles as read when swiping between articles.</string> <string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
<string name="prefer_webview_in_article_viewer_title">Use a webview in the article viewer.</string> <string name="add_to_favs_reader">Add to favorites</string>
<string name="prefer_webview_in_article_viewer_on">Using the webview for the content of the article viewer. Urls, gifs and images will be better handled, but may be slower.</string> <string name="remove_to_favs_reader">Remove from favorites</string>
<string name="prefer_webview_in_article_viewer_off">The content of the article will be displayed as simple text with links and images. Urls may not work, and gifs won\'t load.</string> <string name="pref_content_reader_font_size">Article reader content font size</string>
<string name="pref_header_viewer">Article viewer</string>
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
<string name="markall_dialog_message">This will mark all the items as read.</string>
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
</resources> </resources>

View File

@ -158,8 +158,13 @@
<string name="reader_action_more">Read more</string> <string name="reader_action_more">Read more</string>
<string name="reader_action_open">Open in browser</string> <string name="reader_action_open">Open in browser</string>
<string name="reader_action_share">Share</string> <string name="reader_action_share">Share</string>
<string name="pref_switch_actions_pager_scroll">Mark articles as read when swiping between articles.</string> <string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
<string name="prefer_webview_in_article_viewer_title">Use a webview in the article viewer.</string> <string name="add_to_favs_reader">Add to favorites</string>
<string name="prefer_webview_in_article_viewer_on">Using the webview for the content of the article viewer. Urls, gifs and images will be better handled, but may be slower.</string> <string name="remove_to_favs_reader">Remove from favorites</string>
<string name="prefer_webview_in_article_viewer_off">The content of the article will be displayed as simple text with links and images. Urls may not work, and gifs won\'t load.</string> <string name="pref_content_reader_font_size">Article reader content font size</string>
<string name="pref_header_viewer">Article viewer</string>
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
<string name="markall_dialog_message">This will mark all the items as read.</string>
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
</resources> </resources>

View File

@ -158,8 +158,13 @@
<string name="reader_action_more">Read more</string> <string name="reader_action_more">Read more</string>
<string name="reader_action_open">Open in browser</string> <string name="reader_action_open">Open in browser</string>
<string name="reader_action_share">Share</string> <string name="reader_action_share">Share</string>
<string name="pref_switch_actions_pager_scroll">Mark articles as read when swiping between articles.</string> <string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
<string name="prefer_webview_in_article_viewer_title">Use a webview in the article viewer.</string> <string name="add_to_favs_reader">Add to favorites</string>
<string name="prefer_webview_in_article_viewer_on">Using the webview for the content of the article viewer. Urls, gifs and images will be better handled, but may be slower.</string> <string name="remove_to_favs_reader">Remove from favorites</string>
<string name="prefer_webview_in_article_viewer_off">The content of the article will be displayed as simple text with links and images. Urls may not work, and gifs won\'t load.</string> <string name="pref_content_reader_font_size">Article reader content font size</string>
<string name="pref_header_viewer">Article viewer</string>
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
<string name="markall_dialog_message">This will mark all the items as read.</string>
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
</resources> </resources>

View File

@ -158,8 +158,13 @@
<string name="reader_action_more">阅读更多</string> <string name="reader_action_more">阅读更多</string>
<string name="reader_action_open">在浏览器中打开</string> <string name="reader_action_open">在浏览器中打开</string>
<string name="reader_action_share">分享</string> <string name="reader_action_share">分享</string>
<string name="pref_switch_actions_pager_scroll">Mark articles as read when swiping between articles.</string> <string name="pref_switch_actions_pager_scroll_on">切换文章时将文章标记为已读。</string>
<string name="prefer_webview_in_article_viewer_title">Use a webview in the article viewer.</string> <string name="add_to_favs_reader">添加到收藏</string>
<string name="prefer_webview_in_article_viewer_on">Using the webview for the content of the article viewer. Urls, gifs and images will be better handled, but may be slower.</string> <string name="remove_to_favs_reader">从收藏中移除</string>
<string name="prefer_webview_in_article_viewer_off">The content of the article will be displayed as simple text with links and images. Urls may not work, and gifs won\'t load.</string> <string name="pref_content_reader_font_size">Article reader content font size</string>
<string name="pref_header_viewer">Article viewer</string>
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
<string name="markall_dialog_message">This will mark all the items as read.</string>
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
</resources> </resources>

View File

@ -158,8 +158,13 @@
<string name="reader_action_more">阅读更多</string> <string name="reader_action_more">阅读更多</string>
<string name="reader_action_open">在浏览器中打开</string> <string name="reader_action_open">在浏览器中打开</string>
<string name="reader_action_share">分享</string> <string name="reader_action_share">分享</string>
<string name="pref_switch_actions_pager_scroll">Mark articles as read when swiping between articles.</string> <string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
<string name="prefer_webview_in_article_viewer_title">Use a webview in the article viewer.</string> <string name="add_to_favs_reader">Add to favorites</string>
<string name="prefer_webview_in_article_viewer_on">Using the webview for the content of the article viewer. Urls, gifs and images will be better handled, but may be slower.</string> <string name="remove_to_favs_reader">Remove from favorites</string>
<string name="prefer_webview_in_article_viewer_off">The content of the article will be displayed as simple text with links and images. Urls may not work, and gifs won\'t load.</string> <string name="pref_content_reader_font_size">Article reader content font size</string>
<string name="pref_header_viewer">Article viewer</string>
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
<string name="markall_dialog_message">This will mark all the items as read.</string>
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
</resources> </resources>

View File

@ -11,4 +11,13 @@
<color name="refresh_progress_2">@color/colorAccent</color> <color name="refresh_progress_2">@color/colorAccent</color>
<color name="refresh_progress_3">@color/pink</color> <color name="refresh_progress_3">@color/pink</color>
<color name="background_grey">#FFe4e4e4</color> <color name="background_grey">#FFe4e4e4</color>
<color name="dark_webview">#FF303030</color>
<color name="dark_webview_text">@color/md_white_1000</color>
<color name="light_webview">@color/md_grey_50</color>
<color name="light_webview_text">@color/md_grey_900</color>
<color name="cardBackgroundColor">#FFFFFFFF</color>
<color name="materialDrawerHeaderSelectionText">@color/md_grey_900</color>
<color name="darkBackground">#FF303030</color>
</resources> </resources>

View File

@ -161,8 +161,13 @@
<string name="reader_action_more">Read more</string> <string name="reader_action_more">Read more</string>
<string name="reader_action_open">Open in browser</string> <string name="reader_action_open">Open in browser</string>
<string name="reader_action_share">Share</string> <string name="reader_action_share">Share</string>
<string name="pref_switch_actions_pager_scroll">Mark articles as read when swiping between articles.</string> <string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
<string name="prefer_webview_in_article_viewer_title">Use a webview in the article viewer.</string> <string name="add_to_favs_reader">Add to favorites</string>
<string name="prefer_webview_in_article_viewer_on">Using the webview for the content of the article viewer. Urls, gifs and images will be better handled, but may be slower.</string> <string name="remove_to_favs_reader">Remove from favorites</string>
<string name="prefer_webview_in_article_viewer_off">The content of the article will be displayed as simple text with links and images. Urls may not work, and gifs won\'t load.</string> <string name="pref_content_reader_font_size">Article reader content font size</string>
<string name="pref_header_viewer">Article viewer</string>
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
<string name="markall_dialog_message">This will mark all the items as read.</string>
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
</resources> </resources>

View File

@ -43,182 +43,6 @@
<item name="drawerArrowStyle">@style/DrawerArrowStyle</item>--> <item name="drawerArrowStyle">@style/DrawerArrowStyle</item>-->
</style> </style>
<style name="NoBarBlueAmber" parent="MaterialDrawerTheme.Light">
<item name="colorPrimary">@color/md_blue_500</item>
<item name="colorPrimaryDark">@color/md_blue_700</item>
<item name="colorAccent">@color/md_amber_500</item>
<item name="colorAccentDark">@color/md_amber_700</item>
<item name="cardBackgroundColor">@color/white</item>
<item name="android:colorBackground">@color/md_grey_50</item>
<item name="android:textColorPrimary">@color/md_grey_900</item>
<item name="android:textColorSecondary">@color/md_grey_400</item>
<item name="material_drawer_header_selection_text">@color/md_grey_900</item>
<item name="toolbarPopupTheme">@style/ThemeOverlay.AppCompat.Light</item>
</style>
<style name="NoBarBlueAmberDark" parent="MaterialDrawerTheme">
<item name="colorPrimary">@color/md_blue_500</item>
<item name="colorPrimaryDark">@color/md_blue_700</item>
<item name="colorAccent">@color/md_amber_500</item>
<item name="colorAccentDark">@color/md_amber_700</item>
<item name="cardBackgroundColor">@color/md_grey_800</item>
<item name="android:colorBackground">#303030</item>
<item name="bnbBackgroundColor">@color/md_grey_900</item>
<item name="android:textColorPrimary">@color/md_white_1000</item>
<item name="android:textColorSecondary">@color/md_grey_600</item>
<item name="material_drawer_header_selection_text">@color/md_grey_900</item>
<item name="toolbarPopupTheme">@style/ThemeOverlay.AppCompat.Dark</item>
</style>
<style name="NoBarGreyOrange" parent="MaterialDrawerTheme.Light">
<item name="colorPrimary">@color/md_blue_grey_500</item>
<item name="colorPrimaryDark">@color/md_blue_grey_700</item>
<item name="colorAccent">@color/md_deep_orange_500</item>
<item name="colorAccentDark">@color/md_deep_orange_700</item>
<item name="cardBackgroundColor">@color/white</item>
<item name="android:colorBackground">@color/md_grey_50</item>
<item name="android:textColorPrimary">@color/md_grey_900</item>
<item name="android:textColorSecondary">@color/md_grey_400</item>
<item name="material_drawer_header_selection_text">@color/md_grey_900</item>
<item name="toolbarPopupTheme">@style/ThemeOverlay.AppCompat.Light</item>
</style>
<style name="NoBarGreyOrangeDark" parent="MaterialDrawerTheme">
<item name="colorPrimary">@color/md_blue_grey_500</item>
<item name="colorPrimaryDark">@color/md_blue_grey_700</item>
<item name="colorAccent">@color/md_deep_orange_500</item>
<item name="colorAccentDark">@color/md_deep_orange_700</item>
<item name="cardBackgroundColor">@color/md_grey_800</item>
<item name="android:colorBackground">#303030</item>
<item name="bnbBackgroundColor">@color/md_grey_900</item>
<item name="android:textColorPrimary">@color/md_white_1000</item>
<item name="android:textColorSecondary">@color/md_grey_600</item>
<item name="material_drawer_header_selection_text">@color/md_grey_900</item>
<item name="toolbarPopupTheme">@style/ThemeOverlay.AppCompat.Dark</item>
</style>
<style name="NoBarIndigoPink" parent="MaterialDrawerTheme.Light">
<item name="colorPrimary">@color/md_indigo_500</item>
<item name="colorPrimaryDark">@color/md_indigo_700</item>
<item name="colorAccent">@color/md_pink_500</item>
<item name="colorAccentDark">@color/md_pink_700</item>
<item name="cardBackgroundColor">@color/white</item>
<item name="android:colorBackground">@color/md_grey_50</item>
<item name="android:textColorPrimary">@color/md_grey_900</item>
<item name="android:textColorSecondary">@color/md_grey_400</item>
<item name="material_drawer_header_selection_text">@color/md_grey_900</item>
<item name="toolbarPopupTheme">@style/ThemeOverlay.AppCompat.Light</item>
</style>
<style name="NoBarIndigoPinkDark" parent="MaterialDrawerTheme">
<item name="colorPrimary">@color/md_indigo_500</item>
<item name="colorPrimaryDark">@color/md_indigo_700</item>
<item name="colorAccent">@color/md_pink_500</item>
<item name="colorAccentDark">@color/md_pink_700</item>
<item name="cardBackgroundColor">@color/md_grey_800</item>
<item name="android:colorBackground">#303030</item>
<item name="bnbBackgroundColor">@color/md_grey_900</item>
<item name="android:textColorPrimary">@color/md_white_1000</item>
<item name="android:textColorSecondary">@color/md_grey_600</item>
<item name="material_drawer_header_selection_text">@color/md_grey_900</item>
<item name="toolbarPopupTheme">@style/ThemeOverlay.AppCompat.Dark</item>
</style>
<style name="NoBarRedTeal" parent="MaterialDrawerTheme.Light">
<item name="colorPrimary">@color/md_red_500</item>
<item name="colorPrimaryDark">@color/md_red_700</item>
<item name="colorAccent">@color/md_teal_500</item>
<item name="colorAccentDark">@color/md_teal_700</item>
<item name="cardBackgroundColor">@color/white</item>
<item name="android:colorBackground">@color/md_grey_50</item>
<item name="android:textColorPrimary">@color/md_grey_900</item>
<item name="android:textColorSecondary">@color/md_grey_400</item>
<item name="material_drawer_header_selection_text">@color/md_grey_900</item>
<item name="toolbarPopupTheme">@style/ThemeOverlay.AppCompat.Light</item>
</style>
<style name="NoBarRedTealDark" parent="MaterialDrawerTheme">
<item name="colorPrimary">@color/md_red_500</item>
<item name="colorPrimaryDark">@color/md_red_700</item>
<item name="colorAccent">@color/md_teal_500</item>
<item name="colorAccentDark">@color/md_teal_700</item>
<item name="cardBackgroundColor">@color/md_grey_800</item>
<item name="android:colorBackground">#303030</item>
<item name="bnbBackgroundColor">@color/md_grey_900</item>
<item name="android:textColorPrimary">@color/md_white_1000</item>
<item name="android:textColorSecondary">@color/md_grey_600</item>
<item name="material_drawer_header_selection_text">@color/md_grey_900</item>
<item name="toolbarPopupTheme">@style/ThemeOverlay.AppCompat.Dark</item>
</style>
<style name="NoBarCyanPink" parent="MaterialDrawerTheme.Light">
<item name="colorPrimary">@color/md_cyan_500</item>
<item name="colorPrimaryDark">@color/md_cyan_700</item>
<item name="colorAccent">@color/md_pink_500</item>
<item name="colorAccentDark">@color/md_pink_700</item>
<item name="cardBackgroundColor">@color/white</item>
<item name="android:colorBackground">@color/md_grey_50</item>
<item name="android:textColorPrimary">@color/md_grey_900</item>
<item name="android:textColorSecondary">@color/md_grey_400</item>
<item name="material_drawer_header_selection_text">@color/md_grey_900</item>
<item name="toolbarPopupTheme">@style/ThemeOverlay.AppCompat.Light</item>
</style>
<style name="NoBarCyanPinkDark" parent="MaterialDrawerTheme">
<item name="colorPrimary">@color/md_cyan_500</item>
<item name="colorPrimaryDark">@color/md_cyan_700</item>
<item name="colorAccent">@color/md_pink_500</item>
<item name="colorAccentDark">@color/md_pink_700</item>
<item name="cardBackgroundColor">@color/md_grey_800</item>
<item name="android:colorBackground">#303030</item>
<item name="bnbBackgroundColor">@color/md_grey_900</item>
<item name="android:textColorPrimary">@color/md_white_1000</item>
<item name="android:textColorSecondary">@color/md_grey_600</item>
<item name="material_drawer_header_selection_text">@color/md_grey_900</item>
<item name="toolbarPopupTheme">@style/ThemeOverlay.AppCompat.Dark</item>
</style>
<style name="NoBarTealOrange" parent="MaterialDrawerTheme.Light">
<item name="colorPrimary">@color/md_teal_500</item>
<item name="colorPrimaryDark">@color/md_teal_700</item>
<item name="colorAccent">@color/md_orange_500</item>
<item name="colorAccentDark">@color/md_orange_700</item>
<item name="cardBackgroundColor">@color/white</item>
<item name="android:colorBackground">@color/md_grey_50</item>
<item name="android:textColorPrimary">@color/md_grey_900</item>
<item name="android:textColorSecondary">@color/md_grey_400</item>
<item name="material_drawer_header_selection_text">@color/md_grey_900</item>
<item name="toolbarPopupTheme">@style/ThemeOverlay.AppCompat.Light</item>
</style>
<style name="NoBarTealOrangeDark" parent="MaterialDrawerTheme">
<item name="colorPrimary">@color/md_teal_500</item>
<item name="colorPrimaryDark">@color/md_teal_700</item>
<item name="colorAccent">@color/md_orange_500</item>
<item name="colorAccentDark">@color/md_orange_700</item>
<item name="cardBackgroundColor">@color/md_grey_800</item>
<item name="android:colorBackground">#303030</item>
<item name="bnbBackgroundColor">@color/md_grey_900</item>
<item name="android:textColorPrimary">@color/md_white_1000</item>
<item name="android:textColorSecondary">@color/md_grey_600</item>
<item name="material_drawer_header_selection_text">@color/md_grey_900</item>
<item name="toolbarPopupTheme">@style/ThemeOverlay.AppCompat.Dark</item>
</style>
<style name="Theme.App.Light" parent="Theme.IssueReporter.Light.DarkActionBar"> <style name="Theme.App.Light" parent="Theme.IssueReporter.Light.DarkActionBar">
<item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item>

View File

@ -33,13 +33,6 @@
android:summaryOff="@string/prefer_article_viewer_off" android:summaryOff="@string/prefer_article_viewer_off"
android:summaryOn="@string/prefer_article_viewer_on" android:summaryOn="@string/prefer_article_viewer_on"
android:title="@string/prefer_article_viewer_title" /> android:title="@string/prefer_article_viewer_title" />
<SwitchPreference
android:defaultValue="false"
android:dependency="prefer_article_viewer"
android:key="prefer_webview_in_article_viewer"
android:summaryOff="@string/prefer_webview_in_article_viewer_off"
android:summaryOn="@string/prefer_webview_in_article_viewer_on"
android:title="@string/prefer_webview_in_article_viewer_title" />
<PreferenceCategory <PreferenceCategory
android:title="@string/pref_general_category_displaying"> android:title="@string/pref_general_category_displaying">
@ -83,9 +76,5 @@
android:summaryOff="@string/pref_switch_actions_tap_off" android:summaryOff="@string/pref_switch_actions_tap_off"
android:summaryOn="@string/pref_switch_actions_tap_on" android:summaryOn="@string/pref_switch_actions_tap_on"
android:title="@string/pref_switch_actions_tap_title" /> android:title="@string/pref_switch_actions_tap_title" />
<SwitchPreference
android:defaultValue="false"
android:key="mark_on_scroll"
android:title="@string/pref_switch_actions_pager_scroll" />
</PreferenceScreen> </PreferenceScreen>

View File

@ -5,13 +5,19 @@
android:icon="@drawable/ic_settings_black_24dp" android:icon="@drawable/ic_settings_black_24dp"
android:title="@string/pref_header_general"/> android:title="@string/pref_header_general"/>
<header
android:fragment="apps.amine.bou.readerforselfoss.settings.SettingsActivity$ArticleViewerPreferenceFragment"
android:icon="@drawable/ic_chrome_reader_mode_black_24"
android:title="@string/pref_header_viewer"/>
<header <header
android:fragment="apps.amine.bou.readerforselfoss.settings.SettingsActivity$DebugPreferenceFragment" android:fragment="apps.amine.bou.readerforselfoss.settings.SettingsActivity$DebugPreferenceFragment"
android:icon="@drawable/ic_bug_report" android:icon="@drawable/ic_bug_report"
android:title="@string/pref_header_debug"/> android:title="@string/pref_header_debug"/>
<header <header
android:id="@+id/theme_change" android:fragment="apps.amine.bou.readerforselfoss.settings.SettingsActivity$ThemePreferenceFragment"
android:icon="@drawable/ic_color_lens_black_24dp" android:icon="@drawable/ic_color_lens_black_24dp"
android:title="@string/pref_header_theme"/> android:title="@string/pref_header_theme"/>

View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<!-- TODO translate this file -->
<SwitchPreference
android:defaultValue="false"
android:key="dark_theme"
android:title="Dark theme" />
<com.jrummyapps.android.colorpicker.ColorPreference
android:defaultValue="@color/colorPrimary"
android:key="color_primary"
android:title="Primary color"/>
<com.jrummyapps.android.colorpicker.ColorPreference
android:defaultValue="@color/colorPrimaryDark"
android:key="color_primary_dark"
android:title="Primary dark color"/>
<com.jrummyapps.android.colorpicker.ColorPreference
android:defaultValue="@color/colorAccent"
android:key="color_accent"
android:title="Accent color"/>
<com.jrummyapps.android.colorpicker.ColorPreference
android:defaultValue="@color/colorAccentDark"
android:key="color_accent_dark"
android:title="Accent dark color"/>
</PreferenceScreen>

View File

@ -0,0 +1,16 @@
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<SwitchPreference
android:defaultValue="false"
android:key="mark_on_scroll"
android:summaryOff="@string/pref_switch_actions_pager_scroll_off"
android:summaryOn="@string/pref_switch_actions_pager_scroll_on"
android:title="@string/pref_switch_actions_pager_scroll" />
<EditTextPreference
android:defaultValue="14"
android:inputType="number"
android:key="reader_font_size"
android:selectAllOnFocus="true"
android:singleLine="true"
android:title="@string/pref_content_reader_font_size" />
</PreferenceScreen>

View File

@ -1,7 +1,7 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules. // Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript { buildscript {
ext.kotlin_version = '1.2.0' ext.kotlin_version = '1.2.31'
repositories { repositories {
jcenter() jcenter()
google() google()
@ -10,14 +10,12 @@ buildscript {
} }
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.0.1' classpath 'com.android.tools.build:gradle:3.1.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files // in the individual module build.gradle files
classpath 'com.google.gms:google-services:3.1.1' classpath 'com.google.gms:google-services:3.1.1'
classpath "org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:2.6.1"
} }
} }
@ -40,9 +38,9 @@ project.ext.preDexLibs = !project.hasProperty('disablePreDex')
subprojects { subprojects {
project.plugins.whenPluginAdded { plugin -> project.plugins.whenPluginAdded { plugin ->
if ("com.android.build.gradle.AppPlugin".equals(plugin.class.name)) { if ("com.android.build.gradle.AppPlugin" == plugin.class.name) {
project.android.dexOptions.preDexLibraries = rootProject.ext.preDexLibs project.android.dexOptions.preDexLibraries = rootProject.ext.preDexLibs
} else if ("com.android.build.gradle.LibraryPlugin".equals(plugin.class.name)) { } else if ("com.android.build.gradle.LibraryPlugin" == plugin.class.name) {
project.android.dexOptions.preDexLibraries = rootProject.ext.preDexLibs project.android.dexOptions.preDexLibraries = rootProject.ext.preDexLibs
} }
} }

3
docs/_config.yml Normal file
View File

@ -0,0 +1,3 @@
theme: jekyll-theme-cayman
plugins:
- jekyll-redirect-from

BIN
docs/images/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
docs/images/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 294 KiB

95
docs/index.html Normal file
View File

@ -0,0 +1,95 @@
---
redirect_from: "/ReaderforSelfoss/"
---
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Reader for Selfoss</title>
<meta name="description" content="A Selfoss RSS Reader">
<meta name="keywords" content="rss,feed,reader,android,free,app,play,store,selfoss,download,opensource,code,kotlin">
<meta name="author" content="Amine Bouabdallaoui">
<link rel="shortcut icon" href="images/favicon.ico" type="image/x-icon">
<link rel="icon" href="images/favicon.ico" type="image/x-icon">
<style type="text/css">
html {
height: 100%;
}
#main {
width: 100%;
height: 100%;
background-color: #00bfa5;
color: #ffffff;
text-align: center;
margin: 0px;
}
#container {
height: 100%;
display: flex;
flex-direction: column;
justify-content: space-around;
}
h1 {
font-size: 22px;
}
h2 {
font-size: 14px;
}
#logo {
height: 100px;
width: auto;
}
#links {
display: flex;
justify-content: space-around;
}
#store img {
width: 100px;
}
#links iframe {
margin-top: 5px;
}
</style>
<script async defer src="https://buttons.github.io/buttons.js"></script>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-102547516-1', 'auto');
ga('send', 'pageview');
</script>
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-5R5LR4V');</script>
</head>
<body id="main">
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-5R5LR4V"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<div id="container" itemscope itemtype="http://schema.org/SoftwareApplication">
<div id="titles"><h1 itemprop="name">Reader For Selfoss</h1><h2>A new <span itemprop="operatingSystem">Android</span> Selfoss RSS reader</h2></div>
<div>
<img src="images/icon.png" id="logo" itemprop="image">
</div>
<div id="links">
<a itemprop="downloadUrl" id="store" href='https://play.google.com/store/apps/details?id=apps.amine.bou.readerforselfoss&pcampaignid=MKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1'><img alt='Get it on Google Play' src='https://play.google.com/intl/en_us/badges/images/generic/en_badge_web_generic.png'/></a>
<a class="github-button" href="https://github.com/aminecmi/readerforselfoss" data-size="large" aria-label="Star aminecmi/readerforselfoss on GitHub">Star</a>
</div>
<meta itemprop="url" content="https://github.com/aminecmi/readerforselfoss">
<meta itemprop="applicationCategory" content="News & Magazines">
</div>
</body>
</html>

View File

@ -15,3 +15,5 @@ org.gradle.jvmargs=-Xmx1536m
# This option should only be used with decoupled projects. More details, visit # This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true # org.gradle.parallel=true
org.gradle.caching=true
android.enableD8=true

View File

@ -1,6 +1,6 @@
#Sat Sep 02 11:43:17 CEST 2017 #Tue Mar 27 19:14:12 CEST 2018
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip

View File

@ -1 +1,15 @@
include ':app' include ':app'
ext.isCiServer = !!System.getProperty("CI")
buildCache {
local {
enabled = !isCiServer
}
remote(HttpBuildCache) {
url = System.getProperty("cacheUrl")
push = isCiServer
println "url ? " + System.getProperty("cacheUrl")
}
}