Compare commits

..

10 Commits

Author SHA1 Message Date
3b6891c84a App was a little slow with livedata. 2018-10-13 10:24:58 +02:00
4901e7174c Still trying to fix the build issue. 2018-10-13 04:52:55 +02:00
8d70e68fe2 Trying to fix build issue. 2018-10-12 22:50:43 +02:00
d3e1527b70 AS changes gradle version to one that does not exist. 2018-10-12 22:29:33 +02:00
0c201301f2 Replaced reservoir by room. 2018-10-12 22:04:47 +02:00
6090590f24 Imports cleaning. Libraries update. 2018-10-12 21:01:39 +02:00
06b88c783d Auto migration to android x. 2018-10-12 20:36:18 +02:00
bb75ebf635 Merge branch 'master' of github.com:aminecmi/ReaderforSelfoss 2018-10-07 22:30:30 +02:00
7d7d0014be Fixes #83. The issue wasn't selfoss related at all... 2018-10-07 22:30:07 +02:00
b3f8d44794 New Crowdin translations (#224)
* New translations strings.xml (Korean)

* New translations strings.xml (Korean)

* New translations strings.xml (Korean)
2018-10-03 14:35:03 +02:00
56 changed files with 490 additions and 439 deletions

View File

@ -24,6 +24,8 @@ def versionNameFromGit() {
return gitVersion() return gitVersion()
} }
apply plugin: 'kotlin-kapt'
apply plugin: 'com.android.application' apply plugin: 'com.android.application'
apply plugin: 'kotlin-android' apply plugin: 'kotlin-android'
@ -36,7 +38,7 @@ android {
targetCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8
} }
compileSdkVersion 28 compileSdkVersion 28
buildToolsVersion '28.0.2' buildToolsVersion '28.0.3'
defaultConfig { defaultConfig {
applicationId "apps.amine.bou.readerforselfoss" applicationId "apps.amine.bou.readerforselfoss"
minSdkVersion 16 minSdkVersion 16
@ -53,7 +55,7 @@ android {
vectorDrawables.useSupportLibrary = true vectorDrawables.useSupportLibrary = true
// tests // tests
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
} }
buildTypes { buildTypes {
release { release {
@ -85,32 +87,32 @@ android {
dependencies { dependencies {
// Testing // Testing
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0-beta02'
androidTestImplementation 'com.android.support.test:runner:1.0.1' androidTestImplementation 'androidx.test:runner:1.1.0-beta02'
// Espresso-contrib for DatePicker, RecyclerView, Drawer actions, Accessibility checks, CountingIdlingResource // Espresso-contrib for DatePicker, RecyclerView, Drawer actions, Accessibility checks, CountingIdlingResource
androidTestImplementation 'com.android.support.test.espresso:espresso-contrib:3.0.1' androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.1.0-beta02'
// Espresso-intents for validation and stubbing of Intents // Espresso-intents for validation and stubbing of Intents
androidTestImplementation 'com.android.support.test.espresso:espresso-intents:3.0.1' androidTestImplementation 'androidx.test.espresso:espresso-intents:3.1.0-beta02'
implementation fileTree(include: ['*.jar'], dir: 'libs') implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
// Android Support // Android Support
implementation "com.android.support:appcompat-v7:$android_version" implementation "androidx.appcompat:appcompat:$android_version"
implementation "com.android.support:design:$android_version" implementation "com.google.android.material:material:$android_version"
implementation "com.android.support:recyclerview-v7:$android_version" implementation "androidx.recyclerview:recyclerview:$android_version"
implementation "com.android.support:support-v4:$android_version" implementation "androidx.legacy:legacy-support-v4:$android_version"
implementation "com.android.support:support-vector-drawable:$android_version" implementation "androidx.vectordrawable:vectordrawable:$android_version"
implementation "com.android.support:customtabs:$android_version" implementation "androidx.browser:browser:$android_version"
implementation "com.android.support:cardview-v7:$android_version" implementation "androidx.cardview:cardview:$android_version"
implementation 'com.android.support.constraint:constraint-layout:1.1.0' implementation 'androidx.constraintlayout:constraintlayout:2.0.0-alpha2'
//multidex //multidex
implementation 'com.android.support:multidex:1.0.3' implementation 'androidx.multidex:multidex:2.0.0'
// Intro // Intro
implementation 'agency.tango.android:material-intro-screen:0.0.5' implementation 'agency.tango.android:material-intro-screen:0.0.5'
// About // About
implementation('com.mikepenz:aboutlibraries:6.0.0@aar') { implementation('com.mikepenz:aboutlibraries:6.2.0@aar') {
transitive = true transitive = true
} }
@ -121,8 +123,8 @@ dependencies {
implementation 'com.burgstaller:okhttp-digest:1.12' implementation 'com.burgstaller:okhttp-digest:1.12'
// Material-ish things // Material-ish things
implementation 'com.ashokvarma.android:bottom-navigation-bar:2.0.3' implementation 'com.ashokvarma.android:bottom-navigation-bar:2.0.5'
implementation 'com.github.jd-alexander:LikeButton:0.2.1' implementation 'com.github.jd-alexander:LikeButton:0.2.3'
implementation 'com.amulyakhare:com.amulyakhare.textdrawable:1.0.1' implementation 'com.amulyakhare:com.amulyakhare.textdrawable:1.0.1'
// glide // glide
@ -130,25 +132,30 @@ dependencies {
implementation '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
implementation 'com.github.stkent:amplify:2.1.0' implementation 'com.github.stkent:amplify:2.2.0'
// Drawer // Drawer
implementation 'co.zsmb:materialdrawer-kt:1.3.7' implementation 'co.zsmb:materialdrawer-kt:2.0.1'
implementation 'com.anupcowkur:reservoir:3.1.0'
// Themes // Themes
implementation 'com.52inc:scoops:1.0.0' implementation 'com.52inc:scoops:1.0.0'
implementation 'com.jrummyapps:colorpicker:2.1.7' implementation 'com.jaredrummler:colorpicker:1.0.2'
implementation 'com.github.rubensousa:floatingtoolbar:1.5.1' implementation 'com.github.rubensousa:floatingtoolbar:1.5.1'
// Pager // Pager
implementation 'me.relex:circleindicator:1.2.2@aar' implementation 'me.relex:circleindicator:2.0.0@aar'
implementation 'androidx.core:core-ktx:0.3' implementation 'androidx.core:core-ktx:1.0.0'
// Crash // Crash
implementation 'ch.acra:acra-http:5.1.3' implementation 'ch.acra:acra-http:5.1.3'
implementation 'ch.acra:acra-dialog:5.1.3' implementation 'ch.acra:acra-dialog:5.1.3'
implementation "androidx.lifecycle:lifecycle-livedata:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"
implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version"
} }

View File

@ -2,27 +2,27 @@ package apps.amine.bou.readerforselfoss
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.support.test.InstrumentationRegistry import androidx.test.InstrumentationRegistry
import android.support.test.espresso.Espresso.onView import androidx.test.espresso.Espresso.onView
import android.support.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu import androidx.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu
import android.support.test.espresso.action.ViewActions.click import androidx.test.espresso.action.ViewActions.click
import android.support.test.espresso.action.ViewActions.closeSoftKeyboard import androidx.test.espresso.action.ViewActions.closeSoftKeyboard
import android.support.test.espresso.action.ViewActions.pressBack import androidx.test.espresso.action.ViewActions.pressBack
import android.support.test.espresso.action.ViewActions.pressKey import androidx.test.espresso.action.ViewActions.pressKey
import android.support.test.espresso.action.ViewActions.typeText import androidx.test.espresso.action.ViewActions.typeText
import android.support.test.espresso.assertion.ViewAssertions.matches import androidx.test.espresso.assertion.ViewAssertions.matches
import android.support.test.espresso.contrib.DrawerActions import androidx.test.espresso.contrib.DrawerActions
import android.support.test.espresso.intent.Intents import androidx.test.espresso.intent.Intents
import android.support.test.espresso.intent.Intents.intended import androidx.test.espresso.intent.Intents.intended
import android.support.test.espresso.intent.Intents.times import androidx.test.espresso.intent.Intents.times
import android.support.test.espresso.intent.matcher.IntentMatchers.hasComponent import androidx.test.espresso.intent.matcher.IntentMatchers.hasComponent
import android.support.test.espresso.matcher.ViewMatchers.isDisplayed import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import android.support.test.espresso.matcher.ViewMatchers.isRoot import androidx.test.espresso.matcher.ViewMatchers.isRoot
import android.support.test.espresso.matcher.ViewMatchers.withContentDescription import androidx.test.espresso.matcher.ViewMatchers.withContentDescription
import android.support.test.espresso.matcher.ViewMatchers.withId import androidx.test.espresso.matcher.ViewMatchers.withId
import android.support.test.espresso.matcher.ViewMatchers.withText import androidx.test.espresso.matcher.ViewMatchers.withText
import android.support.test.rule.ActivityTestRule import androidx.test.rule.ActivityTestRule
import android.support.test.runner.AndroidJUnit4 import androidx.test.runner.AndroidJUnit4
import android.view.KeyEvent import android.view.KeyEvent
import apps.amine.bou.readerforselfoss.utils.Config import apps.amine.bou.readerforselfoss.utils.Config
import org.junit.After import org.junit.After

View File

@ -2,19 +2,19 @@ package apps.amine.bou.readerforselfoss
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.support.test.InstrumentationRegistry.getInstrumentation import androidx.test.InstrumentationRegistry.getInstrumentation
import android.support.test.espresso.Espresso.onView import androidx.test.espresso.Espresso.onView
import android.support.test.espresso.action.ViewActions.click import androidx.test.espresso.action.ViewActions.click
import android.support.test.espresso.assertion.ViewAssertions.matches import androidx.test.espresso.assertion.ViewAssertions.matches
import android.support.test.espresso.intent.Intents import androidx.test.espresso.intent.Intents
import android.support.test.espresso.intent.Intents.intended import androidx.test.espresso.intent.Intents.intended
import android.support.test.espresso.intent.Intents.times import androidx.test.espresso.intent.Intents.times
import android.support.test.espresso.intent.matcher.IntentMatchers.hasComponent import androidx.test.espresso.intent.matcher.IntentMatchers.hasComponent
import android.support.test.espresso.matcher.ViewMatchers.isDisplayed import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import android.support.test.espresso.matcher.ViewMatchers.withId import androidx.test.espresso.matcher.ViewMatchers.withId
import android.support.test.espresso.matcher.ViewMatchers.withText import androidx.test.espresso.matcher.ViewMatchers.withText
import android.support.test.rule.ActivityTestRule import androidx.test.rule.ActivityTestRule
import android.support.test.runner.AndroidJUnit4 import androidx.test.runner.AndroidJUnit4
import apps.amine.bou.readerforselfoss.utils.Config import apps.amine.bou.readerforselfoss.utils.Config
import org.junit.After import org.junit.After
import org.junit.Before import org.junit.Before

View File

@ -2,25 +2,25 @@ package apps.amine.bou.readerforselfoss
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.support.test.InstrumentationRegistry import androidx.test.InstrumentationRegistry
import android.support.test.espresso.Espresso.onView import androidx.test.espresso.Espresso.onView
import android.support.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu import androidx.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu
import android.support.test.espresso.action.ViewActions.click import androidx.test.espresso.action.ViewActions.click
import android.support.test.espresso.action.ViewActions.closeSoftKeyboard import androidx.test.espresso.action.ViewActions.closeSoftKeyboard
import android.support.test.espresso.action.ViewActions.pressBack import androidx.test.espresso.action.ViewActions.pressBack
import android.support.test.espresso.action.ViewActions.typeText import androidx.test.espresso.action.ViewActions.typeText
import android.support.test.espresso.assertion.ViewAssertions.matches import androidx.test.espresso.assertion.ViewAssertions.matches
import android.support.test.espresso.intent.Intents import androidx.test.espresso.intent.Intents
import android.support.test.espresso.intent.Intents.intended import androidx.test.espresso.intent.Intents.intended
import android.support.test.espresso.intent.Intents.times import androidx.test.espresso.intent.Intents.times
import android.support.test.espresso.intent.matcher.IntentMatchers.hasComponent import androidx.test.espresso.intent.matcher.IntentMatchers.hasComponent
import android.support.test.espresso.matcher.ViewMatchers import androidx.test.espresso.matcher.ViewMatchers
import android.support.test.espresso.matcher.ViewMatchers.isRoot import androidx.test.espresso.matcher.ViewMatchers.isRoot
import android.support.test.espresso.matcher.ViewMatchers.withEffectiveVisibility import androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility
import android.support.test.espresso.matcher.ViewMatchers.withId import androidx.test.espresso.matcher.ViewMatchers.withId
import android.support.test.espresso.matcher.ViewMatchers.withText import androidx.test.espresso.matcher.ViewMatchers.withText
import android.support.test.rule.ActivityTestRule import androidx.test.rule.ActivityTestRule
import android.support.test.runner.AndroidJUnit4 import androidx.test.runner.AndroidJUnit4
import apps.amine.bou.readerforselfoss.utils.Config import apps.amine.bou.readerforselfoss.utils.Config
import com.mikepenz.aboutlibraries.ui.LibsActivity import com.mikepenz.aboutlibraries.ui.LibsActivity
import org.junit.After import org.junit.After

View File

@ -3,13 +3,13 @@ package apps.amine.bou.readerforselfoss
import android.content.Intent import android.content.Intent
import android.content.SharedPreferences import android.content.SharedPreferences
import android.preference.PreferenceManager import android.preference.PreferenceManager
import android.support.test.InstrumentationRegistry.getInstrumentation import androidx.test.InstrumentationRegistry.getInstrumentation
import android.support.test.espresso.intent.Intents import androidx.test.espresso.intent.Intents
import android.support.test.espresso.intent.Intents.intended import androidx.test.espresso.intent.Intents.intended
import android.support.test.espresso.intent.Intents.times import androidx.test.espresso.intent.Intents.times
import android.support.test.espresso.intent.matcher.IntentMatchers.hasComponent import androidx.test.espresso.intent.matcher.IntentMatchers.hasComponent
import android.support.test.rule.ActivityTestRule import androidx.test.rule.ActivityTestRule
import android.support.test.runner.AndroidJUnit4 import androidx.test.runner.AndroidJUnit4
import org.junit.After import org.junit.After
import org.junit.Before import org.junit.Before

View File

@ -1,7 +1,7 @@
package apps.amine.bou.readerforselfoss package apps.amine.bou.readerforselfoss
import android.support.design.widget.TextInputLayout import com.google.android.material.textfield.TextInputLayout
import android.support.test.espresso.matcher.ViewMatchers import androidx.test.espresso.matcher.ViewMatchers
import android.view.View import android.view.View
import org.hamcrest.Description import org.hamcrest.Description
import org.hamcrest.Matcher import org.hamcrest.Matcher

View File

@ -4,8 +4,8 @@ import android.content.Intent
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.constraint.ConstraintLayout import androidx.constraintlayout.widget.ConstraintLayout
import android.support.v7.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import android.view.View import android.view.View
import android.widget.AdapterView import android.widget.AdapterView
import android.widget.ArrayAdapter import android.widget.ArrayAdapter

View File

@ -9,29 +9,32 @@ 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.v4.view.MenuItemCompat import androidx.core.view.MenuItemCompat
import android.support.v7.app.AlertDialog import androidx.appcompat.app.AlertDialog
import android.support.v7.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import android.support.v7.widget.DividerItemDecoration import androidx.recyclerview.widget.DividerItemDecoration
import android.support.v7.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import android.support.v7.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import android.support.v7.widget.SearchView import androidx.appcompat.widget.SearchView
import android.support.v7.widget.StaggeredGridLayoutManager import androidx.recyclerview.widget.StaggeredGridLayoutManager
import android.support.v7.widget.helper.ItemTouchHelper import androidx.recyclerview.widget.ItemTouchHelper
import android.util.Log 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 androidx.room.Room
import androidx.room.RoomDatabase
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.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.Source
import apps.amine.bou.readerforselfoss.api.selfoss.Stats import apps.amine.bou.readerforselfoss.api.selfoss.Stats
import apps.amine.bou.readerforselfoss.api.selfoss.SuccessResponse 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.persistence.database.AppDatabase
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.themes.Toppings
@ -42,14 +45,13 @@ 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.flattenTags
import apps.amine.bou.readerforselfoss.utils.longHash import apps.amine.bou.readerforselfoss.utils.longHash
import apps.amine.bou.readerforselfoss.utils.persistence.toEntity
import apps.amine.bou.readerforselfoss.utils.persistence.toView
import co.zsmb.materialdrawerkt.builders.accountHeader import co.zsmb.materialdrawerkt.builders.accountHeader
import co.zsmb.materialdrawerkt.builders.drawer import co.zsmb.materialdrawerkt.builders.drawer
import co.zsmb.materialdrawerkt.builders.footer import co.zsmb.materialdrawerkt.builders.footer
import co.zsmb.materialdrawerkt.draweritems.badgeable.primaryItem import co.zsmb.materialdrawerkt.draweritems.badgeable.primaryItem
import co.zsmb.materialdrawerkt.draweritems.profile.profile import co.zsmb.materialdrawerkt.draweritems.profile.profile
import com.anupcowkur.reservoir.Reservoir
import com.anupcowkur.reservoir.ReservoirGetCallback
import com.anupcowkur.reservoir.ReservoirPutCallback
import com.ashokvarma.bottomnavigation.BottomNavigationBar import com.ashokvarma.bottomnavigation.BottomNavigationBar
import com.ashokvarma.bottomnavigation.BottomNavigationItem import com.ashokvarma.bottomnavigation.BottomNavigationItem
import com.ashokvarma.bottomnavigation.TextBadgeItem import com.ashokvarma.bottomnavigation.TextBadgeItem
@ -65,9 +67,12 @@ 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
import kotlinx.android.synthetic.main.activity_home.* import kotlinx.android.synthetic.main.activity_home.*
import kotlinx.android.synthetic.main.fragment_article.*
import retrofit2.Call import retrofit2.Call
import retrofit2.Callback import retrofit2.Callback
import retrofit2.Response import retrofit2.Response
import kotlin.concurrent.thread
class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener { class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
private val MENU_PREFERENCES = 12302 private val MENU_PREFERENCES = 12302
@ -94,7 +99,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
private var itemsNumber: Int = 200 private var itemsNumber: Int = 200
private var elementsShown: Int = 0 private var elementsShown: Int = 0
private var maybeTagFilter: Tag? = null private var maybeTagFilter: Tag? = null
private var maybeSourceFilter: Sources? = null private var maybeSourceFilter: Source? = null
private var maybeSearchFilter: String? = null private var maybeSearchFilter: String? = null
private var userIdentifier: String = "" private var userIdentifier: String = ""
private var displayAccountHeader: Boolean = false private var displayAccountHeader: Boolean = false
@ -102,7 +107,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
private var lastFetchDone: Boolean = false private var lastFetchDone: Boolean = false
private var hiddenTags: List<String> = emptyList() private var hiddenTags: List<String> = emptyList()
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
@ -123,10 +127,11 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
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> private lateinit var tagsBadge: Map<Long, Int>
data class DrawerData(val tags: List<Tag>?, val sources: List<Sources>?) private lateinit var db: AppDatabase
data class DrawerData(val tags: List<Tag>?, val sources: List<Source>?)
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
@ -147,6 +152,12 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
Amplify.getSharedInstance().promptIfReady(promptView) Amplify.getSharedInstance().promptIfReady(promptView)
} }
db = Room.databaseBuilder(
applicationContext,
AppDatabase::class.java!!, "selfoss-database"
).build()
customTabActivityHelper = CustomTabActivityHelper() customTabActivityHelper = CustomTabActivityHelper()
sharedPref = PreferenceManager.getDefaultSharedPreferences(this) sharedPref = PreferenceManager.getDefaultSharedPreferences(this)
@ -374,7 +385,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
private fun handleThemeBinding() { private fun handleThemeBinding() {
val scoop = Scoop.getInstance() val scoop = Scoop.getInstance()
scoop.bind(this, Toppings.PRIMARY.value, toolBar) scoop.bind(this, Toppings.PRIMARY.value, toolBar)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
scoop.bindStatusBar(this, Toppings.PRIMARY_DARK.value) scoop.bindStatusBar(this, Toppings.PRIMARY_DARK.value)
} }
} }
@ -384,7 +395,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
val scoop = Scoop.getInstance() val scoop = Scoop.getInstance()
scoop.update(Toppings.PRIMARY.value, appColors.colorPrimary) scoop.update(Toppings.PRIMARY.value, appColors.colorPrimary)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
scoop.update(Toppings.PRIMARY_DARK.value, appColors.colorPrimaryDark) scoop.update(Toppings.PRIMARY_DARK.value, appColors.colorPrimaryDark)
} }
} }
@ -508,7 +519,8 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
) )
} }
} else { } else {
val filteredHiddenTags: List<Tag> = maybeTags.filter { hiddenTags.contains(it.tag) } val filteredHiddenTags: List<Tag> =
maybeTags.filter { hiddenTags.contains(it.tag) }
tagsBadge = filteredHiddenTags.map { tagsBadge = filteredHiddenTags.map {
val gd = GradientDrawable() val gd = GradientDrawable()
val color = try { val color = try {
@ -544,7 +556,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
} }
} }
fun handleSources(maybeSources: List<Sources>?) { fun handleSources(maybeSources: List<Source>?) {
if (maybeSources == null) { if (maybeSources == null) {
if (loadedFromCache) { if (loadedFromCache) {
drawer.addItem( drawer.addItem(
@ -643,14 +655,19 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
if (!loadedFromCache) { if (!loadedFromCache) {
Reservoir.putAsync( if (maybeDrawerData.tags != null) {
"drawerData", maybeDrawerData, object : ReservoirPutCallback { thread {
override fun onSuccess() { val tagEntities = maybeDrawerData.tags.map { it.toEntity() }
} db.drawerDataDao().insertAllTags(*tagEntities.toTypedArray())
}
override fun onFailure(p0: Exception?) { }
} if (maybeDrawerData.sources != null) {
}) thread {
val sourceEntities =
maybeDrawerData.sources.map { it.toEntity(this@HomeActivity) }
db.drawerDataDao().insertAllSources(*sourceEntities.toTypedArray())
}
}
} }
} else { } else {
if (!loadedFromCache) { if (!loadedFromCache) {
@ -672,13 +689,13 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
fun drawerApiCalls(maybeDrawerData: DrawerData?) { fun drawerApiCalls(maybeDrawerData: DrawerData?) {
var tags: List<Tag>? = null var tags: List<Tag>? = null
var sources: List<Sources>? var sources: List<Source>?
fun sourcesApiCall() { fun sourcesApiCall() {
api.sources.enqueue(object : Callback<List<Sources>> { api.sources.enqueue(object : Callback<List<Source>> {
override fun onResponse( override fun onResponse(
call: Call<List<Sources>>?, call: Call<List<Source>>?,
response: Response<List<Sources>> response: Response<List<Source>>
) { ) {
sources = response.body() sources = response.body()
val apiDrawerData = DrawerData(tags, sources) val apiDrawerData = DrawerData(tags, sources)
@ -687,7 +704,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
} }
} }
override fun onFailure(call: Call<List<Sources>>?, t: Throwable?) { override fun onFailure(call: Call<List<Source>>?, t: Throwable?) {
} }
}) })
} }
@ -713,18 +730,12 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
) )
) )
val resultType = object : TypeToken<DrawerData>() {}.type thread {
Reservoir.getAsync( var drawerData = DrawerData(db.drawerDataDao().tags().map { it.toView() },
"drawerData", resultType, object : ReservoirGetCallback<DrawerData> { db.drawerDataDao().sources().map { it.toView() })
override fun onSuccess(maybeDrawerData: DrawerData?) { handleDrawerData(drawerData, loadedFromCache = true)
handleDrawerData(maybeDrawerData, loadedFromCache = true) drawerApiCalls(drawerData)
drawerApiCalls(maybeDrawerData) }
}
override fun onFailure(p0: Exception?) {
drawerApiCalls(null)
}
})
} }
private fun reloadLayoutManager() { private fun reloadLayoutManager() {
@ -735,7 +746,10 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
when (currentManager) { when (currentManager) {
is StaggeredGridLayoutManager -> is StaggeredGridLayoutManager ->
if (!shouldBeCardView) { if (!shouldBeCardView) {
layoutManager = GridLayoutManager(this, calculateNoOfColumns()) layoutManager = GridLayoutManager(
this,
calculateNoOfColumns()
)
recyclerView.layoutManager = layoutManager recyclerView.layoutManager = layoutManager
} }
is GridLayoutManager -> is GridLayoutManager ->
@ -751,7 +765,10 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
else -> else ->
if (currentManager == null) { if (currentManager == null) {
if (!shouldBeCardView) { if (!shouldBeCardView) {
layoutManager = GridLayoutManager(this, calculateNoOfColumns()) layoutManager = GridLayoutManager(
this,
calculateNoOfColumns()
)
recyclerView.layoutManager = layoutManager recyclerView.layoutManager = layoutManager
} else { } else {
layoutManager = StaggeredGridLayoutManager( layoutManager = StaggeredGridLayoutManager(
@ -857,8 +874,8 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
} }
private fun filter(tags: String): Boolean { private fun filter(tags: String): Boolean {
val tagsList = tags.replace("\\s".toRegex(), "").split(",") val tagsList = tags.replace("\\s".toRegex(), "").split(",")
return tagsList.intersect(hiddenTags).isEmpty() return tagsList.intersect(hiddenTags).isEmpty()
} }
private fun doCallTo( private fun doCallTo(
@ -872,7 +889,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
if (shouldUpdate) { if (shouldUpdate) {
items = response.body() as ArrayList<Item> items = response.body() as ArrayList<Item>
items = items.filter { items = items.filter {
maybeTagFilter != null || filter(it.tags) maybeTagFilter != null || filter(it.tags)
} as ArrayList<Item> } as ArrayList<Item>
if (allItems.isEmpty()) { if (allItems.isEmpty()) {

View File

@ -7,7 +7,7 @@ import android.content.Intent
import android.net.Uri import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.preference.PreferenceManager import android.preference.PreferenceManager
import android.support.v7.app.AppCompatDelegate import androidx.appcompat.app.AppCompatDelegate
import android.view.View import android.view.View
class IntroActivity : MaterialIntroActivity() { class IntroActivity : MaterialIntroActivity() {

View File

@ -6,8 +6,8 @@ import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.SharedPreferences import android.content.SharedPreferences
import android.os.Bundle import android.os.Bundle
import android.support.v7.app.AlertDialog import androidx.appcompat.app.AlertDialog
import android.support.v7.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import android.text.TextUtils import android.text.TextUtils
import android.view.Menu import android.view.Menu
import android.view.MenuItem import android.view.MenuItem

View File

@ -3,7 +3,7 @@ package apps.amine.bou.readerforselfoss
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.preference.PreferenceManager import android.preference.PreferenceManager
import android.support.v7.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity() { class MainActivity : AppCompatActivity() {

View File

@ -1,14 +1,12 @@
package apps.amine.bou.readerforselfoss package apps.amine.bou.readerforselfoss
import android.content.Context import android.content.Context
import android.content.SharedPreferences
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.net.Uri import android.net.Uri
import android.preference.PreferenceManager import android.preference.PreferenceManager
import android.support.multidex.MultiDexApplication import androidx.multidex.MultiDexApplication
import android.widget.ImageView import android.widget.ImageView
import apps.amine.bou.readerforselfoss.utils.Config import apps.amine.bou.readerforselfoss.utils.Config
import com.anupcowkur.reservoir.Reservoir
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions import com.bumptech.glide.request.RequestOptions
import com.ftinc.scoop.Scoop import com.ftinc.scoop.Scoop
@ -49,8 +47,6 @@ class MyApp : MultiDexApplication() {
initAmplify() initAmplify()
initCache()
val prefs = getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE) val prefs = getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE)
if (prefs.getString("unique_id", "").isEmpty()) { if (prefs.getString("unique_id", "").isEmpty()) {
val editor = prefs.edit() val editor = prefs.edit()
@ -80,14 +76,6 @@ class MyApp : MultiDexApplication() {
.applyAllDefaultRules() .applyAllDefaultRules()
} }
private fun initCache() {
try {
Reservoir.init(this, 8192) //in bytes
} catch (e: IOException) {
//failure
}
}
private fun initDrawerImageLoader() { private fun initDrawerImageLoader() {
DrawerImageLoader.init(object : AbstractDrawerImageLoader() { DrawerImageLoader.init(object : AbstractDrawerImageLoader() {
override fun set( override fun set(

View File

@ -4,11 +4,11 @@ import android.graphics.drawable.ColorDrawable
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.v4.app.FragmentManager import androidx.fragment.app.FragmentManager
import android.support.v4.app.FragmentStatePagerAdapter import androidx.fragment.app.FragmentStatePagerAdapter
import android.support.v4.content.ContextCompat import androidx.core.content.ContextCompat
import android.support.v4.view.ViewPager import androidx.viewpager.widget.ViewPager
import android.support.v7.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import android.view.Menu import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import android.view.ViewGroup import android.view.ViewGroup

View File

@ -5,12 +5,12 @@ import android.content.res.ColorStateList
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.v7.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import android.support.v7.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import android.widget.Toast 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.Source
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.themes.Toppings
import com.ftinc.scoop.Scoop import com.ftinc.scoop.Scoop
@ -61,18 +61,18 @@ class SourcesActivity : AppCompatActivity() {
prefs.getBoolean("isSelfSignedCert", false), prefs.getBoolean("isSelfSignedCert", false),
prefs.getBoolean("should_log_everything", false) prefs.getBoolean("should_log_everything", false)
) )
var items: ArrayList<Sources> = ArrayList() var items: ArrayList<Source> = ArrayList()
recyclerView.setHasFixedSize(true) recyclerView.setHasFixedSize(true)
recyclerView.layoutManager = mLayoutManager recyclerView.layoutManager = mLayoutManager
api.sources.enqueue(object : Callback<List<Sources>> { api.sources.enqueue(object : Callback<List<Source>> {
override fun onResponse( override fun onResponse(
call: Call<List<Sources>>, call: Call<List<Source>>,
response: Response<List<Sources>> response: Response<List<Source>>
) { ) {
if (response.body() != null && response.body()!!.isNotEmpty()) { if (response.body() != null && response.body()!!.isNotEmpty()) {
items = response.body() as ArrayList<Sources> items = response.body() as ArrayList<Source>
} }
val mAdapter = SourcesListAdapter(this@SourcesActivity, items, api) val mAdapter = SourcesListAdapter(this@SourcesActivity, items, api)
recyclerView.adapter = mAdapter recyclerView.adapter = mAdapter
@ -86,7 +86,7 @@ class SourcesActivity : AppCompatActivity() {
} }
} }
override fun onFailure(call: Call<List<Sources>>, t: Throwable) { override fun onFailure(call: Call<List<Source>>, t: Throwable) {
Toast.makeText( Toast.makeText(
this@SourcesActivity, this@SourcesActivity,
R.string.cant_get_sources, R.string.cant_get_sources,

View File

@ -2,8 +2,8 @@ package apps.amine.bou.readerforselfoss.adapters
import android.app.Activity import android.app.Activity
import android.content.Context import android.content.Context
import android.support.v7.widget.CardView import androidx.cardview.widget.CardView
import android.support.v7.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import android.text.Html import android.text.Html
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View

View File

@ -2,8 +2,8 @@ package apps.amine.bou.readerforselfoss.adapters
import android.app.Activity import android.app.Activity
import android.content.Context import android.content.Context
import android.support.constraint.ConstraintLayout import androidx.constraintlayout.widget.ConstraintLayout
import android.support.v7.widget.RecyclerView import androidx.recyclerview.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

View File

@ -2,8 +2,8 @@ package apps.amine.bou.readerforselfoss.adapters
import android.app.Activity import android.app.Activity
import android.graphics.Color import android.graphics.Color
import android.support.design.widget.Snackbar import com.google.android.material.snackbar.Snackbar
import android.support.v7.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import android.widget.TextView import android.widget.TextView
import android.widget.Toast import android.widget.Toast
import apps.amine.bou.readerforselfoss.R import apps.amine.bou.readerforselfoss.R
@ -62,7 +62,7 @@ abstract class ItemsAdapter<VH : RecyclerView.ViewHolder?> : RecyclerView.Adapte
} }
val view = s.view val view = s.view
val tv: TextView = view.findViewById(android.support.design.R.id.snackbar_text) val tv: TextView = view.findViewById(com.google.android.material.R.id.snackbar_text)
tv.setTextColor(Color.WHITE) tv.setTextColor(Color.WHITE)
s.show() s.show()
} }

View File

@ -2,15 +2,15 @@ package apps.amine.bou.readerforselfoss.adapters
import android.app.Activity import android.app.Activity
import android.content.Context import android.content.Context
import android.support.constraint.ConstraintLayout import androidx.constraintlayout.widget.ConstraintLayout
import android.support.v7.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.Button import android.widget.Button
import android.widget.Toast import android.widget.Toast
import apps.amine.bou.readerforselfoss.R import apps.amine.bou.readerforselfoss.R
import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi
import apps.amine.bou.readerforselfoss.api.selfoss.Sources import apps.amine.bou.readerforselfoss.api.selfoss.Source
import apps.amine.bou.readerforselfoss.api.selfoss.SuccessResponse import apps.amine.bou.readerforselfoss.api.selfoss.SuccessResponse
import apps.amine.bou.readerforselfoss.utils.glide.circularBitmapDrawable import apps.amine.bou.readerforselfoss.utils.glide.circularBitmapDrawable
import apps.amine.bou.readerforselfoss.utils.toTextDrawableString import apps.amine.bou.readerforselfoss.utils.toTextDrawableString
@ -23,7 +23,7 @@ import retrofit2.Response
class SourcesListAdapter( class SourcesListAdapter(
private val app: Activity, private val app: Activity,
private val items: ArrayList<Sources>, private val items: ArrayList<Source>,
private val api: SelfossApi private val api: SelfossApi
) : RecyclerView.Adapter<SourcesListAdapter.ViewHolder>() { ) : RecyclerView.Adapter<SourcesListAdapter.ViewHolder>() {
private val c: Context = app.baseContext private val c: Context = app.baseContext

View File

@ -159,7 +159,7 @@ class SelfossApi(
fun update(): Call<String> = fun update(): Call<String> =
service.update(userName, password) service.update(userName, password)
val sources: Call<List<Sources>> val sources: Call<List<Source>>
get() = service.sources(userName, password) get() = service.sources(userName, password)
fun deleteSource(id: String): Call<SuccessResponse> = fun deleteSource(id: String): Call<SuccessResponse> =

View File

@ -42,7 +42,7 @@ data class Spout(
@SerializedName("description") val description: String @SerializedName("description") val description: String
) )
data class Sources( data class Source(
@SerializedName("id") val id: String, @SerializedName("id") val id: String,
@SerializedName("title") val title: String, @SerializedName("title") val title: String,
@SerializedName("tags") val tags: String, @SerializedName("tags") val tags: String,

View File

@ -95,7 +95,7 @@ internal interface SelfossService {
fun sources( fun sources(
@Query("username") username: String, @Query("username") username: String,
@Query("password") password: String @Query("password") password: String
): Call<List<Sources>> ): Call<List<Source>>
@DELETE("source/{id}") @DELETE("source/{id}")
fun deleteSource( fun deleteSource(

View File

@ -1,20 +1,17 @@
package apps.amine.bou.readerforselfoss.fragments package apps.amine.bou.readerforselfoss.fragments
import android.content.Context import android.content.Context
import android.content.Intent
import android.content.SharedPreferences import android.content.SharedPreferences
import android.content.res.ColorStateList import android.content.res.ColorStateList
import android.graphics.drawable.ColorDrawable 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 androidx.browser.customtabs.CustomTabsIntent
import android.support.design.widget.FloatingActionButton import com.google.android.material.floatingactionbutton.FloatingActionButton
import android.support.v4.app.Fragment import androidx.fragment.app.Fragment
import android.support.v4.content.ContextCompat import androidx.core.content.ContextCompat
import android.support.v4.widget.NestedScrollView import androidx.core.widget.NestedScrollView
import android.support.v7.app.AlertDialog
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
@ -58,7 +55,6 @@ 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 editor: SharedPreferences.Editor
private lateinit var fab: FloatingActionButton private lateinit var fab: FloatingActionButton
private lateinit var appColors: AppColors private lateinit var appColors: AppColors
@ -97,7 +93,6 @@ class ArticleFragment : Fragment() {
val prefs = PreferenceManager.getDefaultSharedPreferences(activity) val prefs = PreferenceManager.getDefaultSharedPreferences(activity)
editor = prefs.edit() editor = prefs.edit()
fontSize = prefs.getString("reader_font_size", "14").toInt() fontSize = prefs.getString("reader_font_size", "14").toInt()
showMalformedUrl = prefs.getBoolean("show_error_malformed_url", true)
val settings = activity!!.getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE) val settings = activity!!.getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE)
val debugReadingItems = prefs.getBoolean("read_debug", false) val debugReadingItems = prefs.getBoolean("read_debug", false)
@ -233,7 +228,13 @@ class ArticleFragment : Fragment() {
if (response.body() != null && response.body()!!.content != null && !response.body()!!.content.isNullOrEmpty()) { if (response.body() != null && response.body()!!.content != null && !response.body()!!.content.isNullOrEmpty()) {
try { try {
rootView.titleView.text = response.body()!!.title rootView.titleView.text = response.body()!!.title
url = response.body()!!.url try {
// Note: Mercury may return relative urls... If it does the url val will not be changed.
URL(response.body()!!.url)
url = response.body()!!.url
} catch (e: MalformedURLException) {
ACRA.getErrorReporter().maybeHandleSilentException(e, activity!!)
}
} catch (e: Exception) { } catch (e: Exception) {
if (context != null) { if (context != null) {
ACRA.getErrorReporter().maybeHandleSilentException(e, context!!) ACRA.getErrorReporter().maybeHandleSilentException(e, context!!)
@ -362,41 +363,7 @@ class ArticleFragment : Fragment() {
val itemUrl = URL(url) val itemUrl = URL(url)
baseUrl = itemUrl.protocol + "://" + itemUrl.host baseUrl = itemUrl.protocol + "://" + itemUrl.host
} catch (e: MalformedURLException) { } catch (e: MalformedURLException) {
if (showMalformedUrl && context != null) { ACRA.getErrorReporter().maybeHandleSilentException(e, activity!!)
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 = Config.feedbackEmail
val subject= "[ReaderForSelfoss 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( rootView.webcontent.loadDataWithBaseURL(

View File

@ -0,0 +1,37 @@
package apps.amine.bou.readerforselfoss.persistence.dao
import androidx.lifecycle.LiveData
import androidx.room.Delete
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import apps.amine.bou.readerforselfoss.persistence.entities.SourceEntity
import apps.amine.bou.readerforselfoss.persistence.entities.TagEntity
@Dao
interface DrawerDataDao {
@Query("SELECT * FROM tags")
fun tags(): List<TagEntity>
@Query("SELECT * FROM sources")
fun sources(): List<SourceEntity>
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertAllTags(vararg tags: TagEntity)
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertAllSources(vararg sources: SourceEntity)
@Query("DELETE FROM tags")
fun deleteAllTags()
@Query("DELETE FROM sources")
fun deleteAllSources()
@Delete
fun deleteTag(tag: TagEntity)
@Delete
fun deleteSource(source: SourceEntity)
}

View File

@ -0,0 +1,12 @@
package apps.amine.bou.readerforselfoss.persistence.database
import androidx.room.RoomDatabase
import androidx.room.Database
import apps.amine.bou.readerforselfoss.persistence.dao.DrawerDataDao
import apps.amine.bou.readerforselfoss.persistence.entities.SourceEntity
import apps.amine.bou.readerforselfoss.persistence.entities.TagEntity
@Database(entities = [TagEntity::class, SourceEntity::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
abstract fun drawerDataDao(): DrawerDataDao
}

View File

@ -0,0 +1,33 @@
package apps.amine.bou.readerforselfoss.persistence.entities
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity(tableName = "tags")
data class TagEntity(
@PrimaryKey
@ColumnInfo(name = "tag")
val tag: String,
@ColumnInfo(name = "color")
val color: String,
@ColumnInfo(name = "unread")
val unread: Int
)
@Entity(tableName = "sources")
data class SourceEntity(
@PrimaryKey
@ColumnInfo(name = "id")
val id: String,
@ColumnInfo(name = "title")
val title: String,
@ColumnInfo(name = "tags")
val tags: String,
@ColumnInfo(name = "spout")
val spout: String,
@ColumnInfo(name = "error")
val error: String,
@ColumnInfo(name = "icon")
val icon: String
)

View File

@ -4,13 +4,13 @@ import android.content.res.Configuration;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.preference.PreferenceActivity; import android.preference.PreferenceActivity;
import android.support.annotation.LayoutRes; import androidx.annotation.LayoutRes;
import android.support.annotation.NonNull; import androidx.annotation.NonNull;
import android.support.annotation.Nullable; import androidx.annotation.Nullable;
import android.support.design.widget.AppBarLayout; import com.google.android.material.appbar.AppBarLayout;
import android.support.v7.app.ActionBar; import androidx.appcompat.app.ActionBar;
import android.support.v7.app.AppCompatDelegate; import androidx.appcompat.app.AppCompatDelegate;
import android.support.v7.widget.Toolbar; import androidx.appcompat.widget.Toolbar;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.MenuInflater; import android.view.MenuInflater;
import android.view.View; import android.view.View;

View File

@ -19,7 +19,7 @@ import android.preference.PreferenceActivity;
import android.preference.PreferenceFragment; 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 androidx.appcompat.app.ActionBar;
import android.text.Editable; import android.text.Editable;
import android.text.InputFilter; import android.text.InputFilter;
import android.text.Spanned; import android.text.Spanned;
@ -31,7 +31,6 @@ import android.widget.Toast;
import java.util.List; import java.util.List;
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.themes.AppColors;
import apps.amine.bou.readerforselfoss.utils.Config; import apps.amine.bou.readerforselfoss.utils.Config;

View File

@ -3,8 +3,8 @@ 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.preference.PreferenceManager
import android.support.annotation.ColorInt import androidx.annotation.ColorInt
import android.support.v7.view.ContextThemeWrapper import androidx.appcompat.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.LayoutInflater

View File

@ -1,6 +1,6 @@
package apps.amine.bou.readerforselfoss.transformers package apps.amine.bou.readerforselfoss.transformers
import android.support.v4.view.ViewPager import androidx.viewpager.widget.ViewPager
import android.view.View import android.view.View
class DepthPageTransformer : ViewPager.PageTransformer { class DepthPageTransformer : ViewPager.PageTransformer {

View File

@ -6,7 +6,7 @@ import android.content.Context
import android.content.Intent import android.content.Intent
import android.graphics.BitmapFactory import android.graphics.BitmapFactory
import android.net.Uri import android.net.Uri
import android.support.customtabs.CustomTabsIntent import androidx.browser.customtabs.CustomTabsIntent
import android.util.Patterns import android.util.Patterns
import android.widget.Toast import android.widget.Toast
import apps.amine.bou.readerforselfoss.R import apps.amine.bou.readerforselfoss.R

View File

@ -1,54 +0,0 @@
package apps.amine.bou.readerforselfoss.utils
import android.content.Context
import android.support.design.widget.CoordinatorLayout
import android.support.design.widget.FloatingActionButton
import android.util.AttributeSet
import android.view.View
class ScrollAwareFABBehavior(
context: Context,
attrs: AttributeSet
) : CoordinatorLayout.Behavior<FloatingActionButton>() {
override fun onStartNestedScroll(
coordinatorLayout: CoordinatorLayout,
child: FloatingActionButton,
directTargetChild: View,
target: View,
nestedScrollAxes: Int
): Boolean {
return true
}
override fun onNestedScroll(
coordinatorLayout: CoordinatorLayout,
child: FloatingActionButton,
target: View,
dxConsumed: Int,
dyConsumed: Int,
dxUnconsumed: Int,
dyUnconsumed: Int
) {
super.onNestedScroll(
coordinatorLayout,
child,
target,
dxConsumed,
dyConsumed,
dxUnconsumed,
dyUnconsumed
)
if (dyConsumed > 0 && child.visibility == View.VISIBLE) {
child.hide(object : FloatingActionButton.OnVisibilityChangedListener() {
override fun onHidden(fab: FloatingActionButton?) {
super.onHidden(fab)
fab!!.visibility = View.INVISIBLE
}
})
} else if (dyConsumed < 0 && child.visibility != View.VISIBLE) {
child.show()
}
}
}

View File

@ -4,10 +4,10 @@ package apps.amine.bou.readerforselfoss.utils.customtabs;
import android.app.Activity; import android.app.Activity;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.support.customtabs.CustomTabsClient; import androidx.browser.customtabs.CustomTabsClient;
import android.support.customtabs.CustomTabsIntent; import androidx.browser.customtabs.CustomTabsIntent;
import android.support.customtabs.CustomTabsServiceConnection; import androidx.browser.customtabs.CustomTabsServiceConnection;
import android.support.customtabs.CustomTabsSession; import androidx.browser.customtabs.CustomTabsSession;
import java.util.List; import java.util.List;

View File

@ -7,7 +7,7 @@ import android.content.IntentFilter;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo; import android.content.pm.ResolveInfo;
import android.net.Uri; import android.net.Uri;
import android.support.customtabs.CustomTabsService; import androidx.browser.customtabs.CustomTabsService;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;

View File

@ -2,8 +2,8 @@ package apps.amine.bou.readerforselfoss.utils.customtabs;
import android.content.ComponentName; import android.content.ComponentName;
import android.support.customtabs.CustomTabsClient; import androidx.browser.customtabs.CustomTabsClient;
import android.support.customtabs.CustomTabsServiceConnection; import androidx.browser.customtabs.CustomTabsServiceConnection;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;

View File

@ -1,7 +1,7 @@
package apps.amine.bou.readerforselfoss.utils.customtabs; package apps.amine.bou.readerforselfoss.utils.customtabs;
import android.support.customtabs.CustomTabsClient; import androidx.browser.customtabs.CustomTabsClient;
public interface ServiceConnectionCallback { public interface ServiceConnectionCallback {

View File

@ -1,7 +1,7 @@
/* From https://github.com/mikepenz/MaterialDrawer/blob/develop/app/src/main/java/com/mikepenz/materialdrawer/app/drawerItems/CustomBaseViewHolder.java */ /* From https://github.com/mikepenz/MaterialDrawer/blob/develop/app/src/main/java/com/mikepenz/materialdrawer/app/drawerItems/CustomBaseViewHolder.java */
package apps.amine.bou.readerforselfoss.utils.drawer package apps.amine.bou.readerforselfoss.utils.drawer
import android.support.v7.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import android.view.View import android.view.View
import android.widget.ImageView import android.widget.ImageView
import android.widget.TextView import android.widget.TextView

View File

@ -2,10 +2,10 @@
package apps.amine.bou.readerforselfoss.utils.drawer package apps.amine.bou.readerforselfoss.utils.drawer
import android.net.Uri import android.net.Uri
import android.support.annotation.ColorInt import androidx.annotation.ColorInt
import android.support.annotation.ColorRes import androidx.annotation.ColorRes
import android.support.annotation.StringRes import androidx.annotation.StringRes
import android.support.v7.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.mikepenz.materialdrawer.holder.ColorHolder import com.mikepenz.materialdrawer.holder.ColorHolder
import com.mikepenz.materialdrawer.holder.ImageHolder import com.mikepenz.materialdrawer.holder.ImageHolder

View File

@ -1,8 +1,8 @@
/* From https://github.com/mikepenz/MaterialDrawer/blob/develop/app/src/main/java/com/mikepenz/materialdrawer/app/drawerItems/CustomUrlPrimaryDrawerItem.java */ /* From https://github.com/mikepenz/MaterialDrawer/blob/develop/app/src/main/java/com/mikepenz/materialdrawer/app/drawerItems/CustomUrlPrimaryDrawerItem.java */
package apps.amine.bou.readerforselfoss.utils.drawer package apps.amine.bou.readerforselfoss.utils.drawer
import android.support.annotation.LayoutRes import androidx.annotation.LayoutRes
import android.support.annotation.StringRes import androidx.annotation.StringRes
import android.view.View import android.view.View
import android.widget.TextView import android.widget.TextView
import apps.amine.bou.readerforselfoss.R import apps.amine.bou.readerforselfoss.R

View File

@ -2,7 +2,7 @@ package apps.amine.bou.readerforselfoss.utils.glide
import android.content.Context import android.content.Context
import android.graphics.Bitmap import android.graphics.Bitmap
import android.support.v4.graphics.drawable.RoundedBitmapDrawableFactory import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory
import android.widget.ImageView import android.widget.ImageView
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions import com.bumptech.glide.request.RequestOptions

View File

@ -0,0 +1,41 @@
package apps.amine.bou.readerforselfoss.utils.persistence
import android.content.Context
import apps.amine.bou.readerforselfoss.api.selfoss.Source
import apps.amine.bou.readerforselfoss.api.selfoss.Tag
import apps.amine.bou.readerforselfoss.persistence.entities.SourceEntity
import apps.amine.bou.readerforselfoss.persistence.entities.TagEntity
fun TagEntity.toView(): Tag =
Tag(
this.tag,
this.color,
this.unread
)
fun SourceEntity.toView(): Source =
Source(
this.id,
this.title,
this.tags,
this.spout,
this.error,
this.icon
)
fun Source.toEntity(context: Context): SourceEntity =
SourceEntity(
this.id,
this.title,
this.tags,
this.spout,
this.error,
this.getIcon(context)
)
fun Tag.toEntity(): TagEntity =
TagEntity(
this.tag,
this.color,
this.unread
)

View File

@ -10,22 +10,22 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical"> android:orientation="vertical">
<android.support.design.widget.AppBarLayout <com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar <androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar" android:id="@+id/toolbar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize" android:layout_height="?attr/actionBarSize"
app:theme="@style/ToolBarStyle" app:theme="@style/ToolBarStyle"
app:popupTheme="?attr/toolbarPopupTheme" /> app:popupTheme="?attr/toolbarPopupTheme" />
</android.support.design.widget.AppBarLayout> </com.google.android.material.appbar.AppBarLayout>
<android.support.constraint.ConstraintLayout <androidx.constraintlayout.widget.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"
@ -121,7 +121,7 @@
android:layout_marginBottom="16dp" android:layout_marginBottom="16dp"
app:layout_constraintVertical_bias="0.0"/> app:layout_constraintVertical_bias="0.0"/>
</android.support.constraint.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
<ProgressBar <ProgressBar
android:id="@+id/progress" android:id="@+id/progress"

View File

@ -30,13 +30,13 @@
app:prompt_view_background_color="?attr/colorAccent" app:prompt_view_background_color="?attr/colorAccent"
app:prompt_view_thanks_display_time_ms="2000"/> app:prompt_view_thanks_display_time_ms="2000"/>
<android.support.design.widget.CoordinatorLayout <androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="@+id/coordLayout" android:id="@+id/coordLayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_below="@id/promptView"> android:layout_below="@id/promptView">
<android.support.design.widget.CoordinatorLayout <androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="@+id/intern_coordLayout" android:id="@+id/intern_coordLayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
@ -46,18 +46,18 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical"> android:orientation="vertical">
<android.support.design.widget.AppBarLayout <com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar <androidx.appcompat.widget.Toolbar
android:id="@+id/toolBar" android:id="@+id/toolBar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize" android:layout_height="?attr/actionBarSize"
app:theme="@style/ToolBarStyle" app:theme="@style/ToolBarStyle"
app:popupTheme="?attr/toolbarPopupTheme" /> app:popupTheme="?attr/toolbarPopupTheme" />
</android.support.design.widget.AppBarLayout> </com.google.android.material.appbar.AppBarLayout>
<FrameLayout <FrameLayout
android:id="@+id/drawer_layout" android:id="@+id/drawer_layout"
@ -66,7 +66,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<android.support.v4.widget.SwipeRefreshLayout <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/swipeRefreshLayout" android:id="@+id/swipeRefreshLayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
@ -89,7 +89,7 @@
android:background="@color/transparent" android:background="@color/transparent"
android:visibility="gone" /> android:visibility="gone" />
<android.support.v7.widget.RecyclerView <androidx.recyclerview.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"
@ -100,16 +100,16 @@
app:layout_behavior="@string/appbar_scrolling_view_behavior" /> app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</LinearLayout> </LinearLayout>
</android.support.v4.widget.SwipeRefreshLayout> </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
</FrameLayout> </FrameLayout>
</LinearLayout> </LinearLayout>
</android.support.design.widget.CoordinatorLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>
<com.ashokvarma.bottomnavigation.BottomNavigationBar <com.ashokvarma.bottomnavigation.BottomNavigationBar
android:layout_gravity="bottom" android:layout_gravity="bottom"
android:id="@+id/bottomBar" android:id="@+id/bottomBar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="60dp"/> android:layout_height="60dp"/>
</android.support.design.widget.CoordinatorLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>
</RelativeLayout> </RelativeLayout>

View File

@ -6,18 +6,18 @@
android:gravity="center_horizontal" android:gravity="center_horizontal"
android:orientation="vertical" android:orientation="vertical"
tools:context="apps.amine.bou.readerforselfoss.LoginActivity"> tools:context="apps.amine.bou.readerforselfoss.LoginActivity">
<android.support.design.widget.AppBarLayout <com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar <androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar" android:id="@+id/toolbar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize" android:layout_height="?attr/actionBarSize"
app:theme="@style/ToolBarStyle" app:theme="@style/ToolBarStyle"
app:popupTheme="?attr/toolbarPopupTheme" /> app:popupTheme="?attr/toolbarPopupTheme" />
</android.support.design.widget.AppBarLayout> </com.google.android.material.appbar.AppBarLayout>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
@ -45,7 +45,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical"> android:orientation="vertical">
<android.support.design.widget.TextInputLayout <com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:id="@+id/urlLayout" android:id="@+id/urlLayout"
@ -60,7 +60,7 @@
android:inputType="textUri" android:inputType="textUri"
android:maxLines="1" /> android:maxLines="1" />
</android.support.design.widget.TextInputLayout> </com.google.android.material.textfield.TextInputLayout>
<Switch <Switch
android:text="@string/withLoginSwitch" android:text="@string/withLoginSwitch"
@ -69,7 +69,7 @@
android:id="@+id/withLogin" android:id="@+id/withLogin"
android:layout_weight="1"/> android:layout_weight="1"/>
<android.support.design.widget.TextInputLayout <com.google.android.material.textfield.TextInputLayout
android:id="@+id/loginLayout" android:id="@+id/loginLayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -83,9 +83,9 @@
android:inputType="text" android:inputType="text"
android:maxLines="1" /> android:maxLines="1" />
</android.support.design.widget.TextInputLayout> </com.google.android.material.textfield.TextInputLayout>
<android.support.design.widget.TextInputLayout <com.google.android.material.textfield.TextInputLayout
android:id="@+id/passwordLayout" android:id="@+id/passwordLayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -99,7 +99,7 @@
android:inputType="textPassword" android:inputType="textPassword"
android:maxLines="1" /> android:maxLines="1" />
</android.support.design.widget.TextInputLayout> </com.google.android.material.textfield.TextInputLayout>
<Switch <Switch
android:id="@+id/withHttpLogin" android:id="@+id/withHttpLogin"
@ -108,7 +108,7 @@
android:layout_weight="1" android:layout_weight="1"
android:text="@string/withHttpLoginSwitch" /> android:text="@string/withHttpLoginSwitch" />
<android.support.design.widget.TextInputLayout <com.google.android.material.textfield.TextInputLayout
android:id="@+id/httpLoginInput" android:id="@+id/httpLoginInput"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
@ -120,9 +120,9 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:hint="@string/prompt_http_login" /> android:hint="@string/prompt_http_login" />
</android.support.design.widget.TextInputLayout> </com.google.android.material.textfield.TextInputLayout>
<android.support.design.widget.TextInputLayout <com.google.android.material.textfield.TextInputLayout
android:id="@+id/httpPasswordInput" android:id="@+id/httpPasswordInput"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
@ -134,7 +134,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:hint="@string/prompt_http_password" android:hint="@string/prompt_http_password"
android:inputType="textPassword" /> android:inputType="textPassword" />
</android.support.design.widget.TextInputLayout> </com.google.android.material.textfield.TextInputLayout>
<Switch <Switch
android:id="@+id/withSelfhostedCert" android:id="@+id/withSelfhostedCert"

View File

@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
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.MainActivity"> tools:context="apps.amine.bou.readerforselfoss.MainActivity">
</android.support.constraint.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,10 +1,10 @@
<?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" <androidx.constraintlayout.widget.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"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout <com.google.android.material.appbar.AppBarLayout
android:id="@+id/appBarLayout" android:id="@+id/appBarLayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -12,16 +12,16 @@
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"> app:layout_constraintTop_toTopOf="parent">
<android.support.v7.widget.Toolbar <androidx.appcompat.widget.Toolbar
android:id="@+id/toolBar" android:id="@+id/toolBar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize" android:layout_height="?attr/actionBarSize"
app:popupTheme="?attr/toolbarPopupTheme" app:popupTheme="?attr/toolbarPopupTheme"
app:theme="@style/ToolBarStyle" /> app:theme="@style/ToolBarStyle" />
</android.support.design.widget.AppBarLayout> </com.google.android.material.appbar.AppBarLayout>
<android.support.v4.view.ViewPager <androidx.viewpager.widget.ViewPager
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"
@ -41,4 +41,4 @@
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" /> app:layout_constraintTop_toTopOf="@+id/pager" />
</android.support.constraint.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,33 +1,33 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.coordinatorlayout.widget.CoordinatorLayout 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">
<android.support.design.widget.AppBarLayout <com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar <androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar" android:id="@+id/toolbar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize" android:layout_height="?attr/actionBarSize"
app:theme="@style/ToolBarStyle" app:theme="@style/ToolBarStyle"
app:popupTheme="?attr/toolbarPopupTheme" /> app:popupTheme="?attr/toolbarPopupTheme" />
</android.support.design.widget.AppBarLayout> </com.google.android.material.appbar.AppBarLayout>
<android.support.v7.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView" android:id="@+id/recyclerView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:scrollbars="vertical" android:scrollbars="vertical"
app:layout_behavior="@string/appbar_scrolling_view_behavior"> app:layout_behavior="@string/appbar_scrolling_view_behavior">
</android.support.v7.widget.RecyclerView> </androidx.recyclerview.widget.RecyclerView>
<android.support.design.widget.FloatingActionButton <com.google.android.material.floatingactionbutton.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"
@ -42,4 +42,4 @@
android:layout_marginEnd="16dp" android:layout_marginEnd="16dp"
android:layout_marginRight="16dp" android:layout_marginRight="16dp"
app:layout_behavior="apps.amine.bou.readerforselfoss.utils.ScrollAwareFABBehavior" /> app:layout_behavior="apps.amine.bou.readerforselfoss.utils.ScrollAwareFABBehavior" />
</android.support.design.widget.CoordinatorLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView <androidx.cardview.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:card_view="http://schemas.android.com/apk/res-auto" xmlns:card_view="http://schemas.android.com/apk/res-auto"
@ -18,7 +18,7 @@
card_view:cardUseCompatPadding="true" card_view:cardUseCompatPadding="true"
card_view:layout_constraintBottom_toBottomOf="parent"> card_view:layout_constraintBottom_toBottomOf="parent">
<android.support.constraint.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
@ -34,7 +34,7 @@
app:srcCompat="@drawable/background_splash" app:srcCompat="@drawable/background_splash"
card_view:layout_constraintBottom_toTopOf="@+id/constraintLayout" /> card_view:layout_constraintBottom_toTopOf="@+id/constraintLayout" />
<android.support.constraint.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/constraintLayout" android:id="@+id/constraintLayout"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -143,7 +143,7 @@
</RelativeLayout> </RelativeLayout>
</android.support.constraint.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</android.support.constraint.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</android.support.v7.widget.CardView> </androidx.cardview.widget.CardView>

View File

@ -1,4 +1,4 @@
<android.support.design.widget.CoordinatorLayout <androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
@ -6,12 +6,12 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:descendantFocusability="blocksDescendants"> android:descendantFocusability="blocksDescendants">
<android.support.v4.widget.NestedScrollView <androidx.core.widget.NestedScrollView
android:id="@+id/nestedScrollView" android:id="@+id/nestedScrollView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<android.support.constraint.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
@ -70,9 +70,9 @@
app:layout_constraintTop_toBottomOf="@+id/source" app:layout_constraintTop_toBottomOf="@+id/source"
tools:visibility="visible" /> tools:visibility="visible" />
</android.support.constraint.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</android.support.v4.widget.NestedScrollView> </androidx.core.widget.NestedScrollView>
<FrameLayout <FrameLayout
android:layout_width="match_parent" android:layout_width="match_parent"
@ -89,7 +89,7 @@
android:layout_gravity="bottom" android:layout_gravity="bottom"
app:floatingMenu="@menu/reader_toolbar" /> app:floatingMenu="@menu/reader_toolbar" />
<android.support.design.widget.FloatingActionButton <com.google.android.material.floatingactionbutton.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"
@ -123,4 +123,4 @@
android:progressTint="?attr/colorAccent" /> android:progressTint="?attr/colorAccent" />
</FrameLayout> </FrameLayout>
</android.support.design.widget.CoordinatorLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -1,5 +1,5 @@
<?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" <androidx.constraintlayout.widget.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" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
@ -115,4 +115,4 @@
</RelativeLayout> </RelativeLayout>
</android.support.constraint.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,15 +1,15 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.AppBarLayout <com.google.android.material.appbar.AppBarLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"> xmlns:app="http://schemas.android.com/apk/res-auto">
<android.support.v7.widget.Toolbar <androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar" android:id="@+id/toolbar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize" android:layout_height="?attr/actionBarSize"
app:theme="@style/ToolBarStyle" app:theme="@style/ToolBarStyle"
app:popupTheme="?attr/toolbarPopupTheme" /> app:popupTheme="?attr/toolbarPopupTheme" />
</android.support.design.widget.AppBarLayout> </com.google.android.material.appbar.AppBarLayout>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
@ -52,4 +52,4 @@
android:layout_width="34dp" android:layout_width="34dp"
android:layout_height="34dp"/> android:layout_height="34dp"/>
</android.support.constraint.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -6,7 +6,7 @@
android:title="@string/menu_home_search" android:title="@string/menu_home_search"
android:icon="@drawable/ic_action_search" android:icon="@drawable/ic_action_search"
app:showAsAction="ifRoom|collapseActionView" app:showAsAction="ifRoom|collapseActionView"
app:actionViewClass="android.support.v7.widget.SearchView" /> app:actionViewClass="androidx.appcompat.widget.SearchView" />
<item android:id="@+id/readAll" <item android:id="@+id/readAll"
android:icon="@drawable/ic_done_all_white_24dp" android:icon="@drawable/ic_done_all_white_24dp"

View File

@ -2,61 +2,61 @@
<!--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 for Selfoss"</string> <string name="app_name">"Reader for Selfoss"</string>
<string name="title_activity_login">"Log in"</string> <string name="title_activity_login">"로그인"</string>
<string name="prompt_password">"Password"</string> <string name="prompt_password">"비밀번호"</string>
<string name="prompt_http_password">"HTTP Password"</string> <string name="prompt_http_password">"HTTP 암호"</string>
<string name="action_sign_in">"Go"</string> <string name="action_sign_in">"Go"</string>
<string name="error_invalid_password">"Password not long enough"</string> <string name="error_invalid_password">"패스워드가 짧습니다."</string>
<string name="error_field_required">"Field required"</string> <string name="error_field_required">"필수 항목"</string>
<string name="prompt_url">"Url"</string> <string name="prompt_url">"Url"</string>
<string name="withLoginSwitch">"Login required ?"</string> <string name="withLoginSwitch">"로그인이 필요합니까?"</string>
<string name="withHttpLoginSwitch">"HTTP Login required ?"</string> <string name="withHttpLoginSwitch">"HTTP 로그인이 필요 합니까?"</string>
<string name="login_url_problem">"Oops. You may need to add a \"/\" at the end of the url."</string> <string name="login_url_problem">"죄송합니다. Url의 끝에 \"/\"를 추가할 필요가 있습니다."</string>
<string name="prompt_login">"Username"</string> <string name="prompt_login">"사용자 이름"</string>
<string name="prompt_http_login">"HTTP Username"</string> <string name="prompt_http_login">"HTTP 사용자 이름"</string>
<string name="label_share">"Share"</string> <string name="label_share">"공유"</string>
<string name="readAll">"Read all"</string> <string name="readAll">"모두 읽기"</string>
<string name="action_disconnect">"Disconnect"</string> <string name="action_disconnect">"연결 해제"</string>
<string name="title_activity_settings">"Settings"</string> <string name="title_activity_settings">"설정"</string>
<string name="pref_header_general">"General"</string> <string name="pref_header_general">"일반"</string>
<string name="pref_switch_actions_tap_title">"Tap action on the articles"</string> <string name="pref_switch_actions_tap_title">"기사에 탭 액션"</string>
<string name="add_source_hint_tags">"Tag1, Tag2, Tag3"</string> <string name="add_source_hint_tags">"태그1, 태그2, 태그3"</string>
<string name="add_source_hint_url">"Link"</string> <string name="add_source_hint_url">"링크"</string>
<string name="add_source_hint_name">"Name"</string> <string name="add_source_hint_name">"이름"</string>
<string name="add_source">"Add a source"</string> <string name="add_source">"소스 추가"</string>
<string name="add_source_save">"Save"</string> <string name="add_source_save">"저장"</string>
<string name="wrong_infos">"Check your details again."</string> <string name="wrong_infos">"세부 정보를 다시 확인하세요."</string>
<string name="all_posts_not_read">"All posts weren't read"</string> <string name="all_posts_not_read">"모든 게시물을 읽지 않았습니다."</string>
<string name="all_posts_read">"All posts were read"</string> <string name="all_posts_read">"모든 게시물을 읽었습니다."</string>
<string name="cant_get_favs">"Can't get favorites"</string> <string name="cant_get_favs">"즐겨찾기를 가져올 수 없습니다."</string>
<string name="cant_get_new_elements">"Can't get new articles"</string> <string name="cant_get_new_elements">"새로운 기사를 가져올 수 없습니다."</string>
<string name="cant_get_read">"Can't get read articles"</string> <string name="cant_get_read">"읽은 기사를 가져올 수 없습니다."</string>
<string name="nothing_here">"Nothing here"</string> <string name="nothing_here">"비어있음"</string>
<string name="tab_new">"New"</string> <string name="tab_new">"새로운"</string>
<string name="tab_read">"All"</string> <string name="tab_read">"전체"</string>
<string name="tab_favs">"Favorites"</string> <string name="tab_favs">"즐겨찾기"</string>
<string name="action_about">"About"</string> <string name="action_about">"정보"</string>
<string name="marked_as_read">"Item read"</string> <string name="marked_as_read">"항목 읽기"</string>
<string name="undo_string">"Undo"</string> <string name="undo_string">"실행 취소"</string>
<string name="addStringNoUrl">"Log in to add sources."</string> <string name="addStringNoUrl">"로그인 소스를 추가 해야 합니다."</string>
<string name="cant_get_sources">"Can't get sources list."</string> <string name="cant_get_sources">"소스 리스트를 얻을 수 없습니다."</string>
<string name="cant_create_source">"Can't create source."</string> <string name="cant_create_source">"소스를 만들 수 없습니다."</string>
<string name="cant_get_spouts">"Can't get spouts list."</string> <string name="cant_get_spouts">"Spouts 목록을 가져올 수 없습니다."</string>
<string name="form_not_complete">"The form is not complete"</string> <string name="form_not_complete">"양식이 완료되지 않았습니다."</string>
<string name="pref_header_links">"Links"</string> <string name="pref_header_links">"링크"</string>
<string name="issue_tracker_link">"Issue Tracker"</string> <string name="issue_tracker_link">"이슈 트래커"</string>
<string name="issue_tracker_summary">"Report a bug or ask for a new feature"</string> <string name="issue_tracker_summary">"버그를 보고 하거나 새기능에 대해 요청하세요."</string>
<string name="warning_wrong_url">"WARNING"</string> <string name="warning_wrong_url">"경고"</string>
<string name="pref_switch_card_view_title">"Card View"</string> <string name="pref_switch_card_view_title">"카드 형식 보기"</string>
<string name="cant_mark_favortie">"Can't mark article as favorite"</string> <string name="cant_mark_favortie">"좋아하는 문서를 마크할 수 없습니다."</string>
<string name="cant_unmark_favortie">"Can't remove item from favorite"</string> <string name="cant_unmark_favortie">"좋아하는 항목에서 제거할 수 없습니다."</string>
<string name="share">"Share"</string> <string name="share">"공유"</string>
<string name="rating_prompt_title">"Enjoying the app ?"</string> <string name="rating_prompt_title">"이 앱에 만족하십니까?"</string>
<string name="rating_prompt_yes">"Yes !"</string> <string name="rating_prompt_yes">"!"</string>
<string name="rating_prompt_no">"Not really …"</string> <string name="rating_prompt_no">"설마..."</string>
<string name="rating_prompt_feedback_title">"Can you tell us why ?"</string> <string name="rating_prompt_feedback_title">"이유를 우리에게 말해줄 수 있습니까?"</string>
<string name="rating_prompt_feedback_yes">"OK !"</string> <string name="rating_prompt_feedback_yes">"OK!"</string>
<string name="rating_prompt_feedback_no">"Not now."</string> <string name="rating_prompt_feedback_no">"나중에"</string>
<string name="rating_prompt_rating_title">"Great ! Can you rate us on the Store ?"</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_yes">"Sure !"</string>
<string name="rating_prompt_rating_no">"Not right now."</string> <string name="rating_prompt_rating_no">"Not right now."</string>

View File

@ -7,22 +7,22 @@
android:key="dark_theme" android:key="dark_theme"
android:title="Dark theme" /> android:title="Dark theme" />
<com.jrummyapps.android.colorpicker.ColorPreference <com.jaredrummler.android.colorpicker.ColorPreference
android:defaultValue="@color/colorPrimary" android:defaultValue="@color/colorPrimary"
android:key="color_primary" android:key="color_primary"
android:title="Primary color"/> android:title="Primary color"/>
<com.jrummyapps.android.colorpicker.ColorPreference <com.jaredrummler.android.colorpicker.ColorPreference
android:defaultValue="@color/colorPrimaryDark" android:defaultValue="@color/colorPrimaryDark"
android:key="color_primary_dark" android:key="color_primary_dark"
android:title="Primary dark color"/> android:title="Primary dark color"/>
<com.jrummyapps.android.colorpicker.ColorPreference <com.jaredrummler.android.colorpicker.ColorPreference
android:defaultValue="@color/colorAccent" android:defaultValue="@color/colorAccent"
android:key="color_accent" android:key="color_accent"
android:title="Accent color"/> android:title="Accent color"/>
<com.jrummyapps.android.colorpicker.ColorPreference <com.jaredrummler.android.colorpicker.ColorPreference
android:defaultValue="@color/colorAccentDark" android:defaultValue="@color/colorAccentDark"
android:key="color_accent_dark" android:key="color_accent_dark"
android:title="Accent dark color"/> android:title="Accent dark color"/>

View File

@ -3,11 +3,13 @@
buildscript { buildscript {
ext { ext {
kotlin_version = '1.2.51' kotlin_version = '1.2.51'
android_version = '28.0.0' android_version = '1.0.0'
lifecycle_version = '2.0.0'
room_version = '2.1.0-alpha01'
} }
repositories { repositories {
jcenter()
google() google()
jcenter()
maven { maven {
url "https://jitpack.io" url "https://jitpack.io"
} }
@ -23,7 +25,7 @@ allprojects {
// For likebutton only // For likebutton only
maven { url "https://jitpack.io" } maven { url "https://jitpack.io" }
maven { url 'https://maven.google.com' } google()
jcenter() jcenter()
mavenCentral() mavenCentral()
} }

View File

@ -16,4 +16,6 @@ org.gradle.jvmargs=-Xmx1536m
# 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 org.gradle.caching=true
android.enableD8=true android.enableD8=true
android.useAndroidX=true
android.enableJetifier=true