Code cleaning.

This commit is contained in:
Amine 2017-06-10 07:40:02 +02:00
parent 58a5b4a5e5
commit c14f47a74b
27 changed files with 811 additions and 697 deletions

View File

@ -25,8 +25,8 @@ android {
applicationId "apps.amine.bou.readerforselfoss" applicationId "apps.amine.bou.readerforselfoss"
minSdkVersion 16 minSdkVersion 16
targetSdkVersion 25 targetSdkVersion 25
versionCode 1511 versionCode 1512
versionName "1.5.1.1" versionName "1.5.1.2"
// Enabling multidex support. // Enabling multidex support.
multiDexEnabled true multiDexEnabled true

View File

@ -6,14 +6,17 @@ import android.support.constraint.ConstraintLayout
import android.support.v7.app.AppCompatActivity import android.support.v7.app.AppCompatActivity
import android.view.View import android.view.View
import android.widget.* import android.widget.*
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi
import apps.amine.bou.readerforselfoss.api.selfoss.Spout import apps.amine.bou.readerforselfoss.api.selfoss.Spout
import apps.amine.bou.readerforselfoss.api.selfoss.SuccessResponse import apps.amine.bou.readerforselfoss.api.selfoss.SuccessResponse
import apps.amine.bou.readerforselfoss.utils.Config import apps.amine.bou.readerforselfoss.utils.Config
import apps.amine.bou.readerforselfoss.utils.isUrlValid import apps.amine.bou.readerforselfoss.utils.isUrlValid
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
class AddSourceActivity : AppCompatActivity() { class AddSourceActivity : AppCompatActivity() {
@ -39,15 +42,15 @@ class AddSourceActivity : AppCompatActivity() {
mustLoginToAddSource() mustLoginToAddSource()
} }
val intent = intent val intent = intent
if (Intent.ACTION_SEND == intent.action && "text/plain" == intent.type) { if (Intent.ACTION_SEND == intent.action && "text/plain" == intent.type) {
mSourceUri.setText(intent.getStringExtra(Intent.EXTRA_TEXT)) mSourceUri.setText(intent.getStringExtra(Intent.EXTRA_TEXT))
mNameInput.setText(intent.getStringExtra(Intent.EXTRA_TITLE)) mNameInput.setText(intent.getStringExtra(Intent.EXTRA_TITLE))
} }
mSaveBtn.setOnClickListener { handleSaveSource(mTags, mNameInput.text.toString(), mSourceUri.text.toString(), api!!) } mSaveBtn.setOnClickListener {
handleSaveSource(mTags, mNameInput.text.toString(), mSourceUri.text.toString(), api!!)
}
val spoutsKV = HashMap<String, String>() val spoutsKV = HashMap<String, String>()
@ -82,7 +85,11 @@ class AddSourceActivity : AppCompatActivity() {
mProgress.visibility = View.GONE mProgress.visibility = View.GONE
mForm.visibility = View.VISIBLE mForm.visibility = View.VISIBLE
val spinnerArrayAdapter = ArrayAdapter(this@AddSourceActivity, android.R.layout.simple_spinner_item, itemsStrings) val spinnerArrayAdapter =
ArrayAdapter(
this@AddSourceActivity,
android.R.layout.simple_spinner_item,
itemsStrings)
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
mSpoutsSpinner.adapter = spinnerArrayAdapter mSpoutsSpinner.adapter = spinnerArrayAdapter
@ -115,7 +122,13 @@ class AddSourceActivity : AppCompatActivity() {
if (title.isEmpty() || url.isEmpty() || mSpoutsValue == null || mSpoutsValue!!.isEmpty()) { if (title.isEmpty() || url.isEmpty() || mSpoutsValue == null || mSpoutsValue!!.isEmpty()) {
Toast.makeText(this, R.string.form_not_complete, Toast.LENGTH_SHORT).show() Toast.makeText(this, R.string.form_not_complete, Toast.LENGTH_SHORT).show()
} else { } else {
api.createSource(title, url, mSpoutsValue!!, mTags.text.toString(), "").enqueue(object : Callback<SuccessResponse> { api.createSource(
title,
url,
mSpoutsValue!!,
mTags.text.toString(),
""
).enqueue(object : Callback<SuccessResponse> {
override fun onResponse(call: Call<SuccessResponse>, response: Response<SuccessResponse>) { override fun onResponse(call: Call<SuccessResponse>, response: Response<SuccessResponse>) {
if (response.body() != null && response.body()!!.isSuccess) { if (response.body() != null && response.body()!!.isSuccess) {
finish() finish()

View File

@ -1,5 +1,7 @@
package apps.amine.bou.readerforselfoss package apps.amine.bou.readerforselfoss
import java.lang.Exception
import android.app.Activity import android.app.Activity
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
@ -19,16 +21,7 @@ import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
import android.widget.Toast import android.widget.Toast
import apps.amine.bou.readerforselfoss.adapters.ItemCardAdapter
import apps.amine.bou.readerforselfoss.adapters.ItemListAdapter
import apps.amine.bou.readerforselfoss.api.selfoss.*
import apps.amine.bou.readerforselfoss.settings.SettingsActivity
import apps.amine.bou.readerforselfoss.utils.Config
import apps.amine.bou.readerforselfoss.utils.checkAndDisplayStoreApk
import apps.amine.bou.readerforselfoss.utils.checkApkVersion
import apps.amine.bou.readerforselfoss.utils.customtabs.CustomTabActivityHelper
import apps.amine.bou.readerforselfoss.utils.drawer.CustomUrlPrimaryDrawerItem
import apps.amine.bou.readerforselfoss.utils.longHash
import com.anupcowkur.reservoir.Reservoir import com.anupcowkur.reservoir.Reservoir
import com.anupcowkur.reservoir.ReservoirGetCallback import com.anupcowkur.reservoir.ReservoirGetCallback
import com.anupcowkur.reservoir.ReservoirPutCallback import com.anupcowkur.reservoir.ReservoirPutCallback
@ -54,7 +47,19 @@ import com.roughike.bottombar.BottomBarTab
import retrofit2.Call import retrofit2.Call
import retrofit2.Callback import retrofit2.Callback
import retrofit2.Response import retrofit2.Response
import java.lang.Exception
import apps.amine.bou.readerforselfoss.adapters.ItemCardAdapter
import apps.amine.bou.readerforselfoss.adapters.ItemListAdapter
import apps.amine.bou.readerforselfoss.api.selfoss.*
import apps.amine.bou.readerforselfoss.settings.SettingsActivity
import apps.amine.bou.readerforselfoss.utils.Config
import apps.amine.bou.readerforselfoss.utils.checkAndDisplayStoreApk
import apps.amine.bou.readerforselfoss.utils.checkApkVersion
import apps.amine.bou.readerforselfoss.utils.customtabs.CustomTabActivityHelper
import apps.amine.bou.readerforselfoss.utils.drawer.CustomUrlPrimaryDrawerItem
import apps.amine.bou.readerforselfoss.utils.longHash
class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener { class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
@ -64,48 +69,136 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
private val DRAWER_ID_TAGS = 100101L private val DRAWER_ID_TAGS = 100101L
private val DRAWER_ID_SOURCES = 100110L private val DRAWER_ID_SOURCES = 100110L
private val DRAWER_ID_FILTERS = 100111L private val DRAWER_ID_FILTERS = 100111L
private var mRecyclerView: RecyclerView? = null private val UNREAD_SHOWN = 1
private var api: SelfossApi? = null private val READ_SHOWN = 2
private var items: ArrayList<Item> = ArrayList() private val FAV_SHOWN = 3
private var mCustomTabActivityHelper: CustomTabActivityHelper? = null
private var items: ArrayList<Item> = ArrayList()
private var clickBehavior = false private var clickBehavior = false
private var internalBrowser = false private var internalBrowser = false
private var articleViewer = false private var articleViewer = false
private var shouldBeCardView = false private var shouldBeCardView = false
private var displayUnreadCount = false private var displayUnreadCount = false
private var displayAllCount = false private var displayAllCount = false
private var editor: SharedPreferences.Editor? = null
private val UNREAD_SHOWN = 1
private val READ_SHOWN = 2
private val FAV_SHOWN = 3
private var elementsShown: Int = 0
private var mBottomBar: BottomBar? = null
private var mCoordinatorLayout: CoordinatorLayout? = null
private var mSwipeRefreshLayout: SwipeRefreshLayout? = null
private var sharedPref: SharedPreferences? = null
private var tabNew: BottomBarTab? = null
private var tabArchive: BottomBarTab? = null
private var tabStarred: BottomBarTab? = null
private var mFirebaseRemoteConfig: FirebaseRemoteConfig? = null
private var fullHeightCards: Boolean = false private var fullHeightCards: Boolean = false
private var toolbar: Toolbar? = null private var elementsShown: Int = 0
private var drawer: Drawer? = null
private var maybeTagFilter: Tag? = null private var maybeTagFilter: Tag? = null
private var maybeSourceFilter: Sources? = null private var maybeSourceFilter: Sources? = null
private var maybeSearchFilter: String? = null private var maybeSearchFilter: String? = null
private lateinit var mRecyclerView: RecyclerView
private lateinit var mBottomBar: BottomBar
private lateinit var mCoordinatorLayout: CoordinatorLayout
private lateinit var mSwipeRefreshLayout: SwipeRefreshLayout
private lateinit var tabNew: BottomBarTab
private lateinit var tabArchive: BottomBarTab
private lateinit var tabStarred: BottomBarTab
private lateinit var toolbar: Toolbar
private lateinit var drawer: Drawer
private lateinit var api: SelfossApi
private lateinit var mCustomTabActivityHelper: CustomTabActivityHelper
private lateinit var editor: SharedPreferences.Editor
private lateinit var sharedPref: SharedPreferences
private lateinit var mFirebaseRemoteConfig: FirebaseRemoteConfig
data class DrawerData(val tags: List<Tag>?, val sources: List<Sources>?) data class DrawerData(val tags: List<Tag>?, val sources: List<Sources>?)
private fun handleSharedPrefs() {
clickBehavior = this.sharedPref!!.getBoolean("tab_on_tap", false)
internalBrowser = this.sharedPref!!.getBoolean("prefer_internal_browser", true) override fun onStart() {
articleViewer = this.sharedPref!!.getBoolean("prefer_article_viewer", true) super.onStart()
shouldBeCardView = this.sharedPref!!.getBoolean("card_view_active", false) mCustomTabActivityHelper.bindCustomTabsService(this)
displayUnreadCount = this.sharedPref!!.getBoolean("display_unread_count", true) }
displayAllCount = this.sharedPref!!.getBoolean("display_other_count", false)
fullHeightCards = this.sharedPref!!.getBoolean("full_height_cards", false) override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_home)
toolbar = findViewById(R.id.toolbar) as Toolbar
setSupportActionBar(toolbar)
if (savedInstanceState == null) {
val promptView = findViewById(R.id.prompt_view) as DefaultLayoutPromptView
Amplify.getSharedInstance().promptIfReady(promptView)
}
mFirebaseRemoteConfig = FirebaseRemoteConfig.getInstance()
mFirebaseRemoteConfig.setDefaults(R.xml.default_remote_config)
mCustomTabActivityHelper = CustomTabActivityHelper()
api = SelfossApi(this)
items = ArrayList()
mBottomBar = findViewById(R.id.bottomBar) as BottomBar
handleDrawer()
// TODO: clean this hack
val listenerAlreadySet = booleanArrayOf(false)
mBottomBar.setOnTabSelectListener { tabId ->
if (listenerAlreadySet[0]) {
if (tabId == R.id.tab_new) {
getUnRead()
} else if (tabId == R.id.tab_archive) {
getRead()
} else if (tabId == R.id.tab_fav) {
getStarred()
}
getElementsAccordingToTab()
} else {
listenerAlreadySet[0] = true
}
}
mCoordinatorLayout = findViewById(R.id.coordLayout) as CoordinatorLayout
mSwipeRefreshLayout = findViewById(R.id.swipeRefreshLayout) as SwipeRefreshLayout
mRecyclerView = findViewById(R.id.my_recycler_view) as RecyclerView
reloadLayoutManager()
mSwipeRefreshLayout.setColorSchemeResources(
R.color.refresh_progress_1,
R.color.refresh_progress_2,
R.color.refresh_progress_3)
mSwipeRefreshLayout.setOnRefreshListener {
handleDrawerItems()
getElementsAccordingToTab()
}
val simpleItemTouchCallback =
object : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT) {
override fun getSwipeDirs(recyclerView: RecyclerView?, viewHolder: RecyclerView.ViewHolder?): Int =
if (elementsShown != UNREAD_SHOWN) 0 else super.getSwipeDirs(recyclerView, viewHolder)
override fun onMove(recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder): Boolean = false
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, swipeDir: Int) {
try {
val i = items[viewHolder.adapterPosition]
val position = items.indexOf(i)
if (shouldBeCardView) {
(mRecyclerView.adapter as ItemCardAdapter).removeItemAtIndex(position)
} else {
(mRecyclerView.adapter as ItemListAdapter).removeItemAtIndex(position)
}
tabNew.setBadgeCount(items.size - 1)
} catch (e: IndexOutOfBoundsException) {}
}
}
ItemTouchHelper(simpleItemTouchCallback).attachToRecyclerView(mRecyclerView)
checkAndDisplayStoreApk(this@HomeActivity)
} }
override fun onResume() { override fun onResume() {
@ -119,75 +212,100 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
editor = settings.edit() editor = settings.edit()
if (BuildConfig.GITHUB_VERSION) { if (BuildConfig.GITHUB_VERSION) {
checkApkVersion(settings, editor!!, this@HomeActivity, mFirebaseRemoteConfig!!) checkApkVersion(settings, editor, this@HomeActivity, mFirebaseRemoteConfig)
} }
handleSharedPrefs() handleSharedPrefs()
tabNew = mBottomBar!!.getTabWithId(R.id.tab_new) tabNew = mBottomBar.getTabWithId(R.id.tab_new)
tabArchive = mBottomBar!!.getTabWithId(R.id.tab_archive) tabArchive = mBottomBar.getTabWithId(R.id.tab_archive)
tabStarred = mBottomBar!!.getTabWithId(R.id.tab_fav) tabStarred = mBottomBar.getTabWithId(R.id.tab_fav)
getElementsAccordingToTab() getElementsAccordingToTab()
} }
fun handleDrawer() { override fun onStop() {
super.onStop()
mCustomTabActivityHelper.unbindCustomTabsService(this)
}
private fun handleSharedPrefs() {
clickBehavior = sharedPref.getBoolean("tab_on_tap", false)
internalBrowser = sharedPref.getBoolean("prefer_internal_browser", true)
articleViewer = sharedPref.getBoolean("prefer_article_viewer", true)
shouldBeCardView = sharedPref.getBoolean("card_view_active", false)
displayUnreadCount = sharedPref.getBoolean("display_unread_count", true)
displayAllCount = sharedPref.getBoolean("display_other_count", false)
fullHeightCards = sharedPref.getBoolean("full_height_cards", false)
}
private fun handleDrawer() {
drawer = DrawerBuilder() drawer = DrawerBuilder()
.withActivity(this) .withActivity(this)
.withRootView(R.id.drawer_layout) .withRootView(R.id.drawer_layout)
.withToolbar(toolbar!!) .withToolbar(toolbar)
.withActionBarDrawerToggle(true) .withActionBarDrawerToggle(true)
.withActionBarDrawerToggleAnimated(true) .withActionBarDrawerToggleAnimated(true)
.withShowDrawerOnFirstLaunch(true) .withShowDrawerOnFirstLaunch(true)
.withOnDrawerListener(object: Drawer.OnDrawerListener { .withOnDrawerListener(object: Drawer.OnDrawerListener {
override fun onDrawerSlide(p0: View?, p1: Float) { override fun onDrawerSlide(v: View?, p1: Float) {
mBottomBar!!.alpha = (1 - p1) mBottomBar.alpha = (1 - p1)
} }
override fun onDrawerClosed(p0: View?) { override fun onDrawerClosed(v: View?) {
mBottomBar!!.shySettings.showBar() mBottomBar.shySettings.showBar()
} }
override fun onDrawerOpened(p0: View?) { override fun onDrawerOpened(v: View?) {
mBottomBar!!.shySettings.hideBar() mBottomBar.shySettings.hideBar()
} }
}) })
.build() .build()
drawer!!.addStickyFooterItem( drawer.addStickyFooterItem(
PrimaryDrawerItem() PrimaryDrawerItem()
.withName(R.string.action_about) .withName(R.string.action_about)
.withSelectable(false) .withSelectable(false)
.withIcon(R.drawable.ic_info_outline) .withIcon(R.drawable.ic_info_outline)
.withOnDrawerItemClickListener { _, _, _ -> .withOnDrawerItemClickListener { _, _, _ ->
LibsBuilder() LibsBuilder()
.withActivityStyle(Libs.ActivityStyle.LIGHT_DARK_TOOLBAR) .withActivityStyle(Libs.ActivityStyle.LIGHT_DARK_TOOLBAR)
.withAboutIconShown(true) .withAboutIconShown(true)
.withAboutVersionShown(true) .withAboutVersionShown(true)
.start(this@HomeActivity) .start(this@HomeActivity)
false false
}) })
drawer!!.addStickyFooterItem( drawer.addStickyFooterItem(
PrimaryDrawerItem() PrimaryDrawerItem()
.withName(R.string.title_activity_settings) .withName(R.string.title_activity_settings)
.withIcon(R.drawable.ic_settings) .withIcon(R.drawable.ic_settings)
.withOnDrawerItemClickListener { _, _, _ -> .withOnDrawerItemClickListener { _, _, _ ->
startActivityForResult(Intent(this@HomeActivity, SettingsActivity::class.java), MENU_PREFERENCES) startActivityForResult(
Intent(
this@HomeActivity,
SettingsActivity::class.java
),
MENU_PREFERENCES
)
false false
} }
) )
} }
fun handleDrawerItems() { private fun handleDrawerItems() {
fun handleDrawerData(maybeDrawerData: DrawerData?, loadedFromCache: Boolean = false) { fun handleDrawerData(maybeDrawerData: DrawerData?, loadedFromCache: Boolean = false) {
fun handleTags(maybeTags: List<Tag>?) { fun handleTags(maybeTags: List<Tag>?) {
if (maybeTags == null) { if (maybeTags == null) {
if (loadedFromCache) if (loadedFromCache)
drawer!!.addItem(SecondaryDrawerItem().withName(getString(R.string.drawer_error_loading_tags)).withSelectable(false)) drawer.addItem(
SecondaryDrawerItem()
.withName(getString(R.string.drawer_error_loading_tags))
.withSelectable(false))
} }
else { else {
for (tag in maybeTags) { for (tag in maybeTags) {
@ -196,7 +314,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
gd.shape = GradientDrawable.RECTANGLE gd.shape = GradientDrawable.RECTANGLE
gd.setSize(30, 30) gd.setSize(30, 30)
gd.cornerRadius = 30F gd.cornerRadius = 30F
drawer!!.addItem( drawer.addItem(
PrimaryDrawerItem() PrimaryDrawerItem()
.withName(tag.tag) .withName(tag.tag)
.withIdentifier(longHash(tag.tag)) .withIdentifier(longHash(tag.tag))
@ -220,11 +338,14 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
fun handleSources(maybeSources: List<Sources>?) { fun handleSources(maybeSources: List<Sources>?) {
if (maybeSources == null) { if (maybeSources == null) {
if (loadedFromCache) if (loadedFromCache)
drawer!!.addItem(SecondaryDrawerItem().withName(getString(R.string.drawer_error_loading_sources)).withSelectable(false)) drawer.addItem(
SecondaryDrawerItem()
.withName(getString(R.string.drawer_error_loading_sources))
.withSelectable(false))
} }
else else
for (tag in maybeSources) for (tag in maybeSources)
drawer!!.addItem( drawer.addItem(
CustomUrlPrimaryDrawerItem() CustomUrlPrimaryDrawerItem()
.withName(tag.title) .withName(tag.title)
.withIdentifier(tag.id.toLong()) .withIdentifier(tag.id.toLong())
@ -238,9 +359,9 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
} }
drawer!!.removeAllItems() drawer.removeAllItems()
if (maybeDrawerData != null) { if (maybeDrawerData != null) {
drawer!!.addItem( drawer.addItem(
SecondaryDrawerItem() SecondaryDrawerItem()
.withName(getString(R.string.drawer_item_filters)) .withName(getString(R.string.drawer_item_filters))
.withSelectable(false) .withSelectable(false)
@ -253,10 +374,14 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
false false
} }
) )
drawer!!.addItem(DividerDrawerItem()) drawer.addItem(DividerDrawerItem())
drawer!!.addItem(SecondaryDrawerItem().withName(getString(R.string.drawer_item_tags)).withIdentifier(DRAWER_ID_TAGS).withSelectable(false)) drawer.addItem(
SecondaryDrawerItem()
.withName(getString(R.string.drawer_item_tags))
.withIdentifier(DRAWER_ID_TAGS)
.withSelectable(false))
handleTags(maybeDrawerData.tags) handleTags(maybeDrawerData.tags)
drawer!!.addItem( drawer.addItem(
SecondaryDrawerItem() SecondaryDrawerItem()
.withName(getString(R.string.drawer_item_sources)) .withName(getString(R.string.drawer_item_sources))
.withIdentifier(DRAWER_ID_TAGS) .withIdentifier(DRAWER_ID_TAGS)
@ -280,8 +405,16 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
}) })
} else { } else {
if (!loadedFromCache) { if (!loadedFromCache) {
drawer!!.addItem(PrimaryDrawerItem().withName(getString(R.string.no_tags_loaded)).withIdentifier(DRAWER_ID_TAGS).withSelectable(false)) drawer.addItem(
drawer!!.addItem(PrimaryDrawerItem().withName(getString(R.string.no_sources_loaded)).withIdentifier(DRAWER_ID_SOURCES).withSelectable(false)) PrimaryDrawerItem()
.withName(getString(R.string.no_tags_loaded))
.withIdentifier(DRAWER_ID_TAGS)
.withSelectable(false))
drawer.addItem(
PrimaryDrawerItem()
.withName(getString(R.string.no_sources_loaded))
.withIdentifier(DRAWER_ID_SOURCES)
.withSelectable(false))
} }
} }
@ -292,11 +425,11 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
var sources: List<Sources>? var sources: List<Sources>?
fun sourcesApiCall() { fun sourcesApiCall() {
api!!.sources.enqueue(object: Callback<List<Sources>> { api.sources.enqueue(object: Callback<List<Sources>> {
override fun onResponse(call: Call<List<Sources>>?, response: Response<List<Sources>>) { override fun onResponse(call: Call<List<Sources>>?, response: Response<List<Sources>>) {
sources = response.body() sources = response.body()
val apiDrawerData = DrawerData(tags, sources) val apiDrawerData = DrawerData(tags, sources)
if (maybeDrawerData == null || (maybeDrawerData != null && maybeDrawerData != apiDrawerData)) if ((maybeDrawerData != null && maybeDrawerData != apiDrawerData) || maybeDrawerData == null)
handleDrawerData(apiDrawerData) handleDrawerData(apiDrawerData)
} }
@ -307,7 +440,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
}) })
} }
api!!.tags.enqueue(object: Callback<List<Tag>> { api.tags.enqueue(object: Callback<List<Tag>> {
override fun onResponse(call: Call<List<Tag>>, response: Response<List<Tag>>) { override fun onResponse(call: Call<List<Tag>>, response: Response<List<Tag>>) {
tags = response.body() tags = response.body()
sourcesApiCall() sourcesApiCall()
@ -320,7 +453,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
}) })
} }
drawer!!.addItem(PrimaryDrawerItem().withName(getString(R.string.drawer_loading)).withSelectable(false)) drawer.addItem(PrimaryDrawerItem().withName(getString(R.string.drawer_loading)).withSelectable(false))
val resultType = object : TypeToken<DrawerData>() {}.type val resultType = object : TypeToken<DrawerData>() {}.type
Reservoir.getAsync("drawerData", resultType, object: ReservoirGetCallback<DrawerData> { Reservoir.getAsync("drawerData", resultType, object: ReservoirGetCallback<DrawerData> {
@ -336,102 +469,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
}) })
} }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_home)
toolbar = findViewById(R.id.toolbar) as Toolbar?
setSupportActionBar(toolbar)
if (savedInstanceState == null) {
val promptView = findViewById(R.id.prompt_view) as DefaultLayoutPromptView
Amplify.getSharedInstance().promptIfReady(promptView)
}
mFirebaseRemoteConfig = FirebaseRemoteConfig.getInstance()
mFirebaseRemoteConfig!!.setDefaults(R.xml.default_remote_config)
mCustomTabActivityHelper = CustomTabActivityHelper()
api = SelfossApi(this)
items = ArrayList()
mBottomBar = findViewById(R.id.bottomBar) as BottomBar
handleDrawer()
// TODO: clean this hack
val listenerAlreadySet = booleanArrayOf(false)
mBottomBar!!.setOnTabSelectListener { tabId ->
if (listenerAlreadySet[0]) {
if (tabId == R.id.tab_new) {
getUnRead()
} else if (tabId == R.id.tab_archive) {
getRead()
} else if (tabId == R.id.tab_fav) {
getStarred()
}
getElementsAccordingToTab()
} else {
listenerAlreadySet[0] = true
}
}
mCoordinatorLayout = findViewById(R.id.coordLayout) as CoordinatorLayout
mSwipeRefreshLayout = findViewById(R.id.swipeRefreshLayout) as SwipeRefreshLayout
mRecyclerView = findViewById(R.id.my_recycler_view) as RecyclerView
reloadLayoutManager()
mSwipeRefreshLayout!!.setColorSchemeResources(
R.color.refresh_progress_1,
R.color.refresh_progress_2,
R.color.refresh_progress_3)
mSwipeRefreshLayout!!.setOnRefreshListener {
handleDrawerItems()
getElementsAccordingToTab()
}
val simpleItemTouchCallback = object : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT) {
override fun getSwipeDirs(recyclerView: RecyclerView?, viewHolder: RecyclerView.ViewHolder?): Int {
if (elementsShown != UNREAD_SHOWN) {
return 0
} else {
return super.getSwipeDirs(recyclerView, viewHolder)
}
}
override fun onMove(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder): Boolean {
return false
}
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, swipeDir: Int) {
try {
val i = items[viewHolder.adapterPosition]
val position = items.indexOf(i)
if (shouldBeCardView) {
(mRecyclerView!!.adapter as ItemCardAdapter).removeItemAtIndex(position)
} else {
(mRecyclerView!!.adapter as ItemListAdapter).removeItemAtIndex(position)
}
tabNew!!.setBadgeCount(items.size - 1)
} catch (e: IndexOutOfBoundsException) {
}
}
}
val itemTouchHelper = ItemTouchHelper(simpleItemTouchCallback)
itemTouchHelper.attachToRecyclerView(mRecyclerView)
checkAndDisplayStoreApk(this@HomeActivity)
}
private fun reloadLayoutManager() { private fun reloadLayoutManager() {
val mLayoutManager: RecyclerView.LayoutManager val mLayoutManager: RecyclerView.LayoutManager
if (shouldBeCardView) { if (shouldBeCardView) {
@ -441,10 +478,10 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
mLayoutManager = GridLayoutManager(this, calculateNoOfColumns()) mLayoutManager = GridLayoutManager(this, calculateNoOfColumns())
} }
mRecyclerView!!.layoutManager = mLayoutManager mRecyclerView.layoutManager = mLayoutManager
mRecyclerView!!.setHasFixedSize(true) mRecyclerView.setHasFixedSize(true)
mBottomBar!!.setOnTabReselectListener { mBottomBar.setOnTabReselectListener {
if (shouldBeCardView) { if (shouldBeCardView) {
if ((mLayoutManager as StaggeredGridLayoutManager).findFirstCompletelyVisibleItemPositions(null)[0] == 0) { if ((mLayoutManager as StaggeredGridLayoutManager).findFirstCompletelyVisibleItemPositions(null)[0] == 0) {
getElementsAccordingToTab() getElementsAccordingToTab()
@ -461,71 +498,56 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
} }
} }
private fun getElementsAccordingToTab() { private fun getElementsAccordingToTab() =
when (elementsShown) { when (elementsShown) {
UNREAD_SHOWN -> getUnRead() UNREAD_SHOWN -> getUnRead()
READ_SHOWN -> getRead() READ_SHOWN -> getRead()
FAV_SHOWN -> getStarred() FAV_SHOWN -> getStarred()
else -> getUnRead() else -> getUnRead()
} }
private fun doCallTo(toastMessage: Int, call: (String?, Long?, String?) -> Call<List<Item>>) {
fun handleItemsResponse(response: Response<List<Item>>) {
val didUpdate = (response.body() != items)
if (response.body() != null) {
if (response.body() != items) {
items = response.body() as ArrayList<Item>
}
} else {
items = ArrayList()
}
if (didUpdate)
handleListResult()
if (items.isEmpty()) Toast.makeText(this@HomeActivity, R.string.nothing_here, Toast.LENGTH_SHORT).show()
mSwipeRefreshLayout.isRefreshing = false
}
call(maybeTagFilter?.tag, maybeSourceFilter?.id?.toLong(), maybeSearchFilter)
.enqueue(object : Callback<List<Item>> {
override fun onResponse(call: Call<List<Item>>, response: Response<List<Item>>) {
handleItemsResponse(response)
}
override fun onFailure(call: Call<List<Item>>, t: Throwable) {
mSwipeRefreshLayout.isRefreshing = false
Toast.makeText(this@HomeActivity, toastMessage, Toast.LENGTH_SHORT).show()
}
})
} }
private fun getUnRead() { private fun getUnRead() {
elementsShown = UNREAD_SHOWN elementsShown = UNREAD_SHOWN
api!!.unreadItems(maybeTagFilter?.tag, maybeSourceFilter?.id?.toLong(), maybeSearchFilter).enqueue(object : Callback<List<Item>> { doCallTo(R.string.cant_get_new_elements){t, id, f -> api.unreadItems(t, id, f)}
override fun onResponse(call: Call<List<Item>>, response: Response<List<Item>>) {
handleItemsResponse(response)
}
override fun onFailure(call: Call<List<Item>>, t: Throwable) {
mSwipeRefreshLayout!!.isRefreshing = false
Toast.makeText(this@HomeActivity, R.string.cant_get_new_elements, Toast.LENGTH_SHORT).show()
}
})
}
private fun handleItemsResponse(response: Response<List<Item>>) {
val didUpdate = (response.body() != items)
if (response.body() != null) {
if (response.body() != items) {
items = response.body() as ArrayList<Item>
}
} else {
items = ArrayList()
}
if (didUpdate)
handleListResult()
if (items.isEmpty()) Toast.makeText(this@HomeActivity, R.string.nothing_here, Toast.LENGTH_SHORT).show()
mSwipeRefreshLayout!!.isRefreshing = false
} }
private fun getRead() { private fun getRead() {
elementsShown = READ_SHOWN elementsShown = READ_SHOWN
api!!.readItems(maybeTagFilter?.tag, maybeSourceFilter?.id?.toLong(), maybeSearchFilter).enqueue(object : Callback<List<Item>> { doCallTo(R.string.cant_get_read){t, id, f -> api.readItems(t, id, f)}
override fun onResponse(call: Call<List<Item>>, response: Response<List<Item>>) {
handleItemsResponse(response)
}
override fun onFailure(call: Call<List<Item>>, t: Throwable) {
Toast.makeText(this@HomeActivity, R.string.cant_get_read, Toast.LENGTH_SHORT).show()
mSwipeRefreshLayout!!.isRefreshing = false
}
})
} }
private fun getStarred() { private fun getStarred() {
elementsShown = FAV_SHOWN elementsShown = FAV_SHOWN
api!!.starredItems(maybeTagFilter?.tag, maybeSourceFilter?.id?.toLong(), maybeSearchFilter).enqueue(object : Callback<List<Item>> { doCallTo(R.string.cant_get_favs){t, id, f -> api.starredItems(t, id, f)}
override fun onResponse(call: Call<List<Item>>, response: Response<List<Item>>) {
handleItemsResponse(response)
}
override fun onFailure(call: Call<List<Item>>, t: Throwable) {
Toast.makeText(this@HomeActivity, R.string.cant_get_favs, Toast.LENGTH_SHORT).show()
mSwipeRefreshLayout!!.isRefreshing = false
}
})
} }
private fun handleListResult() { private fun handleListResult() {
@ -533,157 +555,58 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
val mAdapter: RecyclerView.Adapter<*> val mAdapter: RecyclerView.Adapter<*>
if (shouldBeCardView) { if (shouldBeCardView) {
mAdapter = ItemCardAdapter(this, items, api!!, mCustomTabActivityHelper!!, internalBrowser, articleViewer, fullHeightCards) mAdapter =
ItemCardAdapter(
this,
items,
api,
mCustomTabActivityHelper,
internalBrowser,
articleViewer,
fullHeightCards)
} else { } else {
mAdapter = ItemListAdapter(this, items, api!!, mCustomTabActivityHelper!!, clickBehavior, internalBrowser, articleViewer) mAdapter =
ItemListAdapter(
this,
items,
api,
mCustomTabActivityHelper,
clickBehavior,
internalBrowser,
articleViewer)
} }
mRecyclerView!!.adapter = mAdapter mRecyclerView.adapter = mAdapter
mAdapter.notifyDataSetChanged() mAdapter.notifyDataSetChanged()
reloadBadges() reloadBadges()
} }
override fun onStart() { private fun reloadBadges() {
super.onStart()
mCustomTabActivityHelper!!.bindCustomTabsService(this)
}
override fun onStop() {
super.onStop()
mCustomTabActivityHelper!!.unbindCustomTabsService(this)
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
val inflater = menuInflater
inflater.inflate(R.menu.home_menu, menu)
val searchItem = menu.findItem(R.id.action_search)
val searchView = MenuItemCompat.getActionView(searchItem) as SearchView
searchView.setOnQueryTextListener(this)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.refresh -> {
api!!.update().enqueue(object : Callback<String> {
override fun onResponse(call: Call<String>, response: Response<String>) {
Toast.makeText(this@HomeActivity,
R.string.refresh_success_response, Toast.LENGTH_LONG)
.show()
}
override fun onFailure(call: Call<String>, t: Throwable) {
Toast.makeText(this@HomeActivity, R.string.refresh_failer_message, Toast.LENGTH_SHORT).show()
}
})
Toast.makeText(this, R.string.refresh_in_progress, Toast.LENGTH_SHORT).show()
return true
}
R.id.readAll -> {
if (elementsShown == UNREAD_SHOWN) {
mSwipeRefreshLayout!!.isRefreshing = false
val ids = items.map { it.id }
api!!.readAll(ids).enqueue(object : Callback<SuccessResponse> {
override fun onResponse(call: Call<SuccessResponse>, response: Response<SuccessResponse>) {
if (response.body() != null && response.body()!!.isSuccess) {
Toast.makeText(this@HomeActivity, R.string.all_posts_read, Toast.LENGTH_SHORT).show()
} else {
Toast.makeText(this@HomeActivity, R.string.all_posts_not_read, Toast.LENGTH_SHORT).show()
}
mSwipeRefreshLayout!!.isRefreshing = false
}
override fun onFailure(call: Call<SuccessResponse>, t: Throwable) {
Toast.makeText(this@HomeActivity, R.string.all_posts_not_read, Toast.LENGTH_SHORT).show()
mSwipeRefreshLayout!!.isRefreshing = false
}
})
items = ArrayList()
if (items.isEmpty()) Toast.makeText(this@HomeActivity, R.string.nothing_here, Toast.LENGTH_SHORT).show()
handleListResult()
}
return true
}
R.id.action_disconnect -> {
editor!!.remove("url")
editor!!.remove("login")
editor!!.remove("password")
editor!!.apply()
val intent = Intent(this, LoginActivity::class.java)
startActivity(intent)
finish()
return true
}
R.id.action_share_the_app -> {
if (GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(this) == ConnectionResult.SUCCESS) {
val share = AppInviteInvitation.IntentBuilder(getString(R.string.invitation_title))
.setMessage(getString(R.string.invitation_message))
.setDeepLink(Uri.parse("https://ymbh5.app.goo.gl/qbvQ"))
.setCallToActionText(getString(R.string.invitation_cta))
.build()
startActivityForResult(share, REQUEST_INVITE)
} else {
val sendIntent = Intent()
sendIntent.action = Intent.ACTION_SEND
sendIntent.putExtra(Intent.EXTRA_TEXT, getString(R.string.invitation_message) + " https://ymbh5.app.goo.gl/qbvQ")
sendIntent.type = "text/plain"
startActivityForResult(sendIntent, REQUEST_INVITE_BYMAIL)
}
return super.onOptionsItemSelected(item)
}
else -> return super.onOptionsItemSelected(item)
}
}
fun reloadBadges() {
if (displayUnreadCount || displayAllCount) { if (displayUnreadCount || displayAllCount) {
api!!.stats.enqueue(object : Callback<Stats> { api.stats.enqueue(object : Callback<Stats> {
override fun onResponse(call: Call<Stats>, response: Response<Stats>) { override fun onResponse(call: Call<Stats>, response: Response<Stats>) {
if (response.body() != null) { if (response.body() != null) {
tabNew!!.setBadgeCount(response.body()!!.unread) tabNew.setBadgeCount(response.body()!!.unread)
if (displayAllCount) { if (displayAllCount) {
tabArchive!!.setBadgeCount(response.body()!!.total) tabArchive.setBadgeCount(response.body()!!.total)
tabStarred!!.setBadgeCount(response.body()!!.starred) tabStarred.setBadgeCount(response.body()!!.starred)
} else { } else {
tabArchive!!.removeBadge() tabArchive.removeBadge()
tabStarred!!.removeBadge() tabStarred.removeBadge()
} }
} }
} }
override fun onFailure(call: Call<Stats>, t: Throwable) { override fun onFailure(call: Call<Stats>, t: Throwable) {}
}
}) })
} else { } else {
tabNew!!.removeBadge() tabNew.removeBadge()
tabArchive!!.removeBadge() tabArchive.removeBadge()
tabStarred!!.removeBadge() tabStarred.removeBadge()
} }
} }
override fun onActivityResult(req: Int, result: Int, data: Intent?) { private fun calculateNoOfColumns(): Int {
when (req) {
MENU_PREFERENCES -> {
drawer!!.closeDrawer()
recreate()
}
REQUEST_INVITE -> if (result == Activity.RESULT_OK) {
Answers.getInstance().logInvite(InviteEvent())
}
REQUEST_INVITE_BYMAIL -> {
Answers.getInstance().logInvite(InviteEvent())
super.onActivityResult(req, result, data)
}
else -> super.onActivityResult(req, result, data)
}
}
fun calculateNoOfColumns(): Int {
val displayMetrics = resources.displayMetrics val displayMetrics = resources.displayMetrics
val dpWidth = displayMetrics.widthPixels / displayMetrics.density val dpWidth = displayMetrics.widthPixels / displayMetrics.density
return (dpWidth / 300).toInt() return (dpWidth / 300).toInt()
@ -702,4 +625,111 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
getElementsAccordingToTab() getElementsAccordingToTab()
return false return false
} }
override fun onActivityResult(req: Int, result: Int, data: Intent?) {
when (req) {
MENU_PREFERENCES -> {
drawer.closeDrawer()
recreate()
}
REQUEST_INVITE -> if (result == Activity.RESULT_OK) {
Answers.getInstance().logInvite(InviteEvent())
}
REQUEST_INVITE_BYMAIL -> {
Answers.getInstance().logInvite(InviteEvent())
super.onActivityResult(req, result, data)
}
else -> super.onActivityResult(req, result, data)
}
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
val inflater = menuInflater
inflater.inflate(R.menu.home_menu, menu)
val searchItem = menu.findItem(R.id.action_search)
val searchView = MenuItemCompat.getActionView(searchItem) as SearchView
searchView.setOnQueryTextListener(this)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.refresh -> {
api.update().enqueue(object : Callback<String> {
override fun onResponse(call: Call<String>, response: Response<String>) {
Toast.makeText(this@HomeActivity,
R.string.refresh_success_response, Toast.LENGTH_LONG)
.show()
}
override fun onFailure(call: Call<String>, t: Throwable) {
Toast.makeText(this@HomeActivity, R.string.refresh_failer_message, Toast.LENGTH_SHORT).show()
}
})
Toast.makeText(this, R.string.refresh_in_progress, Toast.LENGTH_SHORT).show()
return true
}
R.id.readAll -> {
if (elementsShown == UNREAD_SHOWN) {
mSwipeRefreshLayout.isRefreshing = false
val ids = items.map { it.id }
api.readAll(ids).enqueue(object : Callback<SuccessResponse> {
override fun onResponse(call: Call<SuccessResponse>, response: Response<SuccessResponse>) {
if (response.body() != null && response.body()!!.isSuccess)
Toast.makeText(this@HomeActivity, R.string.all_posts_read, Toast.LENGTH_SHORT).show()
else
Toast.makeText(this@HomeActivity, R.string.all_posts_not_read, Toast.LENGTH_SHORT).show()
mSwipeRefreshLayout.isRefreshing = false
}
override fun onFailure(call: Call<SuccessResponse>, t: Throwable) {
Toast.makeText(this@HomeActivity, R.string.all_posts_not_read, Toast.LENGTH_SHORT).show()
mSwipeRefreshLayout.isRefreshing = false
}
})
items = ArrayList()
if (items.isEmpty())
Toast.makeText(this@HomeActivity, R.string.nothing_here, Toast.LENGTH_SHORT).show()
handleListResult()
}
return true
}
R.id.action_disconnect -> {
editor.remove("url")
editor.remove("login")
editor.remove("password")
editor.apply()
val intent = Intent(this, LoginActivity::class.java)
startActivity(intent)
finish()
return true
}
R.id.action_share_the_app -> {
if (GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(this) == ConnectionResult.SUCCESS) {
val share = AppInviteInvitation.IntentBuilder(getString(R.string.invitation_title))
.setMessage(getString(R.string.invitation_message))
.setDeepLink(Uri.parse("https://ymbh5.app.goo.gl/qbvQ"))
.setCallToActionText(getString(R.string.invitation_cta))
.build()
startActivityForResult(share, REQUEST_INVITE)
} else {
val sendIntent = Intent()
sendIntent.action = Intent.ACTION_SEND
sendIntent.putExtra(
Intent.EXTRA_TEXT,
getString(R.string.invitation_message) + " https://ymbh5.app.goo.gl/qbvQ"
)
sendIntent.type = "text/plain"
startActivityForResult(sendIntent, REQUEST_INVITE_BYMAIL)
}
return super.onOptionsItemSelected(item)
}
else -> return super.onOptionsItemSelected(item)
}
}
} }

View File

@ -1,14 +1,16 @@
package apps.amine.bou.readerforselfoss package apps.amine.bou.readerforselfoss
import agency.tango.materialintroscreen.MaterialIntroActivity
import agency.tango.materialintroscreen.MessageButtonBehaviour
import agency.tango.materialintroscreen.SlideFragmentBuilder
import android.content.Intent 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.view.View import android.view.View
import agency.tango.materialintroscreen.MaterialIntroActivity
import agency.tango.materialintroscreen.MessageButtonBehaviour
import agency.tango.materialintroscreen.SlideFragmentBuilder
class IntroActivity : MaterialIntroActivity() { class IntroActivity : MaterialIntroActivity() {
@ -16,32 +18,32 @@ class IntroActivity : MaterialIntroActivity() {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
addSlide(SlideFragmentBuilder() addSlide(SlideFragmentBuilder()
.backgroundColor(R.color.colorPrimary) .backgroundColor(R.color.colorPrimary)
.buttonsColor(R.color.colorAccent) .buttonsColor(R.color.colorAccent)
.image(R.mipmap.ic_launcher) .image(R.mipmap.ic_launcher)
.title(getString(R.string.intro_hello_title)) .title(getString(R.string.intro_hello_title))
.description(getString(R.string.intro_hello_message)) .description(getString(R.string.intro_hello_message))
.build()) .build())
addSlide(SlideFragmentBuilder() addSlide(SlideFragmentBuilder()
.backgroundColor(R.color.colorAccent) .backgroundColor(R.color.colorAccent)
.buttonsColor(R.color.colorPrimary) .buttonsColor(R.color.colorPrimary)
.image(R.drawable.ic_info_outline_white_48dp) .image(R.drawable.ic_info_outline_white_48dp)
.title(getString(R.string.intro_needs_selfoss_title)) .title(getString(R.string.intro_needs_selfoss_title))
.description(getString(R.string.intro_needs_selfoss_message)) .description(getString(R.string.intro_needs_selfoss_message))
.build(), .build(),
MessageButtonBehaviour(View.OnClickListener { MessageButtonBehaviour(View.OnClickListener {
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse("https://selfoss.aditu.de")) val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse("https://selfoss.aditu.de"))
startActivity(browserIntent) startActivity(browserIntent)
}, getString(R.string.intro_needs_selfoss_link))) }, getString(R.string.intro_needs_selfoss_link)))
addSlide(SlideFragmentBuilder() addSlide(SlideFragmentBuilder()
.backgroundColor(R.color.colorPrimaryDark) .backgroundColor(R.color.colorPrimaryDark)
.buttonsColor(R.color.colorAccentDark) .buttonsColor(R.color.colorAccentDark)
.image(R.drawable.ic_thumb_up_white_48dp) .image(R.drawable.ic_thumb_up_white_48dp)
.title(getString(R.string.intro_all_set_title)) .title(getString(R.string.intro_all_set_title))
.description(getString(R.string.intro_all_set_message)) .description(getString(R.string.intro_all_set_message))
.build()) .build())
} }
override fun onFinish() { override fun onFinish() {

View File

@ -18,11 +18,7 @@ import android.widget.Button
import android.widget.EditText import android.widget.EditText
import android.widget.Switch import android.widget.Switch
import android.widget.TextView import android.widget.TextView
import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi
import apps.amine.bou.readerforselfoss.api.selfoss.SuccessResponse
import apps.amine.bou.readerforselfoss.utils.Config
import apps.amine.bou.readerforselfoss.utils.checkAndDisplayStoreApk
import apps.amine.bou.readerforselfoss.utils.isUrlValid
import com.google.firebase.analytics.FirebaseAnalytics import com.google.firebase.analytics.FirebaseAnalytics
import com.mikepenz.aboutlibraries.Libs import com.mikepenz.aboutlibraries.Libs
import com.mikepenz.aboutlibraries.LibsBuilder import com.mikepenz.aboutlibraries.LibsBuilder
@ -30,21 +26,29 @@ import retrofit2.Call
import retrofit2.Callback import retrofit2.Callback
import retrofit2.Response import retrofit2.Response
import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi
import apps.amine.bou.readerforselfoss.api.selfoss.SuccessResponse
import apps.amine.bou.readerforselfoss.utils.Config
import apps.amine.bou.readerforselfoss.utils.checkAndDisplayStoreApk
import apps.amine.bou.readerforselfoss.utils.isUrlValid
class LoginActivity : AppCompatActivity() { class LoginActivity : AppCompatActivity() {
private var settings: SharedPreferences? = null
private var mProgressView: View? = null
private var mUrlView: EditText? = null
private var mLoginView: TextView? = null
private var mHTTPLoginView: TextView? = null
private var mPasswordView: EditText? = null
private var mHTTPPasswordView: EditText? = null
private var inValidCount: Int = 0 private var inValidCount: Int = 0
private var isWithLogin = false private var isWithLogin = false
private var isWithHTTPLogin = false private var isWithHTTPLogin = false
private var mLoginFormView: View? = null
private var mFirebaseAnalytics: FirebaseAnalytics? = null private lateinit var settings: SharedPreferences
private lateinit var mFirebaseAnalytics: FirebaseAnalytics
private lateinit var mUrlView: EditText
private lateinit var mLoginView: TextView
private lateinit var mHTTPLoginView: TextView
private lateinit var mProgressView: View
private lateinit var mPasswordView: EditText
private lateinit var mHTTPPasswordView: EditText
private lateinit var mLoginFormView: View
@ -53,16 +57,12 @@ class LoginActivity : AppCompatActivity() {
setContentView(R.layout.activity_login) setContentView(R.layout.activity_login)
settings = getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE) settings = getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE)
if (settings!!.getString("url", "").isNotEmpty()) { if (settings.getString("url", "").isNotEmpty()) {
goToMain() goToMain()
} else { } else {
checkAndDisplayStoreApk(this@LoginActivity) checkAndDisplayStoreApk(this@LoginActivity)
} }
isWithLogin = false
isWithHTTPLogin = false
inValidCount = 0
mFirebaseAnalytics = FirebaseAnalytics.getInstance(this) mFirebaseAnalytics = FirebaseAnalytics.getInstance(this)
mUrlView = findViewById(R.id.url) as EditText mUrlView = findViewById(R.id.url) as EditText
mLoginView = findViewById(R.id.login) as TextView mLoginView = findViewById(R.id.login) as TextView
@ -80,7 +80,7 @@ class LoginActivity : AppCompatActivity() {
val mHTTPPasswordLayout = findViewById(R.id.httpPasswordInput) as TextInputLayout val mHTTPPasswordLayout = findViewById(R.id.httpPasswordInput) as TextInputLayout
val mEmailSignInButton = findViewById(R.id.email_sign_in_button) as Button val mEmailSignInButton = findViewById(R.id.email_sign_in_button) as Button
mPasswordView!!.setOnEditorActionListener(TextView.OnEditorActionListener { _, id, _ -> mPasswordView.setOnEditorActionListener(TextView.OnEditorActionListener { _, id, _ ->
if (id == R.id.login || id == EditorInfo.IME_NULL) { if (id == R.id.login || id == EditorInfo.IME_NULL) {
attemptLogin() attemptLogin()
return@OnEditorActionListener true return@OnEditorActionListener true
@ -92,26 +92,16 @@ class LoginActivity : AppCompatActivity() {
mSwitch.setOnCheckedChangeListener { _, b -> mSwitch.setOnCheckedChangeListener { _, b ->
isWithLogin = !isWithLogin isWithLogin = !isWithLogin
val visi: Int val visi: Int = if (b) View.VISIBLE else View.GONE
if (b) {
visi = View.VISIBLE
} else {
visi = View.GONE
}
mLoginLayout.visibility = visi mLoginLayout.visibility = visi
mPasswordLayout.visibility = visi mPasswordLayout.visibility = visi
} }
mHTTPSwitch.setOnCheckedChangeListener { _, b -> mHTTPSwitch.setOnCheckedChangeListener { _, b ->
isWithHTTPLogin = !isWithHTTPLogin isWithHTTPLogin = !isWithHTTPLogin
val visi: Int val visi: Int = if (b) View.VISIBLE else View.GONE
if (b) {
visi = View.VISIBLE
} else {
visi = View.GONE
}
mHTTPLoginLayout.visibility = visi mHTTPLoginLayout.visibility = visi
mHTTPPasswordLayout.visibility = visi mHTTPPasswordLayout.visibility = visi
} }
@ -126,24 +116,24 @@ class LoginActivity : AppCompatActivity() {
private fun attemptLogin() { private fun attemptLogin() {
// Reset errors. // Reset errors.
mUrlView!!.error = null mUrlView.error = null
mLoginView!!.error = null mLoginView.error = null
mHTTPLoginView!!.error = null mHTTPLoginView.error = null
mPasswordView!!.error = null mPasswordView.error = null
mHTTPPasswordView!!.error = null mHTTPPasswordView.error = null
// Store values at the time of the login attempt. // Store values at the time of the login attempt.
val url = mUrlView!!.text.toString() val url = mUrlView.text.toString()
val login = mLoginView!!.text.toString() val login = mLoginView.text.toString()
val httpLogin = mHTTPLoginView!!.text.toString() val httpLogin = mHTTPLoginView.text.toString()
val password = mPasswordView!!.text.toString() val password = mPasswordView.text.toString()
val httpPassword = mHTTPPasswordView!!.text.toString() val httpPassword = mHTTPPasswordView.text.toString()
var cancel = false var cancel = false
var focusView: View? = null var focusView: View? = null
if (!isUrlValid(url)) { if (!isUrlValid(url)) {
mUrlView!!.error = getString(R.string.login_url_problem) mUrlView.error = getString(R.string.login_url_problem)
focusView = mUrlView focusView = mUrlView
cancel = true cancel = true
inValidCount++ inValidCount++
@ -151,8 +141,10 @@ class LoginActivity : AppCompatActivity() {
val alertDialog = AlertDialog.Builder(this).create() val alertDialog = AlertDialog.Builder(this).create()
alertDialog.setTitle(getString(R.string.warning_wrong_url)) alertDialog.setTitle(getString(R.string.warning_wrong_url))
alertDialog.setMessage(getString(R.string.text_wrong_url)) alertDialog.setMessage(getString(R.string.text_wrong_url))
alertDialog.setButton(AlertDialog.BUTTON_NEUTRAL, "OK", alertDialog.setButton(
{ dialog, _ -> dialog.dismiss() }) AlertDialog.BUTTON_NEUTRAL,
"OK",
{ dialog, _ -> dialog.dismiss() })
alertDialog.show() alertDialog.show()
inValidCount = 0 inValidCount = 0
} }
@ -160,24 +152,24 @@ class LoginActivity : AppCompatActivity() {
if (isWithLogin || isWithHTTPLogin) { if (isWithLogin || isWithHTTPLogin) {
if (TextUtils.isEmpty(password)) { if (TextUtils.isEmpty(password)) {
mPasswordView!!.error = getString(R.string.error_invalid_password) mPasswordView.error = getString(R.string.error_invalid_password)
focusView = mPasswordView focusView = mPasswordView
cancel = true cancel = true
} }
if (TextUtils.isEmpty(login)) { if (TextUtils.isEmpty(login)) {
mLoginView!!.error = getString(R.string.error_field_required) mLoginView.error = getString(R.string.error_field_required)
focusView = mLoginView focusView = mLoginView
cancel = true cancel = true
} }
} }
if (cancel) { if (cancel) {
focusView!!.requestFocus() focusView?.requestFocus()
} else { } else {
showProgress(true) showProgress(true)
val editor = settings!!.edit() val editor = settings.edit()
editor.putString("url", url) editor.putString("url", url)
editor.putString("login", login) editor.putString("login", login)
editor.putString("httpUserName", httpLogin) editor.putString("httpUserName", httpLogin)
@ -194,17 +186,17 @@ class LoginActivity : AppCompatActivity() {
editor.remove("password") editor.remove("password")
editor.remove("httpPassword") editor.remove("httpPassword")
editor.apply() editor.apply()
mUrlView!!.error = getString(R.string.wrong_infos) mUrlView.error = getString(R.string.wrong_infos)
mLoginView!!.error = getString(R.string.wrong_infos) mLoginView.error = getString(R.string.wrong_infos)
mPasswordView!!.error = getString(R.string.wrong_infos) mPasswordView.error = getString(R.string.wrong_infos)
mHTTPLoginView!!.error = getString(R.string.wrong_infos) mHTTPLoginView.error = getString(R.string.wrong_infos)
mHTTPPasswordView!!.error = getString(R.string.wrong_infos) mHTTPPasswordView.error = getString(R.string.wrong_infos)
showProgress(false) showProgress(false)
} }
override fun onResponse(call: Call<SuccessResponse>, response: Response<SuccessResponse>) { override fun onResponse(call: Call<SuccessResponse>, response: Response<SuccessResponse>) {
if (response.body() != null && response.body()!!.isSuccess) { if (response.body() != null && response.body()!!.isSuccess) {
mFirebaseAnalytics!!.logEvent(FirebaseAnalytics.Event.LOGIN, Bundle()) mFirebaseAnalytics.logEvent(FirebaseAnalytics.Event.LOGIN, Bundle())
goToMain() goToMain()
} else { } else {
preferenceError() preferenceError()
@ -224,26 +216,33 @@ class LoginActivity : AppCompatActivity() {
private fun showProgress(show: Boolean) { private fun showProgress(show: Boolean) {
val shortAnimTime = resources.getInteger(android.R.integer.config_shortAnimTime) val shortAnimTime = resources.getInteger(android.R.integer.config_shortAnimTime)
mLoginFormView!!.visibility = if (show) View.GONE else View.VISIBLE mLoginFormView.visibility = if (show) View.GONE else View.VISIBLE
mLoginFormView!!.animate().setDuration(shortAnimTime.toLong()).alpha( mLoginFormView
if (show) 0F else 1F).setListener(object : AnimatorListenerAdapter() { .animate()
override fun onAnimationEnd(animation: Animator) { .setDuration(shortAnimTime.toLong())
mLoginFormView!!.visibility = if (show) View.GONE else View.VISIBLE .alpha(
} if (show) 0F else 1F
}) ).setListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
mLoginFormView.visibility = if (show) View.GONE else View.VISIBLE
}
})
mProgressView!!.visibility = if (show) View.VISIBLE else View.GONE mProgressView.visibility = if (show) View.VISIBLE else View.GONE
mProgressView!!.animate().setDuration(shortAnimTime.toLong()).alpha( mProgressView
if (show) 1F else 0F).setListener(object : AnimatorListenerAdapter() { .animate()
override fun onAnimationEnd(animation: Animator) { .setDuration(shortAnimTime.toLong())
mProgressView!!.visibility = if (show) View.VISIBLE else View.GONE .alpha(
} if (show) 1F else 0F
}) ).setListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
mProgressView.visibility = if (show) View.VISIBLE else View.GONE
}
})
} }
override fun onCreateOptionsMenu(menu: Menu): Boolean { override fun onCreateOptionsMenu(menu: Menu): Boolean {
val inflater = menuInflater menuInflater.inflate(R.menu.login_menu, menu)
inflater.inflate(R.menu.login_menu, menu)
return true return true
} }
@ -251,10 +250,10 @@ class LoginActivity : AppCompatActivity() {
when (item.itemId) { when (item.itemId) {
R.id.about -> { R.id.about -> {
LibsBuilder() LibsBuilder()
.withActivityStyle(Libs.ActivityStyle.LIGHT_DARK_TOOLBAR) .withActivityStyle(Libs.ActivityStyle.LIGHT_DARK_TOOLBAR)
.withAboutIconShown(true) .withAboutIconShown(true)
.withAboutVersionShown(true) .withAboutVersionShown(true)
.start(this) .start(this)
return true return true
} }
else -> return super.onOptionsItemSelected(item) else -> return super.onOptionsItemSelected(item)

View File

@ -6,6 +6,7 @@ import android.preference.PreferenceManager
import android.support.v7.app.AppCompatActivity import android.support.v7.app.AppCompatActivity
class MainActivity : AppCompatActivity() { class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {

View File

@ -5,14 +5,13 @@ import android.graphics.drawable.Drawable
import android.net.Uri import android.net.Uri
import android.support.multidex.MultiDexApplication import android.support.multidex.MultiDexApplication
import android.widget.ImageView import android.widget.ImageView
import com.crashlytics.android.Crashlytics
import com.github.stkent.amplify.tracking.Amplify
import io.fabric.sdk.android.Fabric
import com.anupcowkur.reservoir.Reservoir import com.anupcowkur.reservoir.Reservoir
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.mikepenz.iconics.IconicsDrawable import com.crashlytics.android.Crashlytics
import com.github.stkent.amplify.tracking.Amplify
import com.mikepenz.materialdrawer.util.AbstractDrawerImageLoader import com.mikepenz.materialdrawer.util.AbstractDrawerImageLoader
import com.mikepenz.materialdrawer.util.DrawerImageLoader import com.mikepenz.materialdrawer.util.DrawerImageLoader
import io.fabric.sdk.android.Fabric
import java.io.IOException import java.io.IOException

View File

@ -9,10 +9,7 @@ import android.view.ViewGroup
import android.widget.ImageButton import android.widget.ImageButton
import android.widget.ImageView import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import apps.amine.bou.readerforselfoss.api.mercury.MercuryApi
import apps.amine.bou.readerforselfoss.api.mercury.ParsedContent
import apps.amine.bou.readerforselfoss.utils.buildCustomTabsIntent
import apps.amine.bou.readerforselfoss.utils.customtabs.CustomTabActivityHelper
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import org.sufficientlysecure.htmltextview.HtmlHttpImageGetter import org.sufficientlysecure.htmltextview.HtmlHttpImageGetter
import org.sufficientlysecure.htmltextview.HtmlTextView import org.sufficientlysecure.htmltextview.HtmlTextView
@ -21,18 +18,24 @@ import retrofit2.Callback
import retrofit2.Response import retrofit2.Response
import xyz.klinker.android.drag_dismiss.activity.DragDismissActivity import xyz.klinker.android.drag_dismiss.activity.DragDismissActivity
import apps.amine.bou.readerforselfoss.api.mercury.MercuryApi
import apps.amine.bou.readerforselfoss.api.mercury.ParsedContent
import apps.amine.bou.readerforselfoss.utils.buildCustomTabsIntent
import apps.amine.bou.readerforselfoss.utils.customtabs.CustomTabActivityHelper
class ReaderActivity : DragDismissActivity() { class ReaderActivity : DragDismissActivity() {
private var mCustomTabActivityHelper: CustomTabActivityHelper? = null private lateinit var mCustomTabActivityHelper: CustomTabActivityHelper
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
mCustomTabActivityHelper!!.bindCustomTabsService(this) mCustomTabActivityHelper.bindCustomTabsService(this)
} }
override fun onStop() { override fun onStop() {
super.onStop() super.onStop()
mCustomTabActivityHelper!!.unbindCustomTabsService(this) mCustomTabActivityHelper.unbindCustomTabsService(this)
} }
override fun onCreateContent(inflater: LayoutInflater, parent: ViewGroup, savedInstanceState: Bundle?): View { override fun onCreateContent(inflater: LayoutInflater, parent: ViewGroup, savedInstanceState: Bundle?): View {
@ -51,7 +54,7 @@ class ReaderActivity : DragDismissActivity() {
val customTabsIntent = buildCustomTabsIntent(this@ReaderActivity) val customTabsIntent = buildCustomTabsIntent(this@ReaderActivity)
mCustomTabActivityHelper = CustomTabActivityHelper() mCustomTabActivityHelper = CustomTabActivityHelper()
mCustomTabActivityHelper!!.bindCustomTabsService(this) mCustomTabActivityHelper.bindCustomTabsService(this)
parser.parseUrl(url).enqueue(object : Callback<ParsedContent> { parser.parseUrl(url).enqueue(object : Callback<ParsedContent> {
@ -62,7 +65,12 @@ class ReaderActivity : DragDismissActivity() {
if (response.body()!!.content != null && !response.body()!!.content.isEmpty()) if (response.body()!!.content != null && !response.body()!!.content.isEmpty())
content.setHtml(response.body()!!.content, HtmlHttpImageGetter(content, null, true)) content.setHtml(response.body()!!.content, HtmlHttpImageGetter(content, null, true))
if (response.body()!!.lead_image_url != null && !response.body()!!.lead_image_url.isEmpty()) if (response.body()!!.lead_image_url != null && !response.body()!!.lead_image_url.isEmpty())
Glide.with(applicationContext).load(response.body()!!.lead_image_url).asBitmap().fitCenter().into(image) Glide
.with(applicationContext)
.load(response.body()!!.lead_image_url)
.asBitmap()
.fitCenter()
.into(image)
shareBtn.setOnClickListener { shareBtn.setOnClickListener {
val sendIntent = Intent() val sendIntent = Intent()
@ -81,14 +89,10 @@ class ReaderActivity : DragDismissActivity() {
} }
hideProgressBar() hideProgressBar()
} else { } else errorAfterMercuryCall()
errorAfterMercuryCall()
}
} }
override fun onFailure(call: Call<ParsedContent>, t: Throwable) { override fun onFailure(call: Call<ParsedContent>, t: Throwable) = errorAfterMercuryCall()
errorAfterMercuryCall()
}
private fun errorAfterMercuryCall() { private fun errorAfterMercuryCall() {
CustomTabActivityHelper.openCustomTab(this@ReaderActivity, customTabsIntent, Uri.parse(url) CustomTabActivityHelper.openCustomTab(this@ReaderActivity, customTabsIntent, Uri.parse(url)

View File

@ -6,14 +6,17 @@ import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.LinearLayoutManager import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView import android.support.v7.widget.RecyclerView
import android.widget.Toast import android.widget.Toast
import apps.amine.bou.readerforselfoss.adapters.SourcesListAdapter
import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi
import apps.amine.bou.readerforselfoss.api.selfoss.Sources
import com.melnykov.fab.FloatingActionButton import com.melnykov.fab.FloatingActionButton
import retrofit2.Call import retrofit2.Call
import retrofit2.Callback import retrofit2.Callback
import retrofit2.Response import retrofit2.Response
import apps.amine.bou.readerforselfoss.adapters.SourcesListAdapter
import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi
import apps.amine.bou.readerforselfoss.api.selfoss.Sources
class SourcesActivity : AppCompatActivity() { class SourcesActivity : AppCompatActivity() {

View File

@ -1,6 +1,5 @@
package apps.amine.bou.readerforselfoss.adapters package apps.amine.bou.readerforselfoss.adapters
import android.app.Activity import android.app.Activity
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
@ -20,13 +19,7 @@ import android.widget.ImageView
import android.widget.ImageView.ScaleType import android.widget.ImageView.ScaleType
import android.widget.TextView import android.widget.TextView
import android.widget.Toast import android.widget.Toast
import apps.amine.bou.readerforselfoss.R
import apps.amine.bou.readerforselfoss.api.selfoss.Item
import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi
import apps.amine.bou.readerforselfoss.api.selfoss.SuccessResponse
import apps.amine.bou.readerforselfoss.utils.buildCustomTabsIntent
import apps.amine.bou.readerforselfoss.utils.customtabs.CustomTabActivityHelper
import apps.amine.bou.readerforselfoss.utils.openItemUrl
import com.amulyakhare.textdrawable.TextDrawable import com.amulyakhare.textdrawable.TextDrawable
import com.amulyakhare.textdrawable.util.ColorGenerator import com.amulyakhare.textdrawable.util.ColorGenerator
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
@ -40,10 +33,21 @@ import java.text.ParseException
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.* import java.util.*
import apps.amine.bou.readerforselfoss.R
import apps.amine.bou.readerforselfoss.api.selfoss.Item
import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi
import apps.amine.bou.readerforselfoss.api.selfoss.SuccessResponse
import apps.amine.bou.readerforselfoss.utils.buildCustomTabsIntent
import apps.amine.bou.readerforselfoss.utils.customtabs.CustomTabActivityHelper
import apps.amine.bou.readerforselfoss.utils.openItemUrl
class ItemCardAdapter(private val app: Activity, private val items: ArrayList<Item>, private val api: SelfossApi, class ItemCardAdapter(private val app: Activity,
private val helper: CustomTabActivityHelper, private val internalBrowser: Boolean, private val items: ArrayList<Item>,
private val articleViewer: Boolean, private val fullHeightCards: Boolean) : RecyclerView.Adapter<ItemCardAdapter.ViewHolder>() { private val api: SelfossApi,
private val helper: CustomTabActivityHelper,
private val internalBrowser: Boolean,
private val articleViewer: Boolean,
private val fullHeightCards: Boolean) : RecyclerView.Adapter<ItemCardAdapter.ViewHolder>() {
private val c: Context = app.applicationContext private val c: Context = app.applicationContext
private val generator: ColorGenerator = ColorGenerator.MATERIAL private val generator: ColorGenerator = ColorGenerator.MATERIAL
@ -56,8 +60,8 @@ class ItemCardAdapter(private val app: Activity, private val items: ArrayList<It
val itm = items[position] val itm = items[position]
holder.saveBtn!!.isLiked = itm.starred holder.saveBtn.isLiked = itm.starred
holder.title!!.text = Html.fromHtml(itm.title) holder.title.text = Html.fromHtml(itm.title)
var sourceAndDate = itm.sourcetitle var sourceAndDate = itm.sourcetitle
val d: Long val d: Long
@ -73,11 +77,11 @@ class ItemCardAdapter(private val app: Activity, private val items: ArrayList<It
e.printStackTrace() e.printStackTrace()
} }
holder.sourceTitleAndDate!!.text = sourceAndDate holder.sourceTitleAndDate.text = sourceAndDate
if (itm.getThumbnail(c).isEmpty()) { if (itm.getThumbnail(c).isEmpty()) {
Glide.clear(holder.itemImage) Glide.clear(holder.itemImage)
holder.itemImage!!.setImageDrawable(null) holder.itemImage.setImageDrawable(null)
} else { } else {
if (fullHeightCards) { if (fullHeightCards) {
Glide.with(c).load(itm.getThumbnail(c)).asBitmap().fitCenter().into(holder.itemImage) Glide.with(c).load(itm.getThumbnail(c)).asBitmap().fitCenter().into(holder.itemImage)
@ -97,19 +101,19 @@ class ItemCardAdapter(private val app: Activity, private val items: ArrayList<It
val builder = TextDrawable.builder().round() val builder = TextDrawable.builder().round()
val drawable = builder.build(textDrawable.toString(), color) val drawable = builder.build(textDrawable.toString(), color)
holder.sourceImage!!.setImageDrawable(drawable) holder.sourceImage.setImageDrawable(drawable)
} else { } else {
Glide.with(c).load(itm.getIcon(c)).asBitmap().centerCrop().into(object : BitmapImageViewTarget(holder.sourceImage) { Glide.with(c).load(itm.getIcon(c)).asBitmap().centerCrop().into(object : BitmapImageViewTarget(holder.sourceImage) {
override fun setResource(resource: Bitmap) { override fun setResource(resource: Bitmap) {
val circularBitmapDrawable = RoundedBitmapDrawableFactory.create(c.resources, resource) val circularBitmapDrawable = RoundedBitmapDrawableFactory.create(c.resources, resource)
circularBitmapDrawable.isCircular = true circularBitmapDrawable.isCircular = true
fHolder.sourceImage!!.setImageDrawable(circularBitmapDrawable) fHolder.sourceImage.setImageDrawable(circularBitmapDrawable)
} }
}) })
} }
holder.saveBtn!!.isLiked = itm.starred holder.saveBtn.isLiked = itm.starred
} }
override fun getItemCount(): Int { override fun getItemCount(): Int {
@ -163,13 +167,13 @@ class ItemCardAdapter(private val app: Activity, private val items: ArrayList<It
} }
inner class ViewHolder(val mView: ConstraintLayout) : RecyclerView.ViewHolder(mView) { inner class ViewHolder(val mView: ConstraintLayout) : RecyclerView.ViewHolder(mView) {
var saveBtn: LikeButton? = null lateinit var saveBtn: LikeButton
var browserBtn: ImageButton? = null lateinit var browserBtn: ImageButton
var shareBtn: ImageButton? = null lateinit var shareBtn: ImageButton
var itemImage: ImageView? = null lateinit var itemImage: ImageView
var sourceImage: ImageView? = null lateinit var sourceImage: ImageView
var title: TextView? = null lateinit var title: TextView
var sourceTitleAndDate: TextView? = null lateinit var sourceTitleAndDate: TextView
init { init {
handleClickListeners() handleClickListeners()
@ -186,18 +190,18 @@ class ItemCardAdapter(private val app: Activity, private val items: ArrayList<It
browserBtn = mView.findViewById(R.id.browserBtn) as ImageButton browserBtn = mView.findViewById(R.id.browserBtn) as ImageButton
if (!fullHeightCards) { if (!fullHeightCards) {
itemImage!!.maxHeight = c.resources.getDimension(R.dimen.card_image_max_height).toInt() itemImage.maxHeight = c.resources.getDimension(R.dimen.card_image_max_height).toInt()
itemImage!!.scaleType = ScaleType.CENTER_CROP itemImage.scaleType = ScaleType.CENTER_CROP
} }
saveBtn!!.setOnLikeListener(object : OnLikeListener { saveBtn.setOnLikeListener(object : OnLikeListener {
override fun liked(likeButton: LikeButton) { override fun liked(likeButton: LikeButton) {
val (id) = items[adapterPosition] val (id) = items[adapterPosition]
api.starrItem(id).enqueue(object : Callback<SuccessResponse> { api.starrItem(id).enqueue(object : Callback<SuccessResponse> {
override fun onResponse(call: Call<SuccessResponse>, response: Response<SuccessResponse>) {} override fun onResponse(call: Call<SuccessResponse>, response: Response<SuccessResponse>) {}
override fun onFailure(call: Call<SuccessResponse>, t: Throwable) { override fun onFailure(call: Call<SuccessResponse>, t: Throwable) {
saveBtn!!.isLiked = false saveBtn.isLiked = false
Toast.makeText(c, R.string.cant_mark_favortie, Toast.LENGTH_SHORT).show() Toast.makeText(c, R.string.cant_mark_favortie, Toast.LENGTH_SHORT).show()
} }
}) })
@ -209,14 +213,14 @@ class ItemCardAdapter(private val app: Activity, private val items: ArrayList<It
override fun onResponse(call: Call<SuccessResponse>, response: Response<SuccessResponse>) {} override fun onResponse(call: Call<SuccessResponse>, response: Response<SuccessResponse>) {}
override fun onFailure(call: Call<SuccessResponse>, t: Throwable) { override fun onFailure(call: Call<SuccessResponse>, t: Throwable) {
saveBtn!!.isLiked = true saveBtn.isLiked = true
Toast.makeText(c, R.string.cant_unmark_favortie, Toast.LENGTH_SHORT).show() Toast.makeText(c, R.string.cant_unmark_favortie, Toast.LENGTH_SHORT).show()
} }
}) })
} }
}) })
shareBtn!!.setOnClickListener { shareBtn.setOnClickListener {
val i = items[adapterPosition] val i = items[adapterPosition]
val sendIntent = Intent() val sendIntent = Intent()
sendIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK sendIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
@ -226,7 +230,7 @@ class ItemCardAdapter(private val app: Activity, private val items: ArrayList<It
c.startActivity(Intent.createChooser(sendIntent, c.getString(R.string.share)).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)) c.startActivity(Intent.createChooser(sendIntent, c.getString(R.string.share)).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK))
} }
browserBtn!!.setOnClickListener { browserBtn.setOnClickListener {
val i = items[adapterPosition] val i = items[adapterPosition]
val intent = Intent(Intent.ACTION_VIEW) val intent = Intent(Intent.ACTION_VIEW)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
@ -241,11 +245,11 @@ class ItemCardAdapter(private val app: Activity, private val items: ArrayList<It
mView.setOnClickListener { mView.setOnClickListener {
openItemUrl(items[adapterPosition], openItemUrl(items[adapterPosition],
customTabsIntent, customTabsIntent,
internalBrowser, internalBrowser,
articleViewer, articleViewer,
app, app,
c) c)
} }
} }
} }

View File

@ -18,13 +18,7 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.* import android.widget.*
import apps.amine.bou.readerforselfoss.R
import apps.amine.bou.readerforselfoss.api.selfoss.Item
import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi
import apps.amine.bou.readerforselfoss.api.selfoss.SuccessResponse
import apps.amine.bou.readerforselfoss.utils.buildCustomTabsIntent
import apps.amine.bou.readerforselfoss.utils.customtabs.CustomTabActivityHelper
import apps.amine.bou.readerforselfoss.utils.openItemUrl
import com.amulyakhare.textdrawable.TextDrawable import com.amulyakhare.textdrawable.TextDrawable
import com.amulyakhare.textdrawable.util.ColorGenerator import com.amulyakhare.textdrawable.util.ColorGenerator
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
@ -38,10 +32,23 @@ import java.text.ParseException
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.* import java.util.*
import apps.amine.bou.readerforselfoss.R
import apps.amine.bou.readerforselfoss.api.selfoss.Item
import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi
import apps.amine.bou.readerforselfoss.api.selfoss.SuccessResponse
import apps.amine.bou.readerforselfoss.utils.buildCustomTabsIntent
import apps.amine.bou.readerforselfoss.utils.customtabs.CustomTabActivityHelper
import apps.amine.bou.readerforselfoss.utils.openItemUrl
class ItemListAdapter(private val app: Activity, private val items: ArrayList<Item>, private val api: SelfossApi,
private val helper: CustomTabActivityHelper, private val clickBehavior: Boolean,
private val internalBrowser: Boolean, private val articleViewer: Boolean) : RecyclerView.Adapter<ItemListAdapter.ViewHolder>() { class ItemListAdapter(private val app: Activity,
private val items: ArrayList<Item>,
private val api: SelfossApi,
private val helper: CustomTabActivityHelper,
private val clickBehavior: Boolean,
private val internalBrowser: Boolean,
private val articleViewer: Boolean) : RecyclerView.Adapter<ItemListAdapter.ViewHolder>() {
private val generator: ColorGenerator = ColorGenerator.MATERIAL private val generator: ColorGenerator = ColorGenerator.MATERIAL
private val c: Context = app.applicationContext private val c: Context = app.applicationContext
private val bars: ArrayList<Boolean> = ArrayList(Collections.nCopies(items.size + 1, false)) private val bars: ArrayList<Boolean> = ArrayList(Collections.nCopies(items.size + 1, false))
@ -55,41 +62,41 @@ class ItemListAdapter(private val app: Activity, private val items: ArrayList<It
val itm = items[position] val itm = items[position]
holder.saveBtn!!.isLiked = itm.starred holder.saveBtn.isLiked = itm.starred
holder.title!!.text = Html.fromHtml(itm.title) holder.title.text = Html.fromHtml(itm.title)
var sourceAndDate = itm.sourcetitle var sourceAndDate = itm.sourcetitle
val d: Long val d: Long
try { try {
d = SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(itm.datetime).time d = SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(itm.datetime).time
sourceAndDate += " " + DateUtils.getRelativeTimeSpanString( sourceAndDate += " " + DateUtils.getRelativeTimeSpanString(
d, d,
Date().time, Date().time,
DateUtils.MINUTE_IN_MILLIS, DateUtils.MINUTE_IN_MILLIS,
DateUtils.FORMAT_ABBREV_RELATIVE DateUtils.FORMAT_ABBREV_RELATIVE
) )
} catch (e: ParseException) { } catch (e: ParseException) {
e.printStackTrace() e.printStackTrace()
} }
holder.sourceTitleAndDate!!.text = sourceAndDate holder.sourceTitleAndDate.text = sourceAndDate
if (itm.getThumbnail(c).isEmpty()) { if (itm.getThumbnail(c).isEmpty()) {
val sizeInInt = 46 val sizeInInt = 46
val sizeInDp = TypedValue.applyDimension( val sizeInDp = TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, sizeInInt.toFloat(), c.resources TypedValue.COMPLEX_UNIT_DIP, sizeInInt.toFloat(), c.resources
.displayMetrics).toInt() .displayMetrics).toInt()
val marginInInt = 16 val marginInInt = 16
val marginInDp = TypedValue.applyDimension( val marginInDp = TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, marginInInt.toFloat(), c.resources TypedValue.COMPLEX_UNIT_DIP, marginInInt.toFloat(), c.resources
.displayMetrics).toInt() .displayMetrics).toInt()
val params = holder.sourceImage!!.layoutParams as ViewGroup.MarginLayoutParams val params = holder.sourceImage.layoutParams as ViewGroup.MarginLayoutParams
params.height = sizeInDp params.height = sizeInDp
params.width = sizeInDp params.width = sizeInDp
params.setMargins(marginInDp, 0, 0, 0) params.setMargins(marginInDp, 0, 0, 0)
holder.sourceImage!!.layoutParams = params holder.sourceImage.layoutParams = params
if (itm.getIcon(c).isEmpty()) { if (itm.getIcon(c).isEmpty()) {
val color = generator.getColor(itm.sourcetitle) val color = generator.getColor(itm.sourcetitle)
@ -101,7 +108,7 @@ class ItemListAdapter(private val app: Activity, private val items: ArrayList<It
val builder = TextDrawable.builder().round() val builder = TextDrawable.builder().round()
val drawable = builder.build(textDrawable.toString(), color) val drawable = builder.build(textDrawable.toString(), color)
holder.sourceImage!!.setImageDrawable(drawable) holder.sourceImage.setImageDrawable(drawable)
} else { } else {
val fHolder = holder val fHolder = holder
@ -109,7 +116,7 @@ class ItemListAdapter(private val app: Activity, private val items: ArrayList<It
override fun setResource(resource: Bitmap) { override fun setResource(resource: Bitmap) {
val circularBitmapDrawable = RoundedBitmapDrawableFactory.create(c.resources, resource) val circularBitmapDrawable = RoundedBitmapDrawableFactory.create(c.resources, resource)
circularBitmapDrawable.isCircular = true circularBitmapDrawable.isCircular = true
fHolder.sourceImage!!.setImageDrawable(circularBitmapDrawable) fHolder.sourceImage.setImageDrawable(circularBitmapDrawable)
} }
}) })
} }
@ -117,18 +124,12 @@ class ItemListAdapter(private val app: Activity, private val items: ArrayList<It
Glide.with(c).load(itm.getThumbnail(c)).asBitmap().centerCrop().into(holder.sourceImage) Glide.with(c).load(itm.getThumbnail(c)).asBitmap().centerCrop().into(holder.sourceImage)
} }
if (bars[position]) { if (bars[position]) holder.actionBar.visibility = View.VISIBLE else holder.actionBar.visibility = View.GONE
holder.actionBar!!.visibility = View.VISIBLE
} else {
holder.actionBar!!.visibility = View.GONE
}
holder.saveBtn!!.isLiked = itm.starred holder.saveBtn.isLiked = itm.starred
} }
override fun getItemCount(): Int { override fun getItemCount(): Int = items.size
return items.size
}
private fun doUnmark(i: Item, position: Int) { private fun doUnmark(i: Item, position: Int) {
@ -178,13 +179,13 @@ class ItemListAdapter(private val app: Activity, private val items: ArrayList<It
} }
inner class ViewHolder(val mView: ConstraintLayout) : RecyclerView.ViewHolder(mView) { inner class ViewHolder(val mView: ConstraintLayout) : RecyclerView.ViewHolder(mView) {
var saveBtn: LikeButton? = null lateinit var saveBtn: LikeButton
var browserBtn: ImageButton? = null lateinit var browserBtn: ImageButton
var shareBtn: ImageButton? = null lateinit var shareBtn: ImageButton
var actionBar: RelativeLayout? = null lateinit var actionBar: RelativeLayout
var sourceImage: ImageView? = null lateinit var sourceImage: ImageView
var title: TextView? = null lateinit var title: TextView
var sourceTitleAndDate: TextView? = null lateinit var sourceTitleAndDate: TextView
init { init {
handleClickListeners() handleClickListeners()
@ -201,14 +202,14 @@ class ItemListAdapter(private val app: Activity, private val items: ArrayList<It
browserBtn = mView.findViewById(R.id.browserBtn) as ImageButton browserBtn = mView.findViewById(R.id.browserBtn) as ImageButton
saveBtn!!.setOnLikeListener(object : OnLikeListener { saveBtn.setOnLikeListener(object : OnLikeListener {
override fun liked(likeButton: LikeButton) { override fun liked(likeButton: LikeButton) {
val (id) = items[adapterPosition] val (id) = items[adapterPosition]
api.starrItem(id).enqueue(object : Callback<SuccessResponse> { api.starrItem(id).enqueue(object : Callback<SuccessResponse> {
override fun onResponse(call: Call<SuccessResponse>, response: Response<SuccessResponse>) {} override fun onResponse(call: Call<SuccessResponse>, response: Response<SuccessResponse>) {}
override fun onFailure(call: Call<SuccessResponse>, t: Throwable) { override fun onFailure(call: Call<SuccessResponse>, t: Throwable) {
saveBtn!!.isLiked = false saveBtn.isLiked = false
Toast.makeText(c, R.string.cant_mark_favortie, Toast.LENGTH_SHORT).show() Toast.makeText(c, R.string.cant_mark_favortie, Toast.LENGTH_SHORT).show()
} }
}) })
@ -220,14 +221,14 @@ class ItemListAdapter(private val app: Activity, private val items: ArrayList<It
override fun onResponse(call: Call<SuccessResponse>, response: Response<SuccessResponse>) {} override fun onResponse(call: Call<SuccessResponse>, response: Response<SuccessResponse>) {}
override fun onFailure(call: Call<SuccessResponse>, t: Throwable) { override fun onFailure(call: Call<SuccessResponse>, t: Throwable) {
saveBtn!!.isLiked = true saveBtn.isLiked = true
Toast.makeText(c, R.string.cant_unmark_favortie, Toast.LENGTH_SHORT).show() Toast.makeText(c, R.string.cant_unmark_favortie, Toast.LENGTH_SHORT).show()
} }
}) })
} }
}) })
shareBtn!!.setOnClickListener { shareBtn.setOnClickListener {
val i = items[adapterPosition] val i = items[adapterPosition]
val sendIntent = Intent() val sendIntent = Intent()
sendIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK sendIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
@ -237,7 +238,7 @@ class ItemListAdapter(private val app: Activity, private val items: ArrayList<It
c.startActivity(Intent.createChooser(sendIntent, c.getString(R.string.share)).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)) c.startActivity(Intent.createChooser(sendIntent, c.getString(R.string.share)).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK))
} }
browserBtn!!.setOnClickListener { browserBtn.setOnClickListener {
val i = items[adapterPosition] val i = items[adapterPosition]
val intent = Intent(Intent.ACTION_VIEW) val intent = Intent(Intent.ACTION_VIEW)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
@ -255,11 +256,11 @@ class ItemListAdapter(private val app: Activity, private val items: ArrayList<It
if (!clickBehavior) { if (!clickBehavior) {
mView.setOnClickListener { mView.setOnClickListener {
openItemUrl(items[adapterPosition], openItemUrl(items[adapterPosition],
customTabsIntent, customTabsIntent,
internalBrowser, internalBrowser,
articleViewer, articleViewer,
app, app,
c) c)
} }
mView.setOnLongClickListener { mView.setOnLongClickListener {
actionBarShowHide() actionBarShowHide()
@ -269,11 +270,11 @@ class ItemListAdapter(private val app: Activity, private val items: ArrayList<It
mView.setOnClickListener { actionBarShowHide() } mView.setOnClickListener { actionBarShowHide() }
mView.setOnLongClickListener { mView.setOnLongClickListener {
openItemUrl(items[adapterPosition], openItemUrl(items[adapterPosition],
customTabsIntent, customTabsIntent,
internalBrowser, internalBrowser,
articleViewer, articleViewer,
app, app,
c) c)
true true
} }
} }
@ -281,10 +282,7 @@ class ItemListAdapter(private val app: Activity, private val items: ArrayList<It
private fun actionBarShowHide() { private fun actionBarShowHide() {
bars[adapterPosition] = true bars[adapterPosition] = true
if (actionBar!!.visibility == View.GONE) if (actionBar.visibility == View.GONE) actionBar.visibility = View.VISIBLE else actionBar.visibility = View.GONE
actionBar!!.visibility = View.VISIBLE
else
actionBar!!.visibility = View.GONE
} }
} }
} }

View File

@ -12,10 +12,7 @@ import android.widget.Button
import android.widget.ImageView import android.widget.ImageView
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.api.selfoss.SelfossApi
import apps.amine.bou.readerforselfoss.api.selfoss.Sources
import apps.amine.bou.readerforselfoss.api.selfoss.SuccessResponse
import com.amulyakhare.textdrawable.TextDrawable import com.amulyakhare.textdrawable.TextDrawable
import com.amulyakhare.textdrawable.util.ColorGenerator import com.amulyakhare.textdrawable.util.ColorGenerator
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
@ -24,7 +21,16 @@ import retrofit2.Call
import retrofit2.Callback import retrofit2.Callback
import retrofit2.Response import retrofit2.Response
class SourcesListAdapter(private val app: Activity, private val items: ArrayList<Sources>, private val api: SelfossApi) : RecyclerView.Adapter<SourcesListAdapter.ViewHolder>() { import apps.amine.bou.readerforselfoss.R
import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi
import apps.amine.bou.readerforselfoss.api.selfoss.Sources
import apps.amine.bou.readerforselfoss.api.selfoss.SuccessResponse
class SourcesListAdapter(private val app: Activity,
private val items: ArrayList<Sources>,
private val api: SelfossApi) : RecyclerView.Adapter<SourcesListAdapter.ViewHolder>() {
private val c: Context = app.baseContext private val c: Context = app.baseContext
private val generator: ColorGenerator = ColorGenerator.MATERIAL private val generator: ColorGenerator = ColorGenerator.MATERIAL
@ -49,13 +55,18 @@ class SourcesListAdapter(private val app: Activity, private val items: ArrayList
val drawable = builder.build(textDrawable.toString(), color) val drawable = builder.build(textDrawable.toString(), color)
holder.sourceImage!!.setImageDrawable(drawable) holder.sourceImage!!.setImageDrawable(drawable)
} else { } else {
Glide.with(c).load(itm.getIcon(c)).asBitmap().centerCrop().into(object : BitmapImageViewTarget(holder.sourceImage) { Glide
override fun setResource(resource: Bitmap) { .with(c)
val circularBitmapDrawable = RoundedBitmapDrawableFactory.create(c.resources, resource) .load(itm.getIcon(c))
circularBitmapDrawable.isCircular = true .asBitmap()
fHolder.sourceImage!!.setImageDrawable(circularBitmapDrawable) .centerCrop()
} .into(object : BitmapImageViewTarget(holder.sourceImage) {
}) override fun setResource(resource: Bitmap) {
val circularBitmapDrawable = RoundedBitmapDrawableFactory.create(c.resources, resource)
circularBitmapDrawable.isCircular = true
fHolder.sourceImage!!.setImageDrawable(circularBitmapDrawable)
}
})
} }
holder.sourceTitle!!.text = itm.title holder.sourceTitle!!.text = itm.title
@ -89,12 +100,12 @@ class SourcesListAdapter(private val app: Activity, private val items: ArrayList
notifyItemRemoved(adapterPosition) notifyItemRemoved(adapterPosition)
notifyItemRangeChanged(adapterPosition, itemCount) notifyItemRangeChanged(adapterPosition, itemCount)
} else { } else {
Toast.makeText(app, "Petit soucis lors de la suppression de la source.", Toast.LENGTH_SHORT).show() Toast.makeText(app, R.string.can_delete_source, Toast.LENGTH_SHORT).show()
} }
} }
override fun onFailure(call: Call<SuccessResponse>, t: Throwable) { override fun onFailure(call: Call<SuccessResponse>, t: Throwable) {
Toast.makeText(app, "Petit soucis lors de la suppression de la source.", Toast.LENGTH_SHORT).show() Toast.makeText(app, R.string.can_delete_source, Toast.LENGTH_SHORT).show()
} }
}) })
} }

View File

@ -1,6 +1,5 @@
package apps.amine.bou.readerforselfoss.api.mercury package apps.amine.bou.readerforselfoss.api.mercury
import com.google.gson.GsonBuilder import com.google.gson.GsonBuilder
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor import okhttp3.logging.HttpLoggingInterceptor
@ -9,6 +8,7 @@ import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory import retrofit2.converter.gson.GsonConverterFactory
class MercuryApi(private val key: String) { class MercuryApi(private val key: String) {
private val service: MercuryService private val service: MercuryService
@ -21,8 +21,13 @@ class MercuryApi(private val key: String) {
val gson = GsonBuilder() val gson = GsonBuilder()
.setLenient() .setLenient()
.create() .create()
val retrofit = Retrofit.Builder().baseUrl("https://mercury.postlight.com").client(client) val retrofit =
.addConverterFactory(GsonConverterFactory.create(gson)).build() Retrofit
.Builder()
.baseUrl("https://mercury.postlight.com")
.client(client)
.addConverterFactory(GsonConverterFactory.create(gson))
.build()
service = retrofit.create(MercuryService::class.java) service = retrofit.create(MercuryService::class.java)
} }

View File

@ -4,6 +4,7 @@ import android.os.Parcel
import android.os.Parcelable import android.os.Parcelable
class ParsedContent(val title: String, class ParsedContent(val title: String,
val content: String, val content: String,
val date_published: String, val date_published: String,
@ -24,17 +25,17 @@ class ParsedContent(val title: String,
} }
constructor(source: Parcel) : this( constructor(source: Parcel) : this(
title = source.readString(), title = source.readString(),
content = source.readString(), content = source.readString(),
date_published = source.readString(), date_published = source.readString(),
lead_image_url = source.readString(), lead_image_url = source.readString(),
dek = source.readString(), dek = source.readString(),
url = source.readString(), url = source.readString(),
domain = source.readString(), domain = source.readString(),
excerpt = source.readString(), excerpt = source.readString(),
total_pages = source.readInt(), total_pages = source.readInt(),
rendered_pages = source.readInt(), rendered_pages = source.readInt(),
next_page_url = source.readString() next_page_url = source.readString()
) )
override fun describeContents() = 0 override fun describeContents() = 0

View File

@ -7,6 +7,7 @@ import retrofit2.http.Header
import retrofit2.http.Query import retrofit2.http.Query
interface MercuryService { interface MercuryService {
@GET("parser") @GET("parser")
fun parseUrl(@Query("url") url: String, @Header("x-api-key") key: String): Call<ParsedContent> fun parseUrl(@Query("url") url: String, @Header("x-api-key") key: String): Call<ParsedContent>

View File

@ -1,10 +1,12 @@
package apps.amine.bou.readerforselfoss.api.selfoss package apps.amine.bou.readerforselfoss.api.selfoss
import java.lang.reflect.Type
import com.google.gson.JsonParseException import com.google.gson.JsonParseException
import com.google.gson.JsonDeserializationContext import com.google.gson.JsonDeserializationContext
import com.google.gson.JsonElement import com.google.gson.JsonElement
import com.google.gson.JsonDeserializer import com.google.gson.JsonDeserializer
import java.lang.reflect.Type
internal class BooleanTypeAdapter : JsonDeserializer<Boolean> { internal class BooleanTypeAdapter : JsonDeserializer<Boolean> {

View File

@ -1,8 +1,8 @@
package apps.amine.bou.readerforselfoss.api.selfoss package apps.amine.bou.readerforselfoss.api.selfoss
import android.content.Context import android.content.Context
import apps.amine.bou.readerforselfoss.utils.Config import java.util.concurrent.ConcurrentHashMap
import com.burgstaller.okhttp.AuthenticationCacheInterceptor import com.burgstaller.okhttp.AuthenticationCacheInterceptor
import com.burgstaller.okhttp.CachingAuthenticatorDecorator import com.burgstaller.okhttp.CachingAuthenticatorDecorator
import com.burgstaller.okhttp.DispatchingAuthenticator import com.burgstaller.okhttp.DispatchingAuthenticator
@ -16,7 +16,9 @@ import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Call import retrofit2.Call
import retrofit2.Retrofit import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory import retrofit2.converter.gson.GsonConverterFactory
import java.util.concurrent.ConcurrentHashMap
import apps.amine.bou.readerforselfoss.utils.Config
class SelfossApi(c: Context) { class SelfossApi(c: Context) {
@ -43,28 +45,33 @@ class SelfossApi(c: Context) {
// note that all auth schemes should be registered as lowercase! // note that all auth schemes should be registered as lowercase!
val authenticator = DispatchingAuthenticator.Builder() val authenticator = DispatchingAuthenticator.Builder()
.with("digest", digestAuthenticator) .with("digest", digestAuthenticator)
.with("basic", basicAuthenticator) .with("basic", basicAuthenticator)
.build() .build()
val client = httpBuilder val client = httpBuilder
.authenticator(CachingAuthenticatorDecorator(authenticator, authCache)) .authenticator(CachingAuthenticatorDecorator(authenticator, authCache))
.addInterceptor(AuthenticationCacheInterceptor(authCache)) .addInterceptor(AuthenticationCacheInterceptor(authCache))
.addInterceptor(interceptor) .addInterceptor(interceptor)
.build() .build()
val builder = GsonBuilder() val builder = GsonBuilder()
builder.registerTypeAdapter(Boolean::class.javaPrimitiveType, BooleanTypeAdapter()) builder.registerTypeAdapter(Boolean::class.javaPrimitiveType, BooleanTypeAdapter())
val gson = builder val gson = builder
.setLenient() .setLenient()
.create() .create()
userName = config.userLogin userName = config.userLogin
password = config.userPassword password = config.userPassword
val retrofit = Retrofit.Builder().baseUrl(config.baseUrl).client(client) val retrofit =
.addConverterFactory(GsonConverterFactory.create(gson)).build() Retrofit
.Builder()
.baseUrl(config.baseUrl)
.client(client)
.addConverterFactory(GsonConverterFactory.create(gson))
.build()
service = retrofit.create(SelfossService::class.java) service = retrofit.create(SelfossService::class.java)
} }

View File

@ -4,10 +4,12 @@ import android.content.Context
import android.net.Uri import android.net.Uri
import android.os.Parcel import android.os.Parcel
import android.os.Parcelable import android.os.Parcelable
import apps.amine.bou.readerforselfoss.utils.Config import apps.amine.bou.readerforselfoss.utils.Config
import apps.amine.bou.readerforselfoss.utils.isEmptyOrNullOrNullString import apps.amine.bou.readerforselfoss.utils.isEmptyOrNullOrNullString
private fun constructUrl(config: Config?, path: String, file: String): String { private fun constructUrl(config: Config?, path: String, file: String): String {
val baseUriBuilder = Uri.parse(config!!.baseUrl).buildUpon() val baseUriBuilder = Uri.parse(config!!.baseUrl).buildUpon()
baseUriBuilder.appendPath(path).appendPath(file) baseUriBuilder.appendPath(path).appendPath(file)
@ -65,15 +67,15 @@ data class Item(val id: String,
} }
constructor(source: Parcel) : this( constructor(source: Parcel) : this(
id = source.readString(), id = source.readString(),
datetime = source.readString(), datetime = source.readString(),
title = source.readString(), title = source.readString(),
unread = 0.toByte() != source.readByte(), unread = 0.toByte() != source.readByte(),
starred = 0.toByte() != source.readByte(), starred = 0.toByte() != source.readByte(),
thumbnail = source.readString(), thumbnail = source.readString(),
icon = source.readString(), icon = source.readString(),
link = source.readString(), link = source.readString(),
sourcetitle = source.readString() sourcetitle = source.readString()
) )
override fun describeContents() = 0 override fun describeContents() = 0

View File

@ -1,6 +1,5 @@
package apps.amine.bou.readerforselfoss.api.selfoss package apps.amine.bou.readerforselfoss.api.selfoss
import retrofit2.Call import retrofit2.Call
import retrofit2.http.DELETE import retrofit2.http.DELETE
import retrofit2.http.Field import retrofit2.http.Field
@ -11,6 +10,7 @@ import retrofit2.http.Path
import retrofit2.http.Query import retrofit2.http.Query
internal interface SelfossService { internal interface SelfossService {
@GET("login") @GET("login")
fun loginToSelfoss(@Query("username") username: String, @Query("password") password: String): Call<SuccessResponse> fun loginToSelfoss(@Query("username") username: String, @Query("password") password: String): Call<SuccessResponse>
@ -24,47 +24,70 @@ internal interface SelfossService {
@Query("password") password: String): Call<List<Item>> @Query("password") password: String): Call<List<Item>>
@POST("mark/{id}") @POST("mark/{id}")
fun markAsRead(@Path("id") id: String, @Query("username") username: String, @Query("password") password: String): Call<SuccessResponse> fun markAsRead(@Path("id") id: String,
@Query("username") username: String,
@Query("password") password: String): Call<SuccessResponse>
@POST("unmark/{id}") @POST("unmark/{id}")
fun unmarkAsRead(@Path("id") id: String, @Query("username") username: String, @Query("password") password: String): Call<SuccessResponse> fun unmarkAsRead(@Path("id") id: String,
@Query("username") username: String,
@Query("password") password: String): Call<SuccessResponse>
@FormUrlEncoded @FormUrlEncoded
@POST("mark") @POST("mark")
fun markAllAsRead(@Field("ids[]") ids: List<String>, @Query("username") username: String, @Query("password") password: String): Call<SuccessResponse> fun markAllAsRead(@Field("ids[]") ids: List<String>,
@Query("username") username: String,
@Query("password") password: String): Call<SuccessResponse>
@POST("starr/{id}") @POST("starr/{id}")
fun starr(@Path("id") id: String, @Query("username") username: String, @Query("password") password: String): Call<SuccessResponse> fun starr(@Path("id") id: String,
@Query("username") username: String,
@Query("password") password: String): Call<SuccessResponse>
@POST("unstarr/{id}") @POST("unstarr/{id}")
fun unstarr(@Path("id") id: String, @Query("username") username: String, @Query("password") password: String): Call<SuccessResponse> fun unstarr(@Path("id") id: String,
@Query("username") username: String,
@Query("password") password: String): Call<SuccessResponse>
@GET("stats") @GET("stats")
fun stats(@Query("username") username: String, @Query("password") password: String): Call<Stats> fun stats(@Query("username") username: String,
@Query("password") password: String): Call<Stats>
@GET("tags") @GET("tags")
fun tags(@Query("username") username: String, @Query("password") password: String): Call<List<Tag>> fun tags(@Query("username") username: String,
@Query("password") password: String): Call<List<Tag>>
@GET("update") @GET("update")
fun update(@Query("username") username: String, @Query("password") password: String): Call<String> fun update(@Query("username") username: String,
@Query("password") password: String): Call<String>
@GET("sources/spouts") @GET("sources/spouts")
fun spouts(@Query("username") username: String, @Query("password") password: String): Call<Map<String, Spout>> fun spouts(@Query("username") username: String,
@Query("password") password: String): Call<Map<String, Spout>>
@GET("sources/list") @GET("sources/list")
fun sources(@Query("username") username: String, @Query("password") password: String): Call<List<Sources>> fun sources(@Query("username") username: String,
@Query("password") password: String): Call<List<Sources>>
@DELETE("source/{id}") @DELETE("source/{id}")
fun deleteSource(@Path("id") id: String, @Query("username") username: String, @Query("password") password: String): Call<SuccessResponse> fun deleteSource(@Path("id") id: String,
@Query("username") username: String,
@Query("password") password: String): Call<SuccessResponse>
@FormUrlEncoded @FormUrlEncoded
@POST("source") @POST("source")
fun createSource(@Field("title") title: String, @Field("url") url: String, @Field("spout") spout: String, @Field("tags") tags: String, @Field("filter") filter: String, @Query("username") username: String, @Query("password") password: String): Call<SuccessResponse> fun createSource(@Field("title") title: String,
@Field("url") url: String,
@Field("spout") spout: String,
@Field("tags") tags: String,
@Field("filter") filter: String,
@Query("username") username: String,
@Query("password") password: String): Call<SuccessResponse>
} }

View File

@ -7,33 +7,37 @@ import android.net.Uri
import android.support.v7.app.AlertDialog import android.support.v7.app.AlertDialog
import android.text.TextUtils import android.text.TextUtils
import android.util.Patterns import android.util.Patterns
import apps.amine.bou.readerforselfoss.BuildConfig
import apps.amine.bou.readerforselfoss.R
import com.google.firebase.remoteconfig.FirebaseRemoteConfig import com.google.firebase.remoteconfig.FirebaseRemoteConfig
import okhttp3.HttpUrl import okhttp3.HttpUrl
private fun isStoreVersion(context: Context): Boolean { import apps.amine.bou.readerforselfoss.BuildConfig
var result = false import apps.amine.bou.readerforselfoss.R
try {
val installer = context.packageManager
fun checkAndDisplayStoreApk(context: Context) = {
fun isStoreVersion(context: Context): Boolean {
var result = false
try {
val installer = context.packageManager
.getInstallerPackageName(context.packageName) .getInstallerPackageName(context.packageName)
result = !TextUtils.isEmpty(installer) result = !TextUtils.isEmpty(installer)
} catch (e: Throwable) { } catch (e: Throwable) {
}
return result
} }
return result
}
fun checkAndDisplayStoreApk(context: Context) =
if (!isStoreVersion(context) && !BuildConfig.GITHUB_VERSION) { if (!isStoreVersion(context) && !BuildConfig.GITHUB_VERSION) {
val alertDialog = AlertDialog.Builder(context).create() val alertDialog = AlertDialog.Builder(context).create()
alertDialog.setTitle(context.getString(R.string.warning_version)) alertDialog.setTitle(context.getString(R.string.warning_version))
alertDialog.setMessage(context.getString(R.string.text_version)) alertDialog.setMessage(context.getString(R.string.text_version))
alertDialog.setButton(AlertDialog.BUTTON_NEUTRAL, "OK", alertDialog.setButton(AlertDialog.BUTTON_NEUTRAL, "OK",
{ dialog, _ -> dialog.dismiss() }) { dialog, _ -> dialog.dismiss() })
alertDialog.show() alertDialog.show()
} else Unit } else Unit
}
fun isUrlValid(url: String): Boolean { fun isUrlValid(url: String): Boolean {
val baseUrl = HttpUrl.parse(url) val baseUrl = HttpUrl.parse(url)
@ -47,44 +51,46 @@ fun isUrlValid(url: String): Boolean {
} }
fun isEmptyOrNullOrNullString(str: String?): Boolean = fun isEmptyOrNullOrNullString(str: String?): Boolean =
str == null || str == "null" || str.isEmpty() str == null || str == "null" || str.isEmpty()
fun checkApkVersion(settings: SharedPreferences, editor: SharedPreferences.Editor, context: Context, mFirebaseRemoteConfig: FirebaseRemoteConfig) { fun checkApkVersion(settings: SharedPreferences,
mFirebaseRemoteConfig.fetch(43200) editor: SharedPreferences.Editor,
.addOnCompleteListener { task -> context: Context,
if (task.isSuccessful) { mFirebaseRemoteConfig: FirebaseRemoteConfig) = {
mFirebaseRemoteConfig.activateFetched() fun isThereAnUpdate() {
} else { val APK_LINK = "github_apk"
val apkLink = mFirebaseRemoteConfig.getString(APK_LINK)
val storedLink = settings.getString(APK_LINK, "")
if (apkLink != storedLink && !apkLink.isEmpty()) {
val alertDialog = AlertDialog.Builder(context).create()
alertDialog.setTitle(context.getString(R.string.new_apk_available_title))
alertDialog.setMessage(context.getString(R.string.new_apk_available_message))
alertDialog.setButton(AlertDialog.BUTTON_POSITIVE, context.getString(R.string.new_apk_available_get)) { _, _ ->
editor.putString(APK_LINK, apkLink)
editor.apply()
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(apkLink))
context.startActivity(browserIntent)
} }
alertDialog.setButton(AlertDialog.BUTTON_NEUTRAL, context.getString(R.string.new_apk_available_no),
isThereAnUpdate(settings, editor, context, mFirebaseRemoteConfig)
}
}
private fun isThereAnUpdate(settings: SharedPreferences, editor: SharedPreferences.Editor, context: Context, mFirebaseRemoteConfig: FirebaseRemoteConfig) {
val APK_LINK = "github_apk"
val apkLink = mFirebaseRemoteConfig.getString(APK_LINK)
val storedLink = settings.getString(APK_LINK, "")
if (apkLink != storedLink && !apkLink.isEmpty()) {
val alertDialog = AlertDialog.Builder(context).create()
alertDialog.setTitle(context.getString(R.string.new_apk_available_title))
alertDialog.setMessage(context.getString(R.string.new_apk_available_message))
alertDialog.setButton(AlertDialog.BUTTON_POSITIVE, context.getString(R.string.new_apk_available_get)) { _, _ ->
editor.putString(APK_LINK, apkLink)
editor.apply()
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(apkLink))
context.startActivity(browserIntent)
}
alertDialog.setButton(AlertDialog.BUTTON_NEUTRAL, context.getString(R.string.new_apk_available_no),
{ dialog, _ -> { dialog, _ ->
editor.putString(APK_LINK, apkLink) editor.putString(APK_LINK, apkLink)
editor.apply() editor.apply()
dialog.dismiss() dialog.dismiss()
}) })
alertDialog.show() alertDialog.show()
}
} }
mFirebaseRemoteConfig.fetch(43200)
.addOnCompleteListener { task ->
if (task.isSuccessful) {
mFirebaseRemoteConfig.activateFetched()
}
isThereAnUpdate()
}
} }
fun longHash(string: String): Long { fun longHash(string: String): Long {

View File

@ -7,11 +7,15 @@ import android.content.Intent
import android.graphics.BitmapFactory import android.graphics.BitmapFactory
import android.net.Uri import android.net.Uri
import android.support.customtabs.CustomTabsIntent import android.support.customtabs.CustomTabsIntent
import xyz.klinker.android.drag_dismiss.DragDismissIntentBuilder
import apps.amine.bou.readerforselfoss.R import apps.amine.bou.readerforselfoss.R
import apps.amine.bou.readerforselfoss.ReaderActivity import apps.amine.bou.readerforselfoss.ReaderActivity
import apps.amine.bou.readerforselfoss.api.selfoss.Item import apps.amine.bou.readerforselfoss.api.selfoss.Item
import apps.amine.bou.readerforselfoss.utils.customtabs.CustomTabActivityHelper import apps.amine.bou.readerforselfoss.utils.customtabs.CustomTabActivityHelper
import xyz.klinker.android.drag_dismiss.DragDismissIntentBuilder
fun buildCustomTabsIntent(c: Context): CustomTabsIntent { fun buildCustomTabsIntent(c: Context): CustomTabsIntent {

View File

@ -1,7 +1,6 @@
/* 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 android.support.v7.widget.RecyclerView
import android.view.View import android.view.View
import android.widget.ImageView import android.widget.ImageView
@ -10,6 +9,7 @@ import android.widget.TextView
import apps.amine.bou.readerforselfoss.R import apps.amine.bou.readerforselfoss.R
open class CustomBaseViewHolder(var view: View) : RecyclerView.ViewHolder(view) { open class CustomBaseViewHolder(var view: View) : RecyclerView.ViewHolder(view) {
var icon: ImageView = view.findViewById(R.id.material_drawer_icon) as ImageView var icon: ImageView = view.findViewById(R.id.material_drawer_icon) as ImageView
var name: TextView = view.findViewById(R.id.material_drawer_name) as TextView var name: TextView = view.findViewById(R.id.material_drawer_name) as TextView

View File

@ -1,8 +1,6 @@
/* From https://github.com/mikepenz/MaterialDrawer/blob/develop/app/src/main/java/com/mikepenz/materialdrawer/app/drawerItems/CustomUrlBasePrimaryDrawerItem.java */ /* From https://github.com/mikepenz/MaterialDrawer/blob/develop/app/src/main/java/com/mikepenz/materialdrawer/app/drawerItems/CustomUrlBasePrimaryDrawerItem.java */
package apps.amine.bou.readerforselfoss.utils.drawer package apps.amine.bou.readerforselfoss.utils.drawer
import android.content.Context
import android.net.Uri import android.net.Uri
import android.support.annotation.ColorInt import android.support.annotation.ColorInt
import android.support.annotation.ColorRes import android.support.annotation.ColorRes
@ -18,6 +16,7 @@ import com.mikepenz.materialdrawer.util.DrawerUIUtils
import com.mikepenz.materialize.util.UIUtils import com.mikepenz.materialize.util.UIUtils
abstract class CustomUrlBasePrimaryDrawerItem<T, VH : RecyclerView.ViewHolder> : BaseDrawerItem<T, VH>() { abstract class CustomUrlBasePrimaryDrawerItem<T, VH : RecyclerView.ViewHolder> : BaseDrawerItem<T, VH>() {
fun withIcon(url: String): T { fun withIcon(url: String): T {
this.icon = ImageHolder(url) this.icon = ImageHolder(url)

View File

@ -1,18 +1,18 @@
/* 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.content.Context
import android.support.annotation.LayoutRes import android.support.annotation.LayoutRes
import android.support.annotation.StringRes import android.support.annotation.StringRes
import android.view.View import android.view.View
import android.widget.TextView import android.widget.TextView
import apps.amine.bou.readerforselfoss.R
import com.mikepenz.materialdrawer.holder.BadgeStyle import com.mikepenz.materialdrawer.holder.BadgeStyle
import com.mikepenz.materialdrawer.holder.StringHolder import com.mikepenz.materialdrawer.holder.StringHolder
import com.mikepenz.materialdrawer.model.interfaces.ColorfulBadgeable import com.mikepenz.materialdrawer.model.interfaces.ColorfulBadgeable
import apps.amine.bou.readerforselfoss.R
class CustomUrlPrimaryDrawerItem : CustomUrlBasePrimaryDrawerItem<CustomUrlPrimaryDrawerItem, CustomUrlPrimaryDrawerItem.ViewHolder>(), ColorfulBadgeable<CustomUrlPrimaryDrawerItem> { class CustomUrlPrimaryDrawerItem : CustomUrlBasePrimaryDrawerItem<CustomUrlPrimaryDrawerItem, CustomUrlPrimaryDrawerItem.ViewHolder>(), ColorfulBadgeable<CustomUrlPrimaryDrawerItem> {
protected var mBadge: StringHolder = StringHolder("") protected var mBadge: StringHolder = StringHolder("")

View File

@ -15,7 +15,6 @@
<string name="label_share">"Partager"</string> <string name="label_share">"Partager"</string>
<string name="readAll">"Tout lire"</string> <string name="readAll">"Tout lire"</string>
<string name="action_disconnect">"Déconnecter"</string> <string name="action_disconnect">"Déconnecter"</string>
<string name="action_source">"Sources"</string>
<string name="title_activity_settings">"Paramètres"</string> <string name="title_activity_settings">"Paramètres"</string>
<string name="pref_header_general">"General"</string> <string name="pref_header_general">"General"</string>
<string name="pref_switch_actions_tap_title">"Action du clique sur un article"</string> <string name="pref_switch_actions_tap_title">"Action du clique sur un article"</string>
@ -115,4 +114,5 @@
<string name="no_sources_loaded">Pas de sources chargés</string> <string name="no_sources_loaded">Pas de sources chargés</string>
<string name="drawer_loading">Chargement …</string> <string name="drawer_loading">Chargement …</string>
<string name="menu_home_search">Rechercher</string> <string name="menu_home_search">Rechercher</string>
<string name="can_delete_source">Petit soucis lors de la suppression de la source.</string>
</resources> </resources>

View File

@ -15,7 +15,6 @@
<string name="label_share">"Delen"</string> <string name="label_share">"Delen"</string>
<string name="readAll">"Alles lezen"</string> <string name="readAll">"Alles lezen"</string>
<string name="action_disconnect">"Verbinding verbreken"</string> <string name="action_disconnect">"Verbinding verbreken"</string>
<string name="action_source">"Bronnen"</string>
<string name="title_activity_settings">"Instellingen"</string> <string name="title_activity_settings">"Instellingen"</string>
<string name="pref_header_general">"Algemeen"</string> <string name="pref_header_general">"Algemeen"</string>
<string name="pref_switch_actions_tap_title">"Actie bij tikken op artikelen"</string> <string name="pref_switch_actions_tap_title">"Actie bij tikken op artikelen"</string>
@ -115,4 +114,5 @@
<string name="no_sources_loaded">No sources loaded</string> <string name="no_sources_loaded">No sources loaded</string>
<string name="drawer_loading">Loading …</string> <string name="drawer_loading">Loading …</string>
<string name="menu_home_search">Zoeken</string> <string name="menu_home_search">Zoeken</string>
<string name="can_delete_source">Can\'t delete the source...</string>
</resources> </resources>

View File

@ -1,4 +1,4 @@
<resources> <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">"Log in"</string>
<string name="prompt_password">"Password"</string> <string name="prompt_password">"Password"</string>
@ -15,7 +15,6 @@
<string name="label_share">"Share"</string> <string name="label_share">"Share"</string>
<string name="readAll">"Read all"</string> <string name="readAll">"Read all"</string>
<string name="action_disconnect">"Disconnect"</string> <string name="action_disconnect">"Disconnect"</string>
<string name="action_source">"Sources"</string>
<string name="title_activity_settings">"Settings"</string> <string name="title_activity_settings">"Settings"</string>
<string name="pref_header_general">"General"</string> <string name="pref_header_general">"General"</string>
<string name="pref_switch_actions_tap_title">"Tap action on the articles"</string> <string name="pref_switch_actions_tap_title">"Tap action on the articles"</string>
@ -112,9 +111,10 @@
<string name="drawer_item_tags">Tags</string> <string name="drawer_item_tags">Tags</string>
<string name="drawer_item_sources">Sources</string> <string name="drawer_item_sources">Sources</string>
<string name="drawer_action_edit">edit</string> <string name="drawer_action_edit">edit</string>
<string name="cache_drawer_error">Couldn\'t cache your drawer data</string> <string name="cache_drawer_error" tools:keep="@string/cache_drawer_error">Couldn\'t cache your drawer data</string>
<string name="no_tags_loaded">No tags loaded</string> <string name="no_tags_loaded">No tags loaded</string>
<string name="no_sources_loaded">No sources loaded</string> <string name="no_sources_loaded">No sources loaded</string>
<string name="drawer_loading">Loading …</string> <string name="drawer_loading">Loading …</string>
<string name="menu_home_search">Search</string> <string name="menu_home_search">Search</string>
<string name="can_delete_source">Can\'t delete the source...</string>
</resources> </resources>