Commit a9ff6a86 authored by augier's avatar augier

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

Refactor waiting fragment and image with subtitles to used custom compound component instead of fragment
parent 7ca95690
Pipeline #2450 passed 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" />
</LinearLayout>