Commit 8a0fbbfa authored by Christophe Henry's avatar Christophe Henry

Merge branch 'refacto-waiting-fragment' into 'develop'

Refactor waiting fragment and image with subtitles to used custom compound...

See merge request !62
parents 7ca95690 a9ff6a86
Pipeline #2452 running with stage
in 0 seconds
......@@ -18,10 +18,9 @@ import fr.chenry.android.freshrss.utils.Try
import fr.chenry.android.freshrss.utils.whenNotNull
import nl.komponents.kovenant.android.startKovenant
import nl.komponents.kovenant.android.stopKovenant
import nl.komponents.kovenant.deferred
import java.util.Properties
class FreshRSSApplication : Application() {
class FreshRSSApplication: Application() {
private val _refresherService = MutableLiveData<RefresherService>()
private val serviceConnection = RefresherServiceConnection()
......@@ -40,7 +39,7 @@ class FreshRSSApplication : Application() {
startKovenant()
// Stupid hack because Android is still not able to provide the current
// application globally even though it's an actual a singleton...
FreshRSSApplication.applicationPromise.resolve(this)
appInstance = this
preferences.initDefaults()
......@@ -53,7 +52,7 @@ class FreshRSSApplication : Application() {
}.getOrDefault(false)
// Debug
// Stetho.initializeWithDefaults(this)
//Stetho.initializeWithDefaults(this)
}
override fun onTerminate() {
......@@ -62,20 +61,20 @@ class FreshRSSApplication : Application() {
}
companion object {
private val applicationPromise = deferred<FreshRSSApplication, Throwable>()
val application: FreshRSSApplication get() = applicationPromise.promise.get()
private lateinit var appInstance: FreshRSSApplication
val application: FreshRSSApplication get() = appInstance
val database get() = application.database
val context: Context get() = application.applicationContext
val notificationManager: NotificationManagerCompat
get() = NotificationManagerCompat.from(application)
val preferences: FreshRSSPreferences get() = application.preferences
fun getStringR(id: Int, vararg formatArgs: Any = arrayOf()): String = if (formatArgs.isEmpty())
fun getStringR(id: Int, vararg formatArgs: Any = arrayOf()): String = if(formatArgs.isEmpty())
application.resources.getString(id) else
application.resources.getString(id, *formatArgs)
}
inner class RefresherServiceConnection : ServiceConnection, SharedPreferences.OnSharedPreferenceChangeListener {
inner class RefresherServiceConnection: ServiceConnection, SharedPreferences.OnSharedPreferenceChangeListener {
private val handler = Handler()
private val token = object {}
private var refreshFrequency: Long = 30L
......
......@@ -59,7 +59,7 @@ class MainActivity: AppCompatActivity() {
return super.onOptionsItemSelected(item)
}
fun onAddSubscriptionClick(menuItem: MenuItem): Boolean {
fun onAddSubscriptionClick(@Suppress("UNUSED_PARAMETER") menuItem: MenuItem): Boolean {
drawerLayout.closeDrawers()
AddSubscriptionDialog{
Store.postAddSubscription(it).fail(this::e)
......@@ -67,7 +67,7 @@ class MainActivity: AppCompatActivity() {
return true
}
fun onSettingsItemClick(menuItem: MenuItem): Boolean {
fun onSettingsItemClick(@Suppress("UNUSED_PARAMETER") menuItem: MenuItem): Boolean {
drawerLayout.closeDrawers()
navigation.navigate(MainNavDirections.actionGlobalSettingsFragment())
return true
......
......@@ -6,7 +6,7 @@ import android.os.Handler
import androidx.appcompat.app.AppCompatActivity
import androidx.core.os.postDelayed
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import androidx.lifecycle.ViewModelProvider
import fr.chenry.android.freshrss.*
import fr.chenry.android.freshrss.store.database.models.VoidAccount
import fr.chenry.android.freshrss.store.viewmodels.AccountVM
......@@ -17,7 +17,7 @@ import nl.komponents.kovenant.ui.failUi
import org.joda.time.LocalDateTime
class StartActivity : AppCompatActivity() {
private val model by lazy { ViewModelProviders.of(this).get(AccountVM::class.java) }
private val model by lazy { ViewModelProvider(this).get(AccountVM::class.java) }
private val observer = object : Observer<RefresherService> {
override fun onChanged(t: RefresherService?) {
t.whenNotNull {
......
......@@ -28,8 +28,7 @@ import nl.komponents.kovenant.ui.failUi
class SubscriptionArticlesDetailFragment : Fragment() {
private lateinit var articleId: String
private val model: SubscriptionArticleVM by lazy {
ViewModelProviders
.of(this, SubscriptionArticleVMF(articleId))
ViewModelProvider(this, SubscriptionArticleVMF(articleId))
.get(SubscriptionArticleVM::class.java)
}
private var isFetching = MutableLiveData<Boolean>().apply { value = false }
......
package fr.chenry.android.freshrss.components.subscriptionarticles
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.*
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import androidx.lifecycle.*
import androidx.navigation.findNavController
import androidx.navigation.fragment.navArgs
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.*
import androidx.recyclerview.widget.RecyclerView.ViewHolder
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.FlexibleAdapter.OnItemClickListener
......@@ -26,14 +21,13 @@ import kotlinx.android.synthetic.main.fragment_subscription_articles.*
import nl.komponents.kovenant.Promise
import nl.komponents.kovenant.ui.alwaysUi
class SubscriptionArticlesFragment : Fragment(), Observer<List<SubscriptionArticleViewItem>> {
class SubscriptionArticlesFragment: Fragment(), Observer<List<SubscriptionArticleViewItem>> {
private val args: SubscriptionArticlesFragmentArgs by navArgs()
private val streamId: String by lazy { args.id }
private val readStatus: ReadStatus by lazy { args.readStatus }
private val streamId: String by lazy {args.id}
private val readStatus: ReadStatus by lazy {args.readStatus}
private val model: SubscriptionArticlesVM by lazy {
ViewModelProviders
.of(this, SubscriptionArticlesVMF(streamId, readStatus))
ViewModelProvider(this, SubscriptionArticlesVMF(streamId, readStatus))
.get(SubscriptionArticlesVM::class.java).apply {
liveData.observe(this@SubscriptionArticlesFragment, this@SubscriptionArticlesFragment)
}
......@@ -62,7 +56,7 @@ class SubscriptionArticlesFragment : Fragment(), Observer<List<SubscriptionArtic
}
fun onItemClick(position: Int): Boolean =
adapter.getItem(position)?.article?.id?.let { articleId ->
adapter.getItem(position)?.article?.id?.let {articleId ->
val direction = SubscriptionArticlesFragmentDirections
.actionSubscriptionArticlesFragmentToSubscriptionArticlesDetailFragment(articleId)
view?.findNavController()?.navigate(direction)
......@@ -74,42 +68,50 @@ class SubscriptionArticlesFragment : Fragment(), Observer<List<SubscriptionArtic
} ?: Promise.ofSuccess(Unit)
private fun toggleProgressCircle(articles: List<*>) {
fragment_subscription_article_empty_list_text.text = when (readStatus) {
fragment_subscription_article_empty_list.text = when(readStatus) {
READ -> context?.getString(R.string.empty_subscription_list, model.subscription.title)
UNREAD -> context?.getString(R.string.empty_subscription_unread_list, model.subscription.title)
}
when (readStatus) {
when(readStatus) {
READ -> R.drawable.ic_undraw_blogging
UNREAD -> R.drawable.ic_undraw_all_read
}.let { fragment_subscription_article_empty_list_image.setImageResource(it) }
}.let {fragment_subscription_article_empty_list.setImageResource(it)}
if (Store.refreshingPromise.value == null) {
fragment_subscription_article_recycler.visibility = if (articles.isNotEmpty()) View.VISIBLE else View.GONE
fragment_subscription_article_empty_list.visibility = if (articles.isEmpty()) View.VISIBLE else View.GONE
if(articles.isNotEmpty()) {
fragment_subscription_article_recycler.visibility = View.VISIBLE
fragment_subscription_article_empty_list.visibility = View.GONE
fragment_subscription_article_waiting.visibility = View.GONE
} else {
fragment_subscription_article_recycler.visibility = if (articles.isNotEmpty()) View.VISIBLE else View.GONE
fragment_subscription_article_waiting.visibility = if (articles.isEmpty()) View.VISIBLE else View.GONE
fragment_subscription_article_empty_list.visibility = View.GONE
fragment_subscription_article_recycler.visibility = View.GONE
if(Store.refreshingPromise.value == null) {
fragment_subscription_article_waiting.visibility = View.GONE
fragment_subscription_article_empty_list.visibility = View.VISIBLE
} else {
fragment_subscription_article_waiting.visibility = View.VISIBLE
fragment_subscription_article_empty_list.visibility = View.GONE
}
}
}
private inner class ArticleAdapter(items: List<SubscriptionArticleViewItem>) :
private inner class ArticleAdapter(items: List<SubscriptionArticleViewItem>):
FlexibleAdapter<SubscriptionArticleViewItem>(items, null, true) {
override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
super.onAttachedToRecyclerView(recyclerView)
isSwipeEnabled = true
itemTouchHelperCallback.setSwipeFlags(ItemTouchHelper.RIGHT)
addListener(OnItemClickListener { _, position -> this@SubscriptionArticlesFragment.onItemClick(position) })
addListener(object : OnItemSwipeListener {
addListener(OnItemClickListener {_, position -> this@SubscriptionArticlesFragment.onItemClick(position)})
addListener(object: OnItemSwipeListener {
override fun onActionStateChanged(viewHolder: ViewHolder?, actionState: Int) {}
override fun onItemSwipe(position: Int, direction: Int) {
if (direction == ItemTouchHelper.RIGHT) toggleArticleReadStatus(position).alwaysUi {
if (readStatus == READ) this@ArticleAdapter.notifyItemChanged(position)
if(direction == ItemTouchHelper.RIGHT) toggleArticleReadStatus(position).alwaysUi {
if(readStatus == READ) this@ArticleAdapter.notifyItemChanged(position)
}
}
})
......
......@@ -2,10 +2,7 @@ package fr.chenry.android.freshrss.components.subscriptions
import android.os.Bundle
import android.util.TypedValue
import android.view.LayoutInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import android.view.*
import android.widget.LinearLayout
import androidx.core.view.updateLayoutParams
import androidx.fragment.app.Fragment
......@@ -21,8 +18,8 @@ import fr.chenry.android.freshrss.store.database.models.VoidCategory
import kotlinx.android.synthetic.main.fragment_main_subscription.*
import kotlinx.android.synthetic.main.menu_badge.*
class MainSubscriptionFragment : Fragment(), BottomNavigationView.OnNavigationItemSelectedListener {
private val adapter by lazy { MainSubscriptionPagerAdapter() }
class MainSubscriptionFragment: Fragment(), BottomNavigationView.OnNavigationItemSelectedListener {
private val adapter by lazy {MainSubscriptionPagerAdapter()}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? =
inflater.inflate(R.layout.fragment_main_subscription, container, false)
......@@ -40,7 +37,7 @@ class MainSubscriptionFragment : Fragment(), BottomNavigationView.OnNavigationIt
subcription_fragment_container.currentItem = it.ordinal
}
subcription_fragment_container.addOnPageChangeListener(object : SimpleOnPageChangeListener() {
subcription_fragment_container.addOnPageChangeListener(object: SimpleOnPageChangeListener() {
override fun onPageSelected(position: Int) = this@MainSubscriptionFragment.onPageSelected(position)
})
subcription_bottom_navigation.setOnNavigationItemSelectedListener(this)
......@@ -67,9 +64,9 @@ class MainSubscriptionFragment : Fragment(), BottomNavigationView.OnNavigationIt
addView(layoutInflater.inflate(R.layout.menu_badge, menuItems as ViewGroup, false))
}
val observer = Observer<Int?> { count ->
menu_counter_badge_count.visibility = if ((count ?: 0) > 0) View.VISIBLE else View.INVISIBLE
menu_counter_badge_count.text = (count ?: 0).let { if (it > 99) "99+" else it.toString() }
val observer = Observer<Int?> {count ->
menu_counter_badge_count.visibility = if((count ?: 0) > 0) View.VISIBLE else View.INVISIBLE
menu_counter_badge_count.text = (count ?: 0).let {if(it > 99) "99+" else it.toString()}
}
setupBadgeStyle(Store.subscriptionsSection.value!!)
......@@ -82,7 +79,7 @@ class MainSubscriptionFragment : Fragment(), BottomNavigationView.OnNavigationIt
(resources.getDimensionPixelSize(R.dimen.badge_active_text_size) -
resources.getDimensionPixelSize(R.dimen.badge_inactive_text_size))
if (activeSubscriptionSection == SubscriptionSection.UNREAD) {
if(activeSubscriptionSection == SubscriptionSection.UNREAD) {
menu_counter_badge_count.updateLayoutParams<LinearLayout.LayoutParams> {
setMargins(0, 0, 0, resources.getDimensionPixelSize(R.dimen.badge_margin_bottom))
marginStart = resources.getDimensionPixelSize(R.dimen.badge_margin_start) + (offset / 2)
......@@ -105,7 +102,10 @@ class MainSubscriptionFragment : Fragment(), BottomNavigationView.OnNavigationIt
}
}
inner class MainSubscriptionPagerAdapter : FragmentPagerAdapter(childFragmentManager) {
inner class MainSubscriptionPagerAdapter:
FragmentPagerAdapter(childFragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
override fun getItem(position: Int) = instantiateFragment(SubscriptionSection.byPosition(position))
override fun getCount() = SubscriptionSection.values().size
......@@ -117,7 +117,7 @@ class MainSubscriptionFragment : Fragment(), BottomNavigationView.OnNavigationIt
return childFragmentManager
.fragmentFactory
.instantiate(activity!!.classLoader, SubscriptionsFragment::class.qualifiedName!!)
.apply { setArguments(arguments) }
.apply {setArguments(arguments)}
}
}
}
......@@ -2,11 +2,9 @@ package fr.chenry.android.freshrss.components.subscriptions
import android.os.Bundle
import android.view.*
import android.widget.ImageView
import android.widget.TextView
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
import androidx.recyclerview.widget.LinearLayoutManager
......@@ -20,8 +18,8 @@ import fr.chenry.android.freshrss.store.Store
import fr.chenry.android.freshrss.store.database.models.*
import fr.chenry.android.freshrss.store.database.models.ReadStatus.READ
import fr.chenry.android.freshrss.store.viewmodels.*
import fr.chenry.android.freshrss.utils.EmotionnalImageSubtext
import fr.chenry.android.freshrss.utils.whenNotNull
import kotlinx.android.synthetic.main.fast_scroller.*
import kotlinx.android.synthetic.main.fragment_subscriptions.*
import nl.komponents.kovenant.Promise
......@@ -32,13 +30,12 @@ class SubscriptionsFragment : Fragment(), Observer<Subscriptions> {
val model by lazy {
if (category != VoidCategory)
ViewModelProviders
.of(this, SubscriptionsFragmentCategoryVMF(category, section))
ViewModelProvider(this, SubscriptionsFragmentCategoryVMF(category, section))
.get(AllSubscriptionsVM::class.java)
else when (section) {
ALL -> ViewModelProviders.of(this).get(AllSubscriptionsVM::class.java)
UNREAD -> ViewModelProviders.of(this).get(UnreadSubscriptionsVM::class.java)
FAVORITES -> ViewModelProviders.of(this).get(FavoritesSubscriptionsVM::class.java)
ALL -> ViewModelProvider(this).get(AllSubscriptionsVM::class.java)
UNREAD -> ViewModelProvider(this).get(UnreadSubscriptionsVM::class.java)
FAVORITES -> ViewModelProvider(this).get(FavoritesSubscriptionsVM::class.java)
}
}
......@@ -64,7 +61,7 @@ class SubscriptionsFragment : Fragment(), Observer<Subscriptions> {
}
}.let { FreshRSSApplication.getStringR(it, category.label) }
view.findViewById<TextView>(R.id.fragment_subscriptions_empty_list_text).text = contentDescription
view.findViewById<EmotionnalImageSubtext>(R.id.fragment_subscriptions_empty_list).text = contentDescription
val imageResource = when (section) {
ALL -> R.drawable.ic_undraw_empty
......@@ -72,7 +69,7 @@ class SubscriptionsFragment : Fragment(), Observer<Subscriptions> {
FAVORITES -> R.drawable.ic_undraw_loving_it
}
view.findViewById<ImageView>(R.id.fragment_subscriptions_empty_list_image).setImageResource(imageResource)
view.findViewById<EmotionnalImageSubtext>(R.id.fragment_subscriptions_empty_list).setImageResource(imageResource)
view.findViewById<SwipeRefreshLayout>(R.id.subcription_pull_to_refresh)?.let {
Store.refreshingPromise.observe(this, Observer<Promise<Unit, Exception>?> { v ->
......@@ -104,12 +101,6 @@ class SubscriptionsFragment : Fragment(), Observer<Subscriptions> {
view.findViewById<RecyclerView>(R.id.fragment_subscriptions_list).let {
it.layoutManager = LinearLayoutManager(context, RecyclerView.VERTICAL, false)
it.adapter = adapter
it.addOnLayoutChangeListener { _, _, top, _, bottom, _, oldTop, _, oldBottom ->
if (top == oldTop && bottom == oldBottom) return@addOnLayoutChangeListener
fast_scroller.visibility =
if (fragment_subscriptions_list.height >= fragment_subscriptions_list_container.height) View.VISIBLE
else View.GONE
}
}
view.findViewById<FastScroller>(R.id.fast_scroller).let {
......@@ -119,16 +110,24 @@ class SubscriptionsFragment : Fragment(), Observer<Subscriptions> {
}
private fun toggleProgressCircle(subscriptions: Subscriptions) {
if (Store.refreshingPromise.value == null) {
fragment_subscriptions_list_container.visibility =
if (subscriptions.isNotEmpty()) View.VISIBLE else View.GONE
fragment_subscriptions_empty_list.visibility = if (subscriptions.isEmpty()) View.VISIBLE else View.GONE
if(subscriptions.isNotEmpty()) {
fragment_subscriptions_list.visibility = View.VISIBLE
fast_scroller.visibility = View.VISIBLE
fragment_subscriptions_empty_list.visibility = View.GONE
fragment_subscriptions_waiting.visibility = View.GONE
} else {
fragment_subscriptions_list_container.visibility =
if (subscriptions.isNotEmpty()) View.VISIBLE else View.GONE
fragment_subscriptions_waiting.visibility = if (subscriptions.isEmpty()) View.VISIBLE else View.GONE
fragment_subscriptions_empty_list.visibility = View.GONE
fragment_subscriptions_list.visibility = View.GONE
fast_scroller.visibility = View.GONE
if(Store.refreshingPromise.value == null) {
fragment_subscriptions_empty_list.visibility = View.VISIBLE
fragment_subscriptions_waiting.visibility = View.GONE
} else {
fragment_subscriptions_empty_list.visibility = View.GONE
fragment_subscriptions_waiting.visibility = View.VISIBLE
}
}
}
}
package fr.chenry.android.freshrss.components.waiting
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import fr.chenry.android.freshrss.R
import kotlinx.android.synthetic.main.fragment_waiting.*
class WaitingFragment : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? =
inflater.inflate(R.layout.fragment_waiting, container, false)
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
val shortAnimTime = resources.getInteger(android.R.integer.config_shortAnimTime).toLong()
waitin_progress.animate().setDuration(shortAnimTime).alpha(1f)
}
}
package fr.chenry.android.freshrss.utils
import android.content.Context
import android.util.AttributeSet
import android.view.*
import android.widget.LinearLayout
import android.widget.TextView
import androidx.annotation.DrawableRes
import androidx.appcompat.widget.AppCompatImageView
import fr.chenry.android.freshrss.R
class EmotionnalImageSubtext: LinearLayout {
var text: CharSequence?
get() = if(::textView.isInitialized) textView.text else ""
set(value) {
if(::textView.isInitialized && text != null) textView.text = value
}
private lateinit var imageView: AppCompatImageView
private lateinit var textView: TextView
constructor(context: Context): super(context) {
init()
}
constructor(context: Context, attrs: AttributeSet): super(context, attrs) {
init(attrs, 0)
}
constructor(context: Context, attrs: AttributeSet, defStyle: Int): super(context, attrs, defStyle) {
init(attrs, defStyle)
}
fun setImageResource(@DrawableRes resId: Int) = imageView.setImageResource(resId)
private fun init(attrs: AttributeSet? = null, defStyle: Int = 0) {
val a =
context.obtainStyledAttributes(attrs, R.styleable.EmotionnalImageSubtext, defStyle, 0)
val text = a.getString(R.styleable.EmotionnalImageSubtext_text)
val src = a.getDrawable(R.styleable.EmotionnalImageSubtext_src)
a.recycle()
orientation = VERTICAL
gravity = Gravity.CENTER
val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
inflater.inflate(R.layout.emotional_image_subtext, this, true)
imageView = getChildAt(0) as AppCompatImageView
textView = getChildAt(1) as TextView
imageView.setImageDrawable(src)
textView.visibility = if(text.isNullOrBlank()) View.GONE else View.VISIBLE
textView.text = text
}
}
......@@ -14,10 +14,8 @@ import com.github.kittinunf.fuel.jackson.responseObject
import fr.chenry.android.freshrss.store.database.models.Account
import nl.komponents.kovenant.Kovenant.deferred
import nl.komponents.kovenant.Promise
import nl.komponents.kovenant.functional.bind
import nl.komponents.kovenant.task
import org.apache.commons.text.StringEscapeUtils
import org.apache.commons.text.WordUtils
import java.net.URL
import kotlin.reflect.full.companionObjectInstance
......@@ -92,7 +90,6 @@ fun String.addTrailingSlash() = if(this.endsWith("/")) this else "$this/"
fun String.removeNewLines() = this.replace("\\s+".toRegex(), " ")
fun String.escapeHtml4() = StringEscapeUtils.escapeHtml4(this).orEmpty()
fun String.unescapeHtml4() = StringEscapeUtils.unescapeHtml4(this).orEmpty()
fun String.capitalizeFull() = WordUtils.capitalize(this)
fun String?.nullIfBlank() = if(this.isNullOrBlank()) null else this
fun String?.extractURLs(): List<Uri> = if(this.isNullOrBlank()) listOf() else {
this
......@@ -101,21 +98,13 @@ fun String?.extractURLs(): List<Uri> = if(this.isNullOrBlank()) listOf() else {
}
}
fun <V, R> Promise<V, Exception>.bindVoid(fn: () -> Promise<R, Exception>): Promise<R, Exception> = this.bind {fn()}
fun <V, E> Promise<V, E>.getOrDefault(default: V) = try {
this.get()
} catch(e: Exception) {
this.w(e)
default
}
fun <T: Any> T?.whenNotNull(body: (T) -> Unit) = if(this !== null) body(this).let {this} else this
fun <T: Any> T?.whenNull(body: () -> Unit) = this ?: body().let {this}
@Suppress("DEPRECATION")
fun Context.isConnectedToNetwork(): Boolean {
val connectivityManager =
this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager?
return connectivityManager?.activeNetworkInfo?.isConnectedOrConnecting() ?: false
val connectivityManager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager?
return connectivityManager?.activeNetworkInfo?.isConnectedOrConnecting ?: false
}
fun URL.queryParameters(): Map<String, String> = this.query
......
package fr.chenry.android.freshrss.utils
import android.content.Context
import android.util.AttributeSet
import android.view.*
import android.widget.*
import fr.chenry.android.freshrss.R
class Loader: LinearLayout {
private lateinit var progressBar: ProgressBar
private lateinit var textView: TextView
constructor(context: Context): super(context) {
init()
}
constructor(context: Context, attrs: AttributeSet): super(context, attrs) {
init(attrs, 0)
}
constructor(context: Context, attrs: AttributeSet, defStyle: Int): super(context, attrs, defStyle) {
init(attrs, defStyle)
}
fun init(attrs: AttributeSet? = null, defStyle: Int = 0) {
val a = context.obtainStyledAttributes(attrs, R.styleable.Loader, defStyle, 0)
val loaderText = a.getString(R.styleable.Loader_loader_text)
a.recycle()
orientation = VERTICAL
gravity = Gravity.CENTER
val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
inflater.inflate(R.layout.loader, this, true)
progressBar = getChildAt(0) as ProgressBar
textView = getChildAt(1) as TextView
val shortAnimTime = resources.getInteger(android.R.integer.config_shortAnimTime).toLong()
progressBar.animate().setDuration(shortAnimTime).alpha(1f)
textView.visibility = if(loaderText.isNullOrBlank()) View.GONE else View.VISIBLE
textView.text = loaderText
}
}
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/emotional_image_subtext_image"
android:layout_width="wrap_content"
android:layout_height="140dp"
android:layout_gravity="center"
android:layout_marginBottom="@dimen/activity_horizontal_margin"
android:src="@drawable/ic_undraw_blogging" />
<TextView
android:id="@+id/emotional_image_subtext_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/empty_subscriptions_section_unread"
style="@style/SubText" />
</merge>
\ No newline at end of file
......@@ -2,7 +2,6 @@
<eu.davidea.fastscroller.FastScroller
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/fast_scroller"
android:layout_width="wrap_content"
android:layout_height="match_parent"
tools:visibility="visible" />
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_height="match_parent"
android:layout_width="match_parent"
tools:context=".components.subscriptionarticles.SubscriptionArticlesFragment"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_margin="0dp"
android:orientation="horizontal"
android:padding="0dp"
android:layout_margin="0dp">
tools:context=".components.subscriptionarticles.SubscriptionArticlesFragment">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/fragment_subscription_article_recycler"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:listitem="@layout/fragment_subscription_article"
android:visibility="visible" />
android:visibility="visible"
tools:listitem="@layout/fragment_subscription_article" />
<FrameLayout
<fr.chenry.android.freshrss.utils.Loader
android:id="@+id/fragment_subscription_article_waiting"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone">
<fragment
android:id="@+id/fragment_subscription_article_waiting_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
class="fr.chenry.android.freshrss.components.waiting.WaitingFragment"
android:layout_margin="0dp" />
</FrameLayout>
android:visibility="gone" />
<LinearLayout
<fr.chenry.android.freshrss.utils.EmotionnalImageSubtext
android:id="@+id/fragment_subscription_article_empty_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center"
android:layout_gravity="center"
android:visibility="gone">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/fragment_subscription_article_empty_list_image"
android:layout_width="wrap_content"
android:layout_height="140dp"
android:src="@drawable/ic_undraw_blogging"
android:layout_marginBottom="@dimen/activity_horizontal_margin" />
<TextView
android:id="@+id/fragment_subscription_article_empty_list_text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/empty_subscriptions_section_unread"
android:gravity="center|center_horizontal|center_vertical"
android:layout_gravity="center"
android:textColor="@color/light_grey"
android:textSize="24sp"
android:textStyle="bold" />