Compare commits
27 Commits
Author | SHA1 | Date | |
---|---|---|---|
ba4feeea87 | |||
6f52eae3c6 | |||
40ea8d56e6 | |||
72e562e8a8 | |||
6fa01bfe19 | |||
0ef59c9b91 | |||
d768d2232b | |||
b44a200731 | |||
016815e0d1 | |||
590534e4a6 | |||
7ea9d4e519 | |||
e0ab09f533 | |||
fbe98f1b16 | |||
d0675b8443 | |||
3ea1ed02ae | |||
ba120b1e0b | |||
acf6995c2d | |||
8306860f90 | |||
65974166be | |||
ee8924f986 | |||
170e575465 | |||
b7d5317b10 | |||
f12e7748c5 | |||
69a2418afc | |||
4924ddd172 | |||
1889b43786 | |||
f2e38a4203 |
5
.github/CONTRIBUTING.md
vendored
@ -38,18 +38,19 @@ Always check if the web version of your instance is working.
|
||||
* Be willing to accept criticism on your PRs (as I am on mine).
|
||||
* Remember that PR review can take time.
|
||||
|
||||
|
||||
# Build the project
|
||||
|
||||
You can directly import this project into IntellIJ/Android Studio.
|
||||
|
||||
You'll have to:
|
||||
|
||||
- [Create your own launcher icon](https://developer.android.com/studio/write/image-asset-studio.html#creating-launcher)
|
||||
|
||||
- Configure Fabric, or [remove it](https://docs.fabric.io/android/fabric/settings/removing.html#).
|
||||
- Create a firebase project and add the `google-services.json` to the `app/` folder.
|
||||
- Define the following in `res/values/strings.xml` or create `res/values/secrets.xml`
|
||||
|
||||
- mercury: A [Mercury](https://mercury.postlight.com/web-parser/) web parser api key for the internal browser
|
||||
- feedback_email: An email to receive users feedback.
|
||||
- source_url: an url to the source code, used in the settings
|
||||
- tracker_url: an url to the tracker, used in the settings
|
||||
- To run your app, you'll have to add `-P appLoginUrl="your.selfoss-instance.url" -P appLoginUsername="Username" -P appLoginPassword="password"`. (These are only used to run the espresso tests. You should be able to use empty strings or fake values to build the app)
|
||||
|
1
.gitignore
vendored
@ -216,5 +216,4 @@ gradle-app.setting
|
||||
|
||||
secrets.xml
|
||||
|
||||
mipmap-*
|
||||
release/
|
46
CHANGELOG.md
@ -1,3 +1,49 @@
|
||||
**1.5.2.06**
|
||||
|
||||
- Fix problem introduced in 1.5.2.04. SVG file not working on older versions of android.
|
||||
|
||||
**1.5.2.05**
|
||||
|
||||
- Versions updates
|
||||
|
||||
**1.5.2.04**
|
||||
|
||||
- Reverted to the old icon.
|
||||
|
||||
- Better icon for the intro activity.
|
||||
|
||||
- Updated gradle version.
|
||||
|
||||
**1.5.2.03**
|
||||
|
||||
- Added the ability to accept self signed certificates. (Needs more testing)
|
||||
|
||||
**1.5.2.02**
|
||||
|
||||
- Added optional login option.
|
||||
|
||||
**1.5.2.01**
|
||||
|
||||
- New (Better) Icon !
|
||||
|
||||
**1.5.2.0**
|
||||
|
||||
- New Icon !
|
||||
|
||||
**1.5.1.9/10/11**
|
||||
|
||||
- Hiding the unread badge when marking all items as read.
|
||||
|
||||
**1.5.1.8**
|
||||
|
||||
- Fixes and libs updates.
|
||||
|
||||
**1.5.1.7**
|
||||
|
||||
- Bug fixes.
|
||||
|
||||
- Code cleaning
|
||||
|
||||
**1.5.1.6**
|
||||
|
||||
- Added back the badges after it was fixed on the library side.
|
||||
|
@ -1,8 +1,8 @@
|
||||
# ReaderForSelfoss
|
||||
|
||||
[](https://gitter.im/amine-bou/ReaderForSelfoss)
|
||||
[](http://jenkins.amine-bou.fr/job/ReaderForSelfoss/)
|
||||
|
||||
[](https://circleci.com/gh/aminecmi/ReaderforSelfoss/tree/master)
|
||||
[](https://gitter.im/amine-bou/ReaderForSelfoss)
|
||||
|
||||
[](https://codebeat.co/projects/github-com-aminecmi-readerforselfoss-master)
|
||||
|
||||
@ -22,3 +22,8 @@ Check the [Contribution guide](https://github.com/aminecmi/ReaderforSelfoss/blob
|
||||
- [Check what changed](https://github.com/aminecmi/ReaderforSelfoss/blob/master/CHANGELOG.md)
|
||||
- [See what I'm doing](https://github.com/aminecmi/ReaderforSelfoss/projects/1)
|
||||
- [Create an issue, or request a new feature](https://github.com/aminecmi/ReaderforSelfoss/issues)
|
||||
|
||||
|
||||
#Icon
|
||||
|
||||
I used RSS Document by AlfredoCreates.com from the Noun Project. You can see it [here](https://thenounproject.com/search/?q=rss&i=596333).
|
@ -8,6 +8,21 @@ buildscript {
|
||||
}
|
||||
}
|
||||
|
||||
def gitVersion() {
|
||||
def process = "git describe --abbrev=0 --tags".execute()
|
||||
return process.text.substring(1).replaceAll("\\.", "")
|
||||
}
|
||||
|
||||
def versionCodeFromGit() {
|
||||
println "version code " + gitVersion().toInteger()
|
||||
return gitVersion().toInteger()
|
||||
}
|
||||
|
||||
def versionNameFromGit() {
|
||||
println "version code " + gitVersion().trim()
|
||||
return gitVersion().trim()
|
||||
}
|
||||
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
apply plugin: 'io.fabric'
|
||||
@ -24,9 +39,9 @@ android {
|
||||
defaultConfig {
|
||||
applicationId "apps.amine.bou.readerforselfoss"
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 25
|
||||
versionCode 1516
|
||||
versionName "1.5.1.6"
|
||||
targetSdkVersion 26
|
||||
versionCode versionCodeFromGit()
|
||||
versionName versionNameFromGit()
|
||||
|
||||
// Enabling multidex support.
|
||||
multiDexEnabled true
|
||||
@ -80,25 +95,25 @@ dependencies {
|
||||
compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
|
||||
|
||||
// Android Support
|
||||
compile 'com.android.support:appcompat-v7:26.0.0-beta2'
|
||||
compile 'com.android.support:design:26.0.0-beta2'
|
||||
compile 'com.android.support:recyclerview-v7:26.0.0-beta2'
|
||||
compile 'com.android.support:support-v4:26.0.0-beta2'
|
||||
compile 'com.android.support:support-vector-drawable:26.0.0-beta2'
|
||||
compile 'com.android.support:customtabs:26.0.0-beta2'
|
||||
compile 'com.android.support:cardview-v7:26.0.0-beta2'
|
||||
compile 'com.android.support:appcompat-v7:26.0.1'
|
||||
compile 'com.android.support:design:26.0.1'
|
||||
compile 'com.android.support:recyclerview-v7:26.0.1'
|
||||
compile 'com.android.support:support-v4:26.0.1'
|
||||
compile 'com.android.support:support-vector-drawable:26.0.1'
|
||||
compile 'com.android.support:customtabs:26.0.1'
|
||||
compile 'com.android.support:cardview-v7:26.0.1'
|
||||
compile 'com.android.support.constraint:constraint-layout:1.0.2'
|
||||
|
||||
// Firebase + crashlytics
|
||||
compile 'com.google.firebase:firebase-core:11.0.1'
|
||||
compile 'com.google.firebase:firebase-config:11.0.1'
|
||||
compile 'com.google.firebase:firebase-invites:11.0.1'
|
||||
compile 'com.google.firebase:firebase-core:11.2.0'
|
||||
compile 'com.google.firebase:firebase-config:11.2.0'
|
||||
compile 'com.google.firebase:firebase-invites:11.2.0'
|
||||
compile('com.crashlytics.sdk.android:crashlytics:2.6.8@aar') {
|
||||
transitive = true
|
||||
}
|
||||
|
||||
//multidex
|
||||
compile 'com.android.support:multidex:1.0.1'
|
||||
compile 'com.android.support:multidex:1.0.2'
|
||||
|
||||
// Intro
|
||||
compile 'agency.tango.android:material-intro-screen:0.0.5'
|
||||
@ -128,10 +143,10 @@ dependencies {
|
||||
compile 'com.github.stkent:amplify:1.5.0'
|
||||
|
||||
// For the article reader
|
||||
compile 'com.klinkerapps:drag-dismiss-activity:1.4.1'
|
||||
compile 'com.klinkerapps:drag-dismiss-activity:1.4.3'
|
||||
|
||||
// Drawer
|
||||
compile('com.mikepenz:materialdrawer:5.9.3@aar') {
|
||||
compile('com.mikepenz:materialdrawer:5.9.5@aar') {
|
||||
transitive = true
|
||||
}
|
||||
compile 'com.anupcowkur:reservoir:3.1.0'
|
||||
@ -170,4 +185,4 @@ def initAppLoginPropertiesIfNeeded() {
|
||||
entry(key: "appLoginPassword", value: System.getProperty("appLoginPassword"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ class HomeActivityEspressoTest {
|
||||
|
||||
intended(hasComponent(LoginActivity::class.java.name), times(1))
|
||||
|
||||
onView(isRoot()).perform(pressBack())
|
||||
//onView(isRoot()).perform(pressBack())
|
||||
|
||||
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ class IntroActivityEspressoTest {
|
||||
Intents.init()
|
||||
}
|
||||
|
||||
@Test
|
||||
/*@Test
|
||||
fun nextEachTimes() {
|
||||
|
||||
rule.launchActivity(Intent())
|
||||
@ -61,7 +61,7 @@ class IntroActivityEspressoTest {
|
||||
intended(hasComponent(IntroActivity::class.java.name), times(1))
|
||||
intended(hasComponent(LoginActivity::class.java.name), times(1))
|
||||
|
||||
}
|
||||
}*/
|
||||
|
||||
@Test
|
||||
fun nextBackRandomTimes() {
|
||||
|
BIN
app/src/main/ic_launcher-web.png
Normal file
After Width: | Height: | Size: 20 KiB |
@ -2,6 +2,7 @@ package apps.amine.bou.readerforselfoss
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.preference.PreferenceManager
|
||||
import android.support.constraint.ConstraintLayout
|
||||
import android.support.v7.app.AppCompatActivity
|
||||
import android.support.v7.widget.Toolbar
|
||||
@ -16,7 +17,7 @@ import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi
|
||||
import apps.amine.bou.readerforselfoss.api.selfoss.Spout
|
||||
import apps.amine.bou.readerforselfoss.api.selfoss.SuccessResponse
|
||||
import apps.amine.bou.readerforselfoss.utils.Config
|
||||
import apps.amine.bou.readerforselfoss.utils.isUrlValid
|
||||
import apps.amine.bou.readerforselfoss.utils.isBaseUrlValid
|
||||
import com.ftinc.scoop.Scoop
|
||||
|
||||
|
||||
@ -43,7 +44,8 @@ class AddSourceActivity : AppCompatActivity() {
|
||||
var api: SelfossApi? = null
|
||||
|
||||
try {
|
||||
api = SelfossApi(this, this@AddSourceActivity)
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(this)
|
||||
api = SelfossApi(this, this@AddSourceActivity, prefs.getBoolean("isSelfSignedCert", false))
|
||||
} catch (e: IllegalArgumentException) {
|
||||
mustLoginToAddSource()
|
||||
}
|
||||
@ -73,7 +75,7 @@ class AddSourceActivity : AppCompatActivity() {
|
||||
|
||||
val config = Config(this)
|
||||
|
||||
if (config.baseUrl.isEmpty() || !config.baseUrl.isUrlValid()) {
|
||||
if (config.baseUrl.isEmpty() || !config.baseUrl.isBaseUrlValid()) {
|
||||
mustLoginToAddSource()
|
||||
} else {
|
||||
|
||||
|
@ -139,7 +139,8 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
|
||||
|
||||
customTabActivityHelper = CustomTabActivityHelper()
|
||||
|
||||
api = SelfossApi(this, this@HomeActivity)
|
||||
val dirtyPref = PreferenceManager.getDefaultSharedPreferences(this)
|
||||
api = SelfossApi(this, this@HomeActivity, dirtyPref.getBoolean("isSelfSignedCert", false))
|
||||
items = ArrayList()
|
||||
|
||||
appColors = AppColors(this@HomeActivity)
|
||||
@ -185,9 +186,10 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
|
||||
} else {
|
||||
(recyclerView.adapter as ItemListAdapter).removeItemAtIndex(position)
|
||||
}
|
||||
tabNewBadge.setText("${items.size}").maybeShow()
|
||||
|
||||
mayBeEmpty()
|
||||
if (items.size > 0)
|
||||
tabNewBadge.setText("${items.size}").maybeShow()
|
||||
else
|
||||
tabNewBadge.hide()
|
||||
|
||||
} catch (e: IndexOutOfBoundsException) {}
|
||||
|
||||
@ -760,8 +762,10 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
|
||||
|
||||
api.readAll(ids).enqueue(object : Callback<SuccessResponse> {
|
||||
override fun onResponse(call: Call<SuccessResponse>, response: Response<SuccessResponse>) {
|
||||
if (response.body() != null && response.body()!!.isSuccess)
|
||||
if (response.body() != null && response.body()!!.isSuccess) {
|
||||
Toast.makeText(this@HomeActivity, R.string.all_posts_read, Toast.LENGTH_SHORT).show()
|
||||
tabNewBadge.removeBadge()
|
||||
}
|
||||
else
|
||||
Toast.makeText(this@HomeActivity, R.string.all_posts_not_read, Toast.LENGTH_SHORT).show()
|
||||
|
||||
|
@ -9,7 +9,7 @@ import android.view.View
|
||||
import agency.tango.materialintroscreen.MaterialIntroActivity
|
||||
import agency.tango.materialintroscreen.MessageButtonBehaviour
|
||||
import agency.tango.materialintroscreen.SlideFragmentBuilder
|
||||
|
||||
import android.support.v7.app.AppCompatDelegate
|
||||
|
||||
|
||||
class IntroActivity : MaterialIntroActivity() {
|
||||
@ -17,10 +17,12 @@ class IntroActivity : MaterialIntroActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
|
||||
|
||||
addSlide(SlideFragmentBuilder()
|
||||
.backgroundColor(R.color.colorPrimary)
|
||||
.buttonsColor(R.color.colorAccent)
|
||||
.image(R.mipmap.ic_launcher)
|
||||
.image(R.drawable.web_hi_res_512)
|
||||
.title(getString(R.string.intro_hello_title))
|
||||
.description(getString(R.string.intro_hello_message))
|
||||
.build())
|
||||
@ -28,7 +30,7 @@ class IntroActivity : MaterialIntroActivity() {
|
||||
addSlide(SlideFragmentBuilder()
|
||||
.backgroundColor(R.color.colorAccent)
|
||||
.buttonsColor(R.color.colorPrimary)
|
||||
.image(R.drawable.ic_info_outline_white_48dp)
|
||||
.image(R.drawable.ic_info_outline_white_48px)
|
||||
.title(getString(R.string.intro_needs_selfoss_title))
|
||||
.description(getString(R.string.intro_needs_selfoss_message))
|
||||
.build(),
|
||||
@ -40,7 +42,7 @@ class IntroActivity : MaterialIntroActivity() {
|
||||
addSlide(SlideFragmentBuilder()
|
||||
.backgroundColor(R.color.colorPrimaryDark)
|
||||
.buttonsColor(R.color.colorAccentDark)
|
||||
.image(R.drawable.ic_thumb_up_white_48dp)
|
||||
.image(R.drawable.ic_thumb_up_white_48px)
|
||||
.title(getString(R.string.intro_all_set_title))
|
||||
.description(getString(R.string.intro_all_set_message))
|
||||
.build())
|
||||
|
@ -15,10 +15,7 @@ import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import android.widget.Button
|
||||
import android.widget.EditText
|
||||
import android.widget.Switch
|
||||
import android.widget.TextView
|
||||
import android.widget.*
|
||||
|
||||
import com.google.firebase.analytics.FirebaseAnalytics
|
||||
import com.mikepenz.aboutlibraries.Libs
|
||||
@ -31,17 +28,21 @@ import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi
|
||||
import apps.amine.bou.readerforselfoss.api.selfoss.SuccessResponse
|
||||
import apps.amine.bou.readerforselfoss.utils.Config
|
||||
import apps.amine.bou.readerforselfoss.utils.checkAndDisplayStoreApk
|
||||
import apps.amine.bou.readerforselfoss.utils.isUrlValid
|
||||
import apps.amine.bou.readerforselfoss.utils.isBaseUrlValid
|
||||
import com.crashlytics.android.Crashlytics
|
||||
import com.ftinc.scoop.Scoop
|
||||
import io.fabric.sdk.android.Fabric
|
||||
|
||||
|
||||
class LoginActivity : AppCompatActivity() {
|
||||
|
||||
private var inValidCount: Int = 0
|
||||
private var isWithSelfSignedCert = false
|
||||
private var isWithLogin = false
|
||||
private var isWithHTTPLogin = false
|
||||
|
||||
private lateinit var settings: SharedPreferences
|
||||
private lateinit var editor: SharedPreferences.Editor
|
||||
private lateinit var mFirebaseAnalytics: FirebaseAnalytics
|
||||
private lateinit var mUrlView: EditText
|
||||
private lateinit var mLoginView: TextView
|
||||
@ -50,6 +51,7 @@ class LoginActivity : AppCompatActivity() {
|
||||
private lateinit var mPasswordView: EditText
|
||||
private lateinit var mHTTPPasswordView: EditText
|
||||
private lateinit var mLoginFormView: View
|
||||
private var logErrors: Boolean = false
|
||||
|
||||
|
||||
|
||||
@ -74,6 +76,10 @@ class LoginActivity : AppCompatActivity() {
|
||||
|
||||
|
||||
settings = getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE)
|
||||
logErrors = settings.getBoolean("loging_debug", false)
|
||||
|
||||
editor = settings.edit()
|
||||
|
||||
if (settings.getString("url", "").isNotEmpty()) {
|
||||
goToMain()
|
||||
} else {
|
||||
@ -96,6 +102,15 @@ class LoginActivity : AppCompatActivity() {
|
||||
val mPasswordLayout: TextInputLayout = findViewById(R.id.passwordLayout)
|
||||
val mHTTPPasswordLayout: TextInputLayout = findViewById(R.id.httpPasswordInput)
|
||||
val mEmailSignInButton: Button = findViewById(R.id.email_sign_in_button)
|
||||
val selfHostedSwitch: Switch = findViewById(R.id.withSelfhostedCert)
|
||||
val warningTextview: TextView = findViewById(R.id.warningText)
|
||||
|
||||
selfHostedSwitch.setOnCheckedChangeListener {_, b ->
|
||||
isWithSelfSignedCert = !isWithSelfSignedCert
|
||||
val visi: Int = if (b) View.VISIBLE else View.GONE
|
||||
|
||||
warningTextview.visibility = visi
|
||||
}
|
||||
|
||||
mPasswordView.setOnEditorActionListener(TextView.OnEditorActionListener { _, id, _ ->
|
||||
if (id == R.id.login || id == EditorInfo.IME_NULL) {
|
||||
@ -149,7 +164,7 @@ class LoginActivity : AppCompatActivity() {
|
||||
var cancel = false
|
||||
var focusView: View? = null
|
||||
|
||||
if (!url.isUrlValid()) {
|
||||
if (!url.isBaseUrlValid()) {
|
||||
mUrlView.error = getString(R.string.login_url_problem)
|
||||
focusView = mUrlView
|
||||
cancel = true
|
||||
@ -186,17 +201,17 @@ class LoginActivity : AppCompatActivity() {
|
||||
} else {
|
||||
showProgress(true)
|
||||
|
||||
val editor = settings.edit()
|
||||
editor.putString("url", url)
|
||||
editor.putString("login", login)
|
||||
editor.putString("httpUserName", httpLogin)
|
||||
editor.putString("password", password)
|
||||
editor.putString("httpPassword", httpPassword)
|
||||
editor.putBoolean("isSelfSignedCert", isWithSelfSignedCert)
|
||||
editor.apply()
|
||||
|
||||
val api = SelfossApi(this, this@LoginActivity)
|
||||
val api = SelfossApi(this, this@LoginActivity, isWithSelfSignedCert)
|
||||
api.login().enqueue(object : Callback<SuccessResponse> {
|
||||
private fun preferenceError() {
|
||||
private fun preferenceError(t: Throwable) {
|
||||
editor.remove("url")
|
||||
editor.remove("login")
|
||||
editor.remove("httpUserName")
|
||||
@ -208,6 +223,11 @@ class LoginActivity : AppCompatActivity() {
|
||||
mPasswordView.error = getString(R.string.wrong_infos)
|
||||
mHTTPLoginView.error = getString(R.string.wrong_infos)
|
||||
mHTTPPasswordView.error = getString(R.string.wrong_infos)
|
||||
if (logErrors) {
|
||||
Crashlytics.log(100, "LOGIN_DEBUG_ERRROR", t.message)
|
||||
Crashlytics.logException(t)
|
||||
Toast.makeText(this@LoginActivity, t.message, Toast.LENGTH_LONG).show()
|
||||
}
|
||||
showProgress(false)
|
||||
}
|
||||
|
||||
@ -216,12 +236,12 @@ class LoginActivity : AppCompatActivity() {
|
||||
mFirebaseAnalytics.logEvent(FirebaseAnalytics.Event.LOGIN, Bundle())
|
||||
goToMain()
|
||||
} else {
|
||||
preferenceError()
|
||||
preferenceError(Exception("No response body..."))
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<SuccessResponse>, t: Throwable) {
|
||||
preferenceError()
|
||||
preferenceError(t)
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -260,6 +280,7 @@ class LoginActivity : AppCompatActivity() {
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
menuInflater.inflate(R.menu.login_menu, menu)
|
||||
menu.findItem(R.id.loging_debug).isChecked = logErrors
|
||||
return true
|
||||
}
|
||||
|
||||
@ -273,6 +294,14 @@ class LoginActivity : AppCompatActivity() {
|
||||
.start(this)
|
||||
return true
|
||||
}
|
||||
R.id.loging_debug -> {
|
||||
val newState = !item.isChecked
|
||||
item.isChecked = newState
|
||||
logErrors = newState
|
||||
editor.putBoolean("loging_debug", newState)
|
||||
editor.apply()
|
||||
return true
|
||||
}
|
||||
else -> return super.onOptionsItemSelected(item)
|
||||
}
|
||||
}
|
||||
|
@ -20,20 +20,35 @@ import java.io.IOException
|
||||
class MyApp : MultiDexApplication() {
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
if (!BuildConfig.DEBUG)
|
||||
Fabric.with(this, Crashlytics())
|
||||
Fabric.with(this, Crashlytics())
|
||||
|
||||
initAmplify()
|
||||
|
||||
initCache()
|
||||
|
||||
initDrawerImageLoader()
|
||||
|
||||
initTheme()
|
||||
|
||||
tryToHandleBug()
|
||||
|
||||
}
|
||||
|
||||
private fun initAmplify() {
|
||||
Amplify.initSharedInstance(this)
|
||||
.setFeedbackEmailAddress(getString(R.string.feedback_email))
|
||||
.setAlwaysShow(BuildConfig.DEBUG)
|
||||
.applyAllDefaultRules()
|
||||
.setFeedbackEmailAddress(getString(R.string.feedback_email))
|
||||
.applyAllDefaultRules()
|
||||
}
|
||||
|
||||
private fun initCache() {
|
||||
try {
|
||||
Reservoir.init(this, 8192) //in bytes
|
||||
} catch (e: IOException) {
|
||||
//failure
|
||||
}
|
||||
}
|
||||
|
||||
private fun initDrawerImageLoader() {
|
||||
DrawerImageLoader.init(object : AbstractDrawerImageLoader() {
|
||||
override fun set(imageView: ImageView?, uri: Uri?, placeholder: Drawable?, tag: String?) {
|
||||
Glide.with(imageView?.context).load(uri).placeholder(placeholder).into(imageView)
|
||||
@ -47,6 +62,9 @@ class MyApp : MultiDexApplication() {
|
||||
return baseContext.resources.getDrawable(R.mipmap.ic_launcher)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun initTheme() {
|
||||
Scoop.waffleCone()
|
||||
.addFlavor(getString(R.string.default_theme), R.style.NoBar, true)
|
||||
.addFlavor(getString(R.string.default_dark_theme), R.style.NoBarDark)
|
||||
@ -64,6 +82,17 @@ class MyApp : MultiDexApplication() {
|
||||
.addFlavor(getString(R.string.red_teal_dark_theme), R.style.NoBarRedTealDark)
|
||||
.setSharedPreferences(PreferenceManager.getDefaultSharedPreferences(this))
|
||||
.initialize()
|
||||
}
|
||||
|
||||
private fun tryToHandleBug() {
|
||||
val oldHandler = Thread.getDefaultUncaughtExceptionHandler()
|
||||
|
||||
Thread.setDefaultUncaughtExceptionHandler { thread, e ->
|
||||
if (e is java.lang.NoClassDefFoundError && e.stackTrace.asList().any { it.toString().contains("android.view.ViewDebug") })
|
||||
Unit
|
||||
else
|
||||
oldHandler.uncaughtException(thread, e)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -22,6 +22,7 @@ import apps.amine.bou.readerforselfoss.api.mercury.MercuryApi
|
||||
import apps.amine.bou.readerforselfoss.api.mercury.ParsedContent
|
||||
import apps.amine.bou.readerforselfoss.utils.buildCustomTabsIntent
|
||||
import apps.amine.bou.readerforselfoss.utils.customtabs.CustomTabActivityHelper
|
||||
import apps.amine.bou.readerforselfoss.utils.openItemUrl
|
||||
import apps.amine.bou.readerforselfoss.utils.shareLink
|
||||
import com.ftinc.scoop.Scoop
|
||||
|
||||
@ -84,10 +85,12 @@ class ReaderActivity : DragDismissActivity() {
|
||||
}
|
||||
|
||||
browserBtn.setOnClickListener {
|
||||
val intent = Intent(Intent.ACTION_VIEW)
|
||||
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
intent.data = Uri.parse(response.body()!!.url)
|
||||
startActivity(intent)
|
||||
this@ReaderActivity.openItemUrl(
|
||||
response.body()!!.url,
|
||||
customTabsIntent,
|
||||
false,
|
||||
false,
|
||||
this@ReaderActivity)
|
||||
}
|
||||
|
||||
hideProgressBar()
|
||||
@ -97,12 +100,13 @@ class ReaderActivity : DragDismissActivity() {
|
||||
override fun onFailure(call: Call<ParsedContent>, t: Throwable) = openInBrowserAfterFailing()
|
||||
|
||||
private fun openInBrowserAfterFailing() {
|
||||
CustomTabActivityHelper.openCustomTab(this@ReaderActivity, customTabsIntent, Uri.parse(url)
|
||||
) { _, uri ->
|
||||
val intent = Intent(Intent.ACTION_VIEW, uri)
|
||||
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
startActivity(intent)
|
||||
}
|
||||
this@ReaderActivity.openItemUrl(
|
||||
url,
|
||||
customTabsIntent,
|
||||
true,
|
||||
false,
|
||||
this@ReaderActivity
|
||||
)
|
||||
finish()
|
||||
}
|
||||
})
|
||||
|
@ -2,6 +2,7 @@ package apps.amine.bou.readerforselfoss
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.preference.PreferenceManager
|
||||
import android.support.v7.app.AppCompatActivity
|
||||
import android.support.v7.widget.LinearLayoutManager
|
||||
import android.support.v7.widget.RecyclerView
|
||||
@ -36,7 +37,10 @@ class SourcesActivity : AppCompatActivity() {
|
||||
val mFab: FloatingActionButton = findViewById(R.id.fab)
|
||||
val mRecyclerView: RecyclerView = findViewById(R.id.activity_sources)
|
||||
val mLayoutManager = LinearLayoutManager(this)
|
||||
val api = SelfossApi(this, this@SourcesActivity)
|
||||
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(this)
|
||||
|
||||
val api = SelfossApi(this, this@SourcesActivity, prefs.getBoolean("isSelfSignedCert", false))
|
||||
var items: ArrayList<Sources> = ArrayList()
|
||||
|
||||
mFab.attachToRecyclerView(mRecyclerView)
|
||||
|
@ -212,7 +212,7 @@ class ItemCardAdapter(private val app: Activity,
|
||||
helper.bindCustomTabsService(app)
|
||||
|
||||
mView.setOnClickListener {
|
||||
c.openItemUrl(items[adapterPosition],
|
||||
c.openItemUrl(items[adapterPosition].getLinkDecoded(),
|
||||
customTabsIntent,
|
||||
internalBrowser,
|
||||
articleViewer,
|
||||
|
@ -223,7 +223,7 @@ class ItemListAdapter(private val app: Activity,
|
||||
|
||||
if (!clickBehavior) {
|
||||
mView.setOnClickListener {
|
||||
c.openItemUrl(items[adapterPosition],
|
||||
c.openItemUrl(items[adapterPosition].getLinkDecoded(),
|
||||
customTabsIntent,
|
||||
internalBrowser,
|
||||
articleViewer,
|
||||
@ -236,7 +236,7 @@ class ItemListAdapter(private val app: Activity,
|
||||
} else {
|
||||
mView.setOnClickListener { actionBarShowHide() }
|
||||
mView.setOnLongClickListener {
|
||||
c.openItemUrl(items[adapterPosition],
|
||||
c.openItemUrl(items[adapterPosition].getLinkDecoded(),
|
||||
customTabsIntent,
|
||||
internalBrowser,
|
||||
articleViewer,
|
||||
|
@ -23,26 +23,66 @@ import retrofit2.Retrofit
|
||||
import retrofit2.converter.gson.GsonConverterFactory
|
||||
|
||||
import apps.amine.bou.readerforselfoss.utils.Config
|
||||
import java.security.cert.CertificateException
|
||||
import java.security.cert.X509Certificate
|
||||
import javax.net.ssl.*
|
||||
|
||||
|
||||
// codebeat:disable[ARITY,TOO_MANY_FUNCTIONS]
|
||||
class SelfossApi(c: Context, callingActivity: Activity) {
|
||||
class SelfossApi(c: Context, callingActivity: Activity, isWithSelfSignedCert: Boolean) {
|
||||
|
||||
private lateinit var service: SelfossService
|
||||
private val config: Config = Config(c)
|
||||
private val userName: String
|
||||
private val password: String
|
||||
|
||||
fun OkHttpClient.Builder.maybeWithSelfSigned(isWithSelfSignedCert: Boolean): OkHttpClient.Builder =
|
||||
if (isWithSelfSignedCert) {
|
||||
try {
|
||||
// Create a trust manager that does not validate certificate chains
|
||||
val trustAllCerts = arrayOf<TrustManager>(object : X509TrustManager {
|
||||
override fun getAcceptedIssuers(): Array<X509Certificate> =
|
||||
arrayOf()
|
||||
|
||||
@Throws(CertificateException::class)
|
||||
override fun checkClientTrusted(chain: Array<java.security.cert.X509Certificate>, authType: String) {
|
||||
}
|
||||
|
||||
@Throws(CertificateException::class)
|
||||
override fun checkServerTrusted(chain: Array<java.security.cert.X509Certificate>, authType: String) {
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
// Install the all-trusting trust manager
|
||||
val sslContext = SSLContext.getInstance("SSL")
|
||||
sslContext.init(null, trustAllCerts, java.security.SecureRandom())
|
||||
|
||||
val sslSocketFactory = sslContext.socketFactory
|
||||
|
||||
OkHttpClient.Builder()
|
||||
.sslSocketFactory(sslSocketFactory, trustAllCerts[0] as X509TrustManager)
|
||||
.hostnameVerifier { _, _ -> true }
|
||||
|
||||
} catch (e: Exception) {
|
||||
throw RuntimeException(e)
|
||||
}
|
||||
|
||||
} else {
|
||||
this
|
||||
}
|
||||
|
||||
fun Credentials.createAuthenticator(): DispatchingAuthenticator =
|
||||
DispatchingAuthenticator.Builder()
|
||||
.with("digest", DigestAuthenticator(this))
|
||||
.with("basic", BasicAuthenticator(this))
|
||||
.build()
|
||||
|
||||
fun DispatchingAuthenticator.getHttpClien(): OkHttpClient {
|
||||
fun DispatchingAuthenticator.getHttpClien(isWithSelfSignedCert: Boolean): OkHttpClient {
|
||||
val authCache = ConcurrentHashMap<String, CachingAuthenticator>()
|
||||
return OkHttpClient
|
||||
.Builder()
|
||||
.maybeWithSelfSigned(isWithSelfSignedCert)
|
||||
.authenticator(CachingAuthenticatorDecorator(this, authCache))
|
||||
.addInterceptor(AuthenticationCacheInterceptor(authCache))
|
||||
.build()
|
||||
@ -71,7 +111,7 @@ class SelfossApi(c: Context, callingActivity: Activity) {
|
||||
Retrofit
|
||||
.Builder()
|
||||
.baseUrl(config.baseUrl)
|
||||
.client(authenticator.getHttpClien())
|
||||
.client(authenticator.getHttpClien(isWithSelfSignedCert))
|
||||
.addConverterFactory(GsonConverterFactory.create(gson))
|
||||
.build()
|
||||
service = retrofit.create(SelfossService::class.java)
|
||||
|
@ -119,6 +119,7 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
|
||||
protected boolean isValidFragment(String fragmentName) {
|
||||
return PreferenceFragment.class.getName().equals(fragmentName)
|
||||
|| GeneralPreferenceFragment.class.getName().equals(fragmentName)
|
||||
|| DebugPreferenceFragment.class.getName().equals(fragmentName)
|
||||
|| LinksPreferenceFragment.class.getName().equals(fragmentName);
|
||||
}
|
||||
|
||||
@ -157,6 +158,26 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
|
||||
}
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
|
||||
public static class DebugPreferenceFragment extends PreferenceFragment {
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
addPreferencesFromResource(R.xml.pref_debug);
|
||||
setHasOptionsMenu(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
int id = item.getItemId();
|
||||
if (id == android.R.id.home) {
|
||||
getActivity().finish();
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This fragment shows general preferences only. It is used when the
|
||||
* activity is showing a two-pane settings UI.
|
||||
@ -206,7 +227,9 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
|
||||
public void onHeaderClick(Header header, int position) {
|
||||
super.onHeaderClick(header, position);
|
||||
if (header.id == R.id.theme_change) {
|
||||
getBaseContext().startActivity(ScoopSettingsActivity.createIntent(getApplicationContext()));
|
||||
Intent intent = ScoopSettingsActivity.createIntent(getApplicationContext());
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
getApplicationContext().startActivity(intent);
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
@ -36,7 +36,10 @@ fun Context.checkAndDisplayStoreApk() = {
|
||||
} else Unit
|
||||
}
|
||||
|
||||
fun String.isUrlValid(): Boolean {
|
||||
fun String.isUrlValid(): Boolean =
|
||||
HttpUrl.parse(this) != null && Patterns.WEB_URL.matcher(this).matches()
|
||||
|
||||
fun String.isBaseUrlValid(): Boolean {
|
||||
val baseUrl = HttpUrl.parse(this)
|
||||
var existsAndEndsWithSlash = false
|
||||
if (baseUrl != null) {
|
||||
|
@ -50,15 +50,13 @@ fun Context.buildCustomTabsIntent(): CustomTabsIntent {
|
||||
return intentBuilder.build()
|
||||
}
|
||||
|
||||
fun Context.openItemUrl(i: Item,
|
||||
fun Context.openItemUrl(linkDecoded: String,
|
||||
customTabsIntent: CustomTabsIntent,
|
||||
internalBrowser: Boolean,
|
||||
articleViewer: Boolean,
|
||||
app: Activity) {
|
||||
if (!internalBrowser) {
|
||||
val intent = Intent(Intent.ACTION_VIEW)
|
||||
intent.data = Uri.parse(i.getLinkDecoded())
|
||||
app.startActivity(intent)
|
||||
if (!internalBrowser || !linkDecoded.isUrlValid()) {
|
||||
openInBrowser(linkDecoded, app)
|
||||
} else {
|
||||
if (articleViewer) {
|
||||
val intent = Intent(this, ReaderActivity::class.java)
|
||||
@ -68,15 +66,25 @@ fun Context.openItemUrl(i: Item,
|
||||
.setDragElasticity(DragDismissIntentBuilder.DragElasticity.NORMAL) // Larger elasticities will make it easier to dismiss.
|
||||
.build(intent)
|
||||
|
||||
intent.putExtra("url", i.getLinkDecoded())
|
||||
intent.putExtra("url", linkDecoded)
|
||||
app.startActivity(intent)
|
||||
} else {
|
||||
CustomTabActivityHelper.openCustomTab(app, customTabsIntent, Uri.parse(i.getLinkDecoded())
|
||||
) { _, uri ->
|
||||
val intent = Intent(Intent.ACTION_VIEW, uri)
|
||||
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
startActivity(intent)
|
||||
try {
|
||||
CustomTabActivityHelper.openCustomTab(app, customTabsIntent, Uri.parse(linkDecoded)
|
||||
) { _, uri ->
|
||||
val intent = Intent(Intent.ACTION_VIEW, uri)
|
||||
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
startActivity(intent)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
openInBrowser(linkDecoded, app)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun openInBrowser(linkDecoded: String, app: Activity) {
|
||||
val intent = Intent(Intent.ACTION_VIEW)
|
||||
intent.data = Uri.parse(linkDecoded)
|
||||
app.startActivity(intent)
|
||||
}
|
||||
|
@ -1,9 +0,0 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M11,17h2v-6h-2v6zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM11,9h2L13,7h-2v2z"/>
|
||||
</vector>
|
@ -1,9 +0,0 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M19.43,12.98c0.04,-0.32 0.07,-0.64 0.07,-0.98s-0.03,-0.66 -0.07,-0.98l2.11,-1.65c0.19,-0.15 0.24,-0.42 0.12,-0.64l-2,-3.46c-0.12,-0.22 -0.39,-0.3 -0.61,-0.22l-2.49,1c-0.52,-0.4 -1.08,-0.73 -1.69,-0.98l-0.38,-2.65C14.46,2.18 14.25,2 14,2h-4c-0.25,0 -0.46,0.18 -0.49,0.42l-0.38,2.65c-0.61,0.25 -1.17,0.59 -1.69,0.98l-2.49,-1c-0.23,-0.09 -0.49,0 -0.61,0.22l-2,3.46c-0.13,0.22 -0.07,0.49 0.12,0.64l2.11,1.65c-0.04,0.32 -0.07,0.65 -0.07,0.98s0.03,0.66 0.07,0.98l-2.11,1.65c-0.19,0.15 -0.24,0.42 -0.12,0.64l2,3.46c0.12,0.22 0.39,0.3 0.61,0.22l2.49,-1c0.52,0.4 1.08,0.73 1.69,0.98l0.38,2.65c0.03,0.24 0.24,0.42 0.49,0.42h4c0.25,0 0.46,-0.18 0.49,-0.42l0.38,-2.65c0.61,-0.25 1.17,-0.59 1.69,-0.98l2.49,1c0.23,0.09 0.49,0 0.61,-0.22l2,-3.46c0.12,-0.22 0.07,-0.49 -0.12,-0.64l-2.11,-1.65zM12,15.5c-1.93,0 -3.5,-1.57 -3.5,-3.5s1.57,-3.5 3.5,-3.5 3.5,1.57 3.5,3.5 -1.57,3.5 -3.5,3.5z"/>
|
||||
</vector>
|
BIN
app/src/main/res/drawable-hdpi/ic_bug_report.png
Normal file
After Width: | Height: | Size: 271 B |
BIN
app/src/main/res/drawable-hdpi/ic_info_outline.png
Normal file
After Width: | Height: | Size: 551 B |
Before Width: | Height: | Size: 953 B |
BIN
app/src/main/res/drawable-hdpi/ic_settings.png
Normal file
After Width: | Height: | Size: 498 B |
BIN
app/src/main/res/drawable-mdpi/ic_bug_report.png
Normal file
After Width: | Height: | Size: 212 B |
BIN
app/src/main/res/drawable-mdpi/ic_info_outline.png
Normal file
After Width: | Height: | Size: 355 B |
Before Width: | Height: | Size: 655 B |
BIN
app/src/main/res/drawable-mdpi/ic_settings.png
Normal file
After Width: | Height: | Size: 339 B |
BIN
app/src/main/res/drawable-xhdpi/ic_bug_report.png
Normal file
After Width: | Height: | Size: 312 B |
BIN
app/src/main/res/drawable-xhdpi/ic_info_outline.png
Normal file
After Width: | Height: | Size: 725 B |
Before Width: | Height: | Size: 1.2 KiB |
BIN
app/src/main/res/drawable-xhdpi/ic_settings.png
Normal file
After Width: | Height: | Size: 606 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_bug_report.png
Normal file
After Width: | Height: | Size: 466 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_info_outline.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 1.9 KiB |
BIN
app/src/main/res/drawable-xxhdpi/ic_settings.png
Normal file
After Width: | Height: | Size: 907 B |
BIN
app/src/main/res/drawable-xxxhdpi/ic_bug_report.png
Normal file
After Width: | Height: | Size: 573 B |
BIN
app/src/main/res/drawable-xxxhdpi/ic_info_outline.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 2.6 KiB |
BIN
app/src/main/res/drawable-xxxhdpi/ic_settings.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
@ -2,12 +2,12 @@
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item
|
||||
android:drawable="@color/white"/>
|
||||
android:drawable="@color/ic_launcher_background"/>
|
||||
|
||||
<item>
|
||||
<bitmap
|
||||
android:gravity="center"
|
||||
android:src="@mipmap/ic_launcher"/>
|
||||
android:src="@mipmap/ic_launcher_foreground"/>
|
||||
</item>
|
||||
|
||||
</layer-list>
|
4
app/src/main/res/drawable/ic_info_outline_white_48px.xml
Normal file
@ -0,0 +1,4 @@
|
||||
<vector android:height="24dp" android:viewportHeight="24.0"
|
||||
android:viewportWidth="24.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FFFFFF" android:pathData="M11,17h2v-6h-2v6zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM11,9h2L13,7h-2v2z"/>
|
||||
</vector>
|
4
app/src/main/res/drawable/ic_thumb_up_white_48px.xml
Normal file
@ -0,0 +1,4 @@
|
||||
<vector android:height="24dp" android:viewportHeight="24.0"
|
||||
android:viewportWidth="24.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FFFFFF" android:pathData="M1,21h4L5,9L1,9v12zM23,10c0,-1.1 -0.9,-2 -2,-2h-6.31l0.95,-4.57 0.03,-0.32c0,-0.41 -0.17,-0.79 -0.44,-1.06L14.17,1 7.59,7.59C7.22,7.95 7,8.45 7,9v10c0,1.1 0.9,2 2,2h9c0.83,0 1.54,-0.5 1.84,-1.22l3.02,-7.05c0.09,-0.23 0.14,-0.47 0.14,-0.73v-1.91l-0.01,-0.01L23,10z"/>
|
||||
</vector>
|
BIN
app/src/main/res/drawable/web_hi_res_512.png
Normal file
After Width: | Height: | Size: 20 KiB |
@ -138,6 +138,20 @@
|
||||
android:hint="@string/prompt_http_password" />
|
||||
</android.support.design.widget.TextInputLayout>
|
||||
|
||||
<Switch
|
||||
android:id="@+id/withSelfhostedCert"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/self_hosted_cert_switch" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/warningText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/self_signed_cert_warning"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
|
||||
android:visibility="gone" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/email_sign_in_button"
|
||||
style="?android:textAppearanceSmall"
|
||||
|
11
app/src/main/res/layout/switch_item.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<Switch
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_centerVertical="true" />
|
||||
</RelativeLayout>
|
@ -2,6 +2,14 @@
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item
|
||||
android:id="@+id/loging_debug"
|
||||
android:checkable="true"
|
||||
android:checked="false"
|
||||
android:icon="@drawable/ic_bug_report"
|
||||
android:title="@string/login_menu_debug"
|
||||
app:showAsAction="never" />
|
||||
|
||||
<item android:id="@+id/about"
|
||||
android:title="@string/action_about"
|
||||
android:orderInCategory="102"
|
||||
|
5
app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/ic_launcher_background"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
5
app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/ic_launcher_background"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
BIN
app/src/main/res/mipmap-hdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_background.png
Normal file
After Width: | Height: | Size: 182 B |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
Normal file
After Width: | Height: | Size: 3.5 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_background.png
Normal file
After Width: | Height: | Size: 125 B |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_background.png
Normal file
After Width: | Height: | Size: 261 B |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
Normal file
After Width: | Height: | Size: 4.7 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 5.1 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher_background.png
Normal file
After Width: | Height: | Size: 487 B |
BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
Normal file
After Width: | Height: | Size: 8.4 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 6.9 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png
Normal file
After Width: | Height: | Size: 803 B |
BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
Normal file
After Width: | Height: | Size: 11 KiB |
@ -131,4 +131,11 @@
|
||||
<string name="blue_amber_dark_theme">Bleu/Ambre/Foncé</string>
|
||||
<string name="indigo_pink_dark_theme">Indigo/Rose/Foncé</string>
|
||||
<string name="red_teal_dark_theme">Rouge/Sarcelle/Foncé</string>
|
||||
<string name="pref_header_debug">Debug</string>
|
||||
<string name="login_debug_title">Activez pour loguer toutes les erreurs de conexion</string>
|
||||
<string name="login_debug_on">Toutes les erreurs de connexion vont être loguées</string>
|
||||
<string name="login_debug_off">Aucune erreur de connexion ne sera loguée</string>
|
||||
<string name="login_menu_debug">Debug</string>
|
||||
<string name="self_hosted_cert_switch">Certificat auto-signé ?</string>
|
||||
<string name="self_signed_cert_warning">Pour des raisons de sécurités, les certificats auto-signés sont désactivés par défaut. En les activant, je ne serais pas responsable de quelconques problèmes de sécurité rencontrés.</string>
|
||||
</resources>
|
@ -131,4 +131,11 @@
|
||||
<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>
|
||||
</resources>
|
4
app/src/main/res/values/ic_launcher_background.xml
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="ic_launcher_background">#FFFFFF</color>
|
||||
</resources>
|
@ -133,4 +133,11 @@
|
||||
<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>
|
||||
</resources>
|
10
app/src/main/res/xml/pref_debug.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<SwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:key="loging_debug"
|
||||
android:summaryOff="@string/login_debug_off"
|
||||
android:summaryOn="@string/login_debug_on"
|
||||
android:title="@string/login_debug_title" />
|
||||
</PreferenceScreen>
|
@ -5,6 +5,11 @@
|
||||
android:icon="@drawable/ic_settings_black_24dp"
|
||||
android:title="@string/pref_header_general"/>
|
||||
|
||||
<header
|
||||
android:fragment="apps.amine.bou.readerforselfoss.settings.SettingsActivity$DebugPreferenceFragment"
|
||||
android:icon="@drawable/ic_bug_report"
|
||||
android:title="@string/pref_header_debug"/>
|
||||
|
||||
<header
|
||||
android:id="@+id/theme_change"
|
||||
android:icon="@drawable/ic_color_lens_black_24dp"
|
||||
|
@ -1,13 +1,13 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.1.3'
|
||||
ext.kotlin_version = '1.1.3-2'
|
||||
repositories {
|
||||
maven { url 'https://maven.google.com' }
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.0.0-alpha5'
|
||||
classpath 'com.android.tools.build:gradle:3.0.0-beta2'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
|
56
circle.yml
@ -1,56 +0,0 @@
|
||||
machine:
|
||||
timezone: Europe/Paris
|
||||
java:
|
||||
version: 'oraclejdk8'
|
||||
environment:
|
||||
ANDROID_HOME: /usr/local/android-sdk-linux
|
||||
PATH: ANDROID_HOME:$ANDROID_HOME/platform-tools:$ANDROID_BUUILD:$ANDROID_HOME/tools:$PATH
|
||||
_JAVA_OPTIONS: "-Xms512m -Xmx1024m"
|
||||
GRADLE_OPTS: '-Dorg.gradle.jvmargs="-Xmx2048m -XX:+HeapDumpOnOutOfMemoryError"'
|
||||
|
||||
dependencies:
|
||||
pre:
|
||||
- touch app/google-services.json
|
||||
- echo $GOOGLE_SERVICES_JSON > app/google-services.json
|
||||
- touch app/src/main/res/values/secrets.xml
|
||||
- echo $SECRETS_XML > app/src/main/res/values/secrets.xml
|
||||
- mkdir app/src/main/res/mipmap-hdpi
|
||||
- convert -size 72x72 xc:white app/src/main/res/mipmap-hdpi/ic_launcher.png
|
||||
- mkdir app/src/main/res/mipmap-mdpi
|
||||
- convert -size 48x48 xc:white app/src/main/res/mipmap-mdpi/ic_launcher.png
|
||||
- mkdir app/src/main/res/mipmap-xhdpi
|
||||
- convert -size 96x96 xc:white app/src/main/res/mipmap-xhdpi/ic_launcher.png
|
||||
- mkdir app/src/main/res/mipmap-xxhdpi
|
||||
- convert -size 192x192 xc:white app/src/main/res/mipmap-xxhdpi/ic_launcher.png
|
||||
- mkdir app/src/main/res/mipmap-xxxhdpi
|
||||
- convert -size 512x512 xc:white app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
|
||||
|
||||
cache_directories:
|
||||
- ~/.gradle
|
||||
- ~/.android
|
||||
|
||||
override:
|
||||
- echo y | android update sdk --no-ui --filter "android-26,build-tools-26.0.0"
|
||||
- echo y | android update sdk --no-ui --all --filter "platform-tools, tools"
|
||||
- echo y | android update sdk --no-ui --all --filter "android-26, build-tools-26.0.0"
|
||||
- echo y | android update sdk --no-ui --all --filter "extra-android-m2repository"
|
||||
- echo y | android update sdk --no-ui --all --filter "extra-android-support"
|
||||
- echo y | android update sdk --no-ui --all --filter "extra-google-m2repository"
|
||||
- echo y | android update sdk --no-ui --all --filter "extra-google-google_play_services"
|
||||
|
||||
test:
|
||||
override:
|
||||
- (TERM="dumb" ./gradlew assemble --configure-on-demand --no-daemon -P crashlyticsdemoApikey=$FABRIC_API_KEY -P crashlyticsdemoApisecret=$FABRIC_API_SECRET -P appLoginUrl=$LOGIN_URL -P appLoginUsername=$LOGIN_USER_NAME -P appLoginPassword=$LOGIN_PASSWORD -PdisablePreDex -Pandroid.threadPoolSize=1 -Porg.gradle.parallel=false):
|
||||
timeout: 1440
|
||||
- emulator -avd circleci-android22 -no-window:
|
||||
background: true
|
||||
parallel: true
|
||||
- circle-android wait-for-boot
|
||||
- sleep 30
|
||||
- adb shell input keyevent 82
|
||||
- adb shell input tap 650 300
|
||||
- (TERM="dumb" ./gradlew connectedAndroidTest --configure-on-demand --no-daemon --stacktrace -P crashlyticsdemoApikey=$FABRIC_API_KEY -P crashlyticsdemoApisecret=$FABRIC_API_SECRET -P appLoginUrl=$LOGIN_URL -P appLoginUsername=$LOGIN_USER_NAME -P appLoginPassword=$LOGIN_PASSWORD -PdisablePreDex -Pandroid.threadPoolSize=1 -Porg.gradle.parallel=false):
|
||||
timeout: 1440
|
||||
- cp -r app/build/outputs $CIRCLE_ARTIFACTS
|
||||
- cp -r app/build/reports/androidTests $CIRCLE_ARTIFACTS
|
||||
- cp -r app/build/outputs/androidTest-results/* $CIRCLE_TEST_REPORTS
|
4
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,6 +1,6 @@
|
||||
#Sun Jul 02 08:13:37 CEST 2017
|
||||
#Wed Aug 16 19:45:22 CEST 2017
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-milestone-1-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-rc-1-all.zip
|
||||
|