diff --git a/app/lint-baseline.xml b/app/lint-baseline.xml
index 03638736..a02d2c01 100644
--- a/app/lint-baseline.xml
+++ b/app/lint-baseline.xml
@@ -113,7 +113,7 @@
errorLine2=" ~~~~~~~">
@@ -311,7 +311,7 @@
errorLine2=" ^">
@@ -355,7 +355,7 @@
errorLine2=" ^">
@@ -366,7 +366,7 @@
errorLine2=" ^">
@@ -388,7 +388,7 @@
errorLine2=" ^">
@@ -399,7 +399,7 @@
errorLine2=" ^">
@@ -410,7 +410,7 @@
errorLine2=" ^">
@@ -432,7 +432,7 @@
errorLine2=" ^">
@@ -454,7 +454,7 @@
errorLine2=" ^">
@@ -465,7 +465,7 @@
errorLine2=" ^">
@@ -476,7 +476,7 @@
errorLine2=" ^">
@@ -487,7 +487,7 @@
errorLine2=" ^">
@@ -498,7 +498,7 @@
errorLine2=" ^">
@@ -509,7 +509,7 @@
errorLine2=" ^">
@@ -520,7 +520,7 @@
errorLine2=" ^">
@@ -531,7 +531,7 @@
errorLine2=" ^">
@@ -542,7 +542,7 @@
errorLine2=" ^">
@@ -553,7 +553,7 @@
errorLine2=" ^">
@@ -564,7 +564,7 @@
errorLine2=" ^">
@@ -575,7 +575,7 @@
errorLine2=" ^">
@@ -586,7 +586,7 @@
errorLine2=" ^">
@@ -597,7 +597,7 @@
errorLine2=" ^">
@@ -784,7 +784,7 @@
errorLine2=" ^">
@@ -795,7 +795,7 @@
errorLine2=" ^">
@@ -806,7 +806,7 @@
errorLine2=" ^">
@@ -817,7 +817,7 @@
errorLine2=" ^">
@@ -828,7 +828,7 @@
errorLine2=" ^">
@@ -839,7 +839,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
@@ -850,7 +850,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
@@ -894,7 +894,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
@@ -905,7 +905,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
@@ -960,7 +960,7 @@
errorLine2=" ^">
@@ -971,7 +971,7 @@
errorLine2=" ^">
@@ -982,7 +982,7 @@
errorLine2=" ^">
@@ -993,7 +993,7 @@
errorLine2=" ^">
@@ -1004,7 +1004,7 @@
errorLine2=" ^">
@@ -1015,7 +1015,7 @@
errorLine2=" ^">
@@ -1026,7 +1026,7 @@
errorLine2=" ^">
@@ -1037,7 +1037,7 @@
errorLine2=" ^">
@@ -1048,7 +1048,7 @@
errorLine2=" ^">
@@ -1059,7 +1059,7 @@
errorLine2=" ^">
@@ -1070,7 +1070,7 @@
errorLine2=" ^">
@@ -1081,7 +1081,7 @@
errorLine2=" ^">
@@ -1092,7 +1092,7 @@
errorLine2=" ^">
@@ -1103,7 +1103,7 @@
errorLine2=" ^">
@@ -1114,21 +1114,21 @@
errorLine2=" ^">
+
+
+
+
-
-
-
-
@@ -1147,7 +1147,7 @@
errorLine2=" ^">
@@ -1158,7 +1158,7 @@
errorLine2=" ^">
@@ -1169,7 +1169,7 @@
errorLine2=" ^">
@@ -1180,7 +1180,7 @@
errorLine2=" ^">
@@ -1191,7 +1191,7 @@
errorLine2=" ^">
@@ -1202,7 +1202,7 @@
errorLine2=" ^">
@@ -1213,7 +1213,7 @@
errorLine2=" ^">
@@ -1224,7 +1224,7 @@
errorLine2=" ^">
@@ -1235,7 +1235,7 @@
errorLine2=" ^">
@@ -1246,7 +1246,7 @@
errorLine2=" ^">
@@ -1257,7 +1257,7 @@
errorLine2=" ^">
@@ -1268,7 +1268,7 @@
errorLine2=" ^">
@@ -1279,7 +1279,7 @@
errorLine2=" ^">
@@ -1290,7 +1290,7 @@
errorLine2=" ^">
@@ -1301,7 +1301,7 @@
errorLine2=" ^">
@@ -1312,7 +1312,7 @@
errorLine2=" ^">
@@ -1323,7 +1323,7 @@
errorLine2=" ^">
@@ -1334,7 +1334,7 @@
errorLine2=" ^">
@@ -1345,7 +1345,7 @@
errorLine2=" ^">
@@ -1356,7 +1356,7 @@
errorLine2=" ^">
@@ -1367,7 +1367,7 @@
errorLine2=" ^">
@@ -1378,7 +1378,7 @@
errorLine2=" ^">
@@ -1389,7 +1389,7 @@
errorLine2=" ^">
@@ -1400,7 +1400,7 @@
errorLine2=" ^">
@@ -1411,7 +1411,7 @@
errorLine2=" ^">
@@ -1422,7 +1422,7 @@
errorLine2=" ^">
@@ -1433,7 +1433,7 @@
errorLine2=" ^">
@@ -2548,17 +2548,6 @@
column="13"/>
-
-
-
-
@@ -2588,7 +2577,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
@@ -2599,7 +2588,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
@@ -2610,7 +2599,7 @@
errorLine2=" ~~~~~~~~~~~~">
@@ -2621,7 +2610,7 @@
errorLine2=" ~~~~~~~~~~~~~~">
@@ -2632,7 +2621,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
@@ -2643,7 +2632,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
@@ -2654,7 +2643,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
@@ -2665,7 +2654,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
@@ -2676,7 +2665,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
@@ -2687,7 +2676,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
@@ -2698,7 +2687,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
@@ -2709,7 +2698,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~">
@@ -2720,7 +2709,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
@@ -2731,7 +2720,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
@@ -2742,7 +2731,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
@@ -2753,7 +2742,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
@@ -2764,7 +2753,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
@@ -2775,7 +2764,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
@@ -2786,7 +2775,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
@@ -2797,7 +2786,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
@@ -4157,7 +4146,7 @@
+ errorLine1=" binding.recyclerView.scrollBy(0, Utils.dpToPx(requireContext(), -30))"
+ errorLine2=" ~~~~~~~">
+ line="215"
+ column="29"/>
@@ -4645,29 +4634,29 @@
errorLine2=" ~~~~~~~">
@@ -4677,8 +4666,8 @@
errorLine1=" binding.totalAccounts.text = formatNumber(totalAccounts)"
errorLine2=" ~~~~~~~~~~~~">
@@ -4688,8 +4677,8 @@
errorLine1=" binding.totalAccounts.text = formatNumber(totalAccounts)"
errorLine2=" ~~~~~~~~~~~~">
@@ -4843,7 +4832,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
@@ -4854,7 +4843,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
@@ -4865,7 +4854,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
@@ -4876,7 +4865,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
@@ -4920,7 +4909,7 @@
errorLine2=" ~~~~~~~~~~">
@@ -5019,7 +5008,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
@@ -5030,7 +5019,7 @@
errorLine2=" ~~~~~~~~~">
@@ -5041,7 +5030,7 @@
errorLine2=" ~~~~~~~~~">
@@ -5052,7 +5041,7 @@
errorLine2=" ~~~~~~~~~">
@@ -5063,7 +5052,7 @@
errorLine2=" ~~~~~~~~~">
@@ -5074,18 +5063,18 @@
errorLine2=" ~~~~~~~~~">
@@ -5118,7 +5107,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~">
@@ -5129,7 +5118,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
@@ -5140,7 +5129,7 @@
errorLine2=" ^">
@@ -5151,7 +5140,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
@@ -5162,7 +5151,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
@@ -5173,7 +5162,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
@@ -5184,7 +5173,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~">
@@ -5195,17 +5184,10 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-
-
-
-
@@ -5686,7 +5668,7 @@
errorLine2=" ~~~~~~~~">
@@ -5697,7 +5679,7 @@
errorLine2=" ~~~~~~~~">
@@ -5708,7 +5690,7 @@
errorLine2=" ~~~~~~~~">
@@ -6192,7 +6174,7 @@
errorLine2=" ~~~~~~~~">
@@ -6203,7 +6185,7 @@
errorLine2=" ~~~~~~~~">
@@ -6214,7 +6196,7 @@
errorLine2=" ~~~~~~~~">
@@ -6225,7 +6207,7 @@
errorLine2=" ~~~~~~~~">
@@ -6588,7 +6570,7 @@
errorLine2=" ~~~~~~~~~">
@@ -6702,28 +6684,6 @@
column="9"/>
-
-
-
-
-
-
-
-
@@ -7369,7 +7329,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~">
@@ -7380,7 +7340,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
@@ -7391,7 +7351,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~">
@@ -7402,7 +7362,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
@@ -7413,7 +7373,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
@@ -7424,7 +7384,7 @@
errorLine2=" ~~~~~~">
@@ -7435,7 +7395,7 @@
errorLine2=" ~~~~~~">
@@ -7446,7 +7406,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
@@ -7457,7 +7417,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
@@ -7468,7 +7428,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
@@ -7479,7 +7439,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
@@ -7490,7 +7450,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~">
@@ -7501,7 +7461,7 @@
errorLine2=" ~~~~~~~~~~~~">
@@ -7512,7 +7472,7 @@
errorLine2=" ~~~~~~~">
@@ -7523,7 +7483,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~">
@@ -7534,7 +7494,7 @@
errorLine2=" ~~~~~~~~~~~~">
@@ -7545,7 +7505,7 @@
errorLine2=" ~~~~~~~">
@@ -7556,7 +7516,7 @@
errorLine2=" ~~~~~~~~~~~~">
@@ -7567,7 +7527,7 @@
errorLine2=" ~~~~~~~">
@@ -7578,7 +7538,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
@@ -7589,7 +7549,7 @@
errorLine2=" ~~~~~~~~~~~~">
@@ -7600,7 +7560,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
@@ -7611,7 +7571,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/TrendingTagViewHolder.kt b/app/src/main/java/com/keylesspalace/tusky/adapter/TrendingTagViewHolder.kt
deleted file mode 100644
index 71a83c98..00000000
--- a/app/src/main/java/com/keylesspalace/tusky/adapter/TrendingTagViewHolder.kt
+++ /dev/null
@@ -1,71 +0,0 @@
-/* Copyright 2023 Tusky Contributors
- *
- * This file is a part of Tusky.
- *
- * This program is free software; you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software Foundation; either version 3 of the
- * License, or (at your option) any later version.
- *
- * Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
- * Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with Tusky; if not,
- * see . */
-
-package com.keylesspalace.tusky.adapter
-
-import androidx.recyclerview.widget.RecyclerView
-import com.keylesspalace.tusky.R
-import com.keylesspalace.tusky.databinding.ItemTrendingCellBinding
-import com.keylesspalace.tusky.entity.TrendingTagHistory
-import com.keylesspalace.tusky.interfaces.LinkListener
-import com.keylesspalace.tusky.util.formatNumber
-import com.keylesspalace.tusky.viewdata.TrendingViewData
-
-class TrendingTagViewHolder(
- private val binding: ItemTrendingCellBinding
-) : RecyclerView.ViewHolder(binding.root) {
-
- fun setup(
- tagViewData: TrendingViewData.Tag,
- maxTrendingValue: Long,
- trendingListener: LinkListener
- ) {
- val reversedHistory = tagViewData.tag.history.reversed()
- setGraph(reversedHistory, maxTrendingValue)
- setTag(tagViewData.tag.name)
-
- val totalUsage = tagViewData.tag.history.sumOf { it.uses.toLongOrNull() ?: 0 }
- binding.totalUsage.text = formatNumber(totalUsage)
-
- val totalAccounts = tagViewData.tag.history.sumOf { it.accounts.toLongOrNull() ?: 0 }
- binding.totalAccounts.text = formatNumber(totalAccounts)
-
- binding.currentUsage.text = reversedHistory.last().uses
- binding.currentAccounts.text = reversedHistory.last().accounts
-
- itemView.setOnClickListener {
- trendingListener.onViewTag(tagViewData.tag.name)
- }
-
- setAccessibility(totalAccounts, tagViewData.tag.name)
- }
-
- private fun setGraph(history: List, maxTrendingValue: Long) {
- binding.graph.maxTrendingValue = maxTrendingValue
- binding.graph.primaryLineData = history
- .mapNotNull { it.uses.toLongOrNull() }
- binding.graph.secondaryLineData = history
- .mapNotNull { it.accounts.toLongOrNull() }
- }
-
- private fun setTag(tag: String) {
- binding.tag.text = binding.root.context.getString(R.string.title_tag, tag)
- }
-
- private fun setAccessibility(totalAccounts: Long, tag: String) {
- itemView.contentDescription =
- itemView.context.getString(R.string.accessibility_talking_about_tag, totalAccounts, tag)
- }
-}
diff --git a/app/src/main/java/com/keylesspalace/tusky/components/trending/TrendingActivity.kt b/app/src/main/java/com/keylesspalace/tusky/components/trending/TrendingActivity.kt
index e9bd3b70..3270e9c2 100644
--- a/app/src/main/java/com/keylesspalace/tusky/components/trending/TrendingActivity.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/components/trending/TrendingActivity.kt
@@ -19,23 +19,19 @@ import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.fragment.app.commit
-import com.keylesspalace.tusky.BottomSheetActivity
+import com.keylesspalace.tusky.BaseActivity
import com.keylesspalace.tusky.R
-import com.keylesspalace.tusky.appstore.EventHub
import com.keylesspalace.tusky.databinding.ActivityTrendingBinding
import com.keylesspalace.tusky.util.viewBinding
import dagger.android.DispatchingAndroidInjector
import dagger.android.HasAndroidInjector
import javax.inject.Inject
-class TrendingActivity : BottomSheetActivity(), HasAndroidInjector {
+class TrendingActivity : BaseActivity(), HasAndroidInjector {
@Inject
lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector
- @Inject
- lateinit var eventHub: EventHub
-
private val binding: ActivityTrendingBinding by viewBinding(ActivityTrendingBinding::inflate)
override fun onCreate(savedInstanceState: Bundle?) {
@@ -44,10 +40,8 @@ class TrendingActivity : BottomSheetActivity(), HasAndroidInjector {
setSupportActionBar(binding.includedToolbar.toolbar)
- val title = getString(R.string.title_public_trending_hashtags)
-
supportActionBar?.run {
- setTitle(title)
+ setTitle(R.string.title_public_trending_hashtags)
setDisplayHomeAsUpEnabled(true)
setDisplayShowHomeEnabled(true)
}
@@ -63,10 +57,6 @@ class TrendingActivity : BottomSheetActivity(), HasAndroidInjector {
override fun androidInjector() = dispatchingAndroidInjector
companion object {
- const val TAG = "TrendingActivity"
-
- @JvmStatic
- fun getIntent(context: Context) =
- Intent(context, TrendingActivity::class.java)
+ fun getIntent(context: Context) = Intent(context, TrendingActivity::class.java)
}
}
diff --git a/app/src/main/java/com/keylesspalace/tusky/components/trending/TrendingAdapter.kt b/app/src/main/java/com/keylesspalace/tusky/components/trending/TrendingAdapter.kt
index 6f405e2f..b40d6767 100644
--- a/app/src/main/java/com/keylesspalace/tusky/components/trending/TrendingAdapter.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/components/trending/TrendingAdapter.kt
@@ -20,15 +20,12 @@ import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
-import com.keylesspalace.tusky.adapter.TrendingDateViewHolder
-import com.keylesspalace.tusky.adapter.TrendingTagViewHolder
import com.keylesspalace.tusky.databinding.ItemTrendingCellBinding
import com.keylesspalace.tusky.databinding.ItemTrendingDateBinding
-import com.keylesspalace.tusky.interfaces.LinkListener
import com.keylesspalace.tusky.viewdata.TrendingViewData
class TrendingAdapter(
- private val trendingListener: LinkListener
+ private val onViewTag: (String) -> Unit
) : ListAdapter(TrendingDifferCallback) {
init {
@@ -42,7 +39,6 @@ class TrendingAdapter(
ItemTrendingCellBinding.inflate(LayoutInflater.from(viewGroup.context))
TrendingTagViewHolder(binding)
}
-
else -> {
val binding =
ItemTrendingDateBinding.inflate(LayoutInflater.from(viewGroup.context))
@@ -52,38 +48,15 @@ class TrendingAdapter(
}
override fun onBindViewHolder(viewHolder: RecyclerView.ViewHolder, position: Int) {
- bindViewHolder(viewHolder, position, null)
- }
-
- override fun onBindViewHolder(
- viewHolder: RecyclerView.ViewHolder,
- position: Int,
- payloads: List<*>
- ) {
- bindViewHolder(viewHolder, position, payloads)
- }
-
- private fun bindViewHolder(
- viewHolder: RecyclerView.ViewHolder,
- position: Int,
- payloads: List<*>?
- ) {
- when (val header = getItem(position)) {
+ when (val viewData = getItem(position)) {
is TrendingViewData.Tag -> {
- val maxTrendingValue = currentList
- .flatMap { trendingViewData ->
- trendingViewData.asTagOrNull()?.tag?.history.orEmpty()
- }
- .mapNotNull { it.uses.toLongOrNull() }
- .maxOrNull() ?: 1
-
val holder = viewHolder as TrendingTagViewHolder
- holder.setup(header, maxTrendingValue, trendingListener)
+ holder.setup(viewData, onViewTag)
}
is TrendingViewData.Header -> {
val holder = viewHolder as TrendingDateViewHolder
- holder.setup(header.start, header.end)
+ holder.setup(viewData.start, viewData.end)
}
}
}
@@ -112,14 +85,7 @@ class TrendingAdapter(
oldItem: TrendingViewData,
newItem: TrendingViewData
): Boolean {
- return false
- }
-
- override fun getChangePayload(
- oldItem: TrendingViewData,
- newItem: TrendingViewData
- ): Any? {
- return null
+ return oldItem == newItem
}
}
}
diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/TrendingDateViewHolder.kt b/app/src/main/java/com/keylesspalace/tusky/components/trending/TrendingDateViewHolder.kt
similarity index 96%
rename from app/src/main/java/com/keylesspalace/tusky/adapter/TrendingDateViewHolder.kt
rename to app/src/main/java/com/keylesspalace/tusky/components/trending/TrendingDateViewHolder.kt
index 48157306..5d9e3c3a 100644
--- a/app/src/main/java/com/keylesspalace/tusky/adapter/TrendingDateViewHolder.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/components/trending/TrendingDateViewHolder.kt
@@ -13,7 +13,7 @@
* You should have received a copy of the GNU General Public License along with Tusky; if not,
* see . */
-package com.keylesspalace.tusky.adapter
+package com.keylesspalace.tusky.components.trending
import androidx.recyclerview.widget.RecyclerView
import com.keylesspalace.tusky.R
diff --git a/app/src/main/java/com/keylesspalace/tusky/components/trending/TrendingFragment.kt b/app/src/main/java/com/keylesspalace/tusky/components/trending/TrendingFragment.kt
index 4148a108..bcb22d05 100644
--- a/app/src/main/java/com/keylesspalace/tusky/components/trending/TrendingFragment.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/components/trending/TrendingFragment.kt
@@ -15,17 +15,14 @@
package com.keylesspalace.tusky.components.trending
-import android.content.Context
import android.content.res.Configuration
import android.os.Bundle
import android.util.Log
-import android.view.LayoutInflater
import android.view.View
-import android.view.ViewGroup
import android.view.accessibility.AccessibilityManager
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
-import androidx.lifecycle.ViewModelProvider
+import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.GridLayoutManager.SpanSizeLookup
@@ -33,18 +30,14 @@ import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.SimpleItemAnimator
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout.OnRefreshListener
import at.connyduck.sparkbutton.helpers.Utils
-import com.keylesspalace.tusky.BottomSheetActivity
-import com.keylesspalace.tusky.PostLookupFallbackBehavior
+import com.keylesspalace.tusky.BaseActivity
import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.StatusListActivity
-import com.keylesspalace.tusky.appstore.EventHub
import com.keylesspalace.tusky.components.trending.viewmodel.TrendingViewModel
import com.keylesspalace.tusky.databinding.FragmentTrendingBinding
-import com.keylesspalace.tusky.db.AccountManager
import com.keylesspalace.tusky.di.Injectable
import com.keylesspalace.tusky.di.ViewModelFactory
import com.keylesspalace.tusky.interfaces.ActionButtonActivity
-import com.keylesspalace.tusky.interfaces.LinkListener
import com.keylesspalace.tusky.interfaces.RefreshableFragment
import com.keylesspalace.tusky.interfaces.ReselectableFragment
import com.keylesspalace.tusky.util.hide
@@ -56,48 +49,20 @@ import kotlinx.coroutines.launch
import javax.inject.Inject
class TrendingFragment :
- Fragment(),
+ Fragment(R.layout.fragment_trending),
OnRefreshListener,
- LinkListener,
Injectable,
ReselectableFragment,
RefreshableFragment {
- private lateinit var bottomSheetActivity: BottomSheetActivity
-
@Inject
lateinit var viewModelFactory: ViewModelFactory
- @Inject
- lateinit var accountManager: AccountManager
-
- @Inject
- lateinit var eventHub: EventHub
-
- private val viewModel: TrendingViewModel by lazy {
- ViewModelProvider(this, viewModelFactory)[TrendingViewModel::class.java]
- }
+ private val viewModel: TrendingViewModel by viewModels { viewModelFactory }
private val binding by viewBinding(FragmentTrendingBinding::bind)
- private lateinit var adapter: TrendingAdapter
-
- override fun onAttach(context: Context) {
- super.onAttach(context)
- bottomSheetActivity = if (context is BottomSheetActivity) {
- context
- } else {
- throw IllegalStateException("Fragment must be attached to a BottomSheetActivity!")
- }
- }
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
-
- adapter = TrendingAdapter(
- this
- )
- }
+ private val adapter = TrendingAdapter(::onViewTag)
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
@@ -106,14 +71,6 @@ class TrendingFragment :
setupLayoutManager(columnCount)
}
- override fun onCreateView(
- inflater: LayoutInflater,
- container: ViewGroup?,
- savedInstanceState: Bundle?
- ): View? {
- return inflater.inflate(R.layout.fragment_trending, container, false)
- }
-
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
setupSwipeRefreshLayout()
setupRecyclerView()
@@ -175,25 +132,19 @@ class TrendingFragment :
}
override fun onRefresh() {
- viewModel.invalidate()
+ viewModel.invalidate(true)
}
- override fun onViewUrl(url: String) {
- bottomSheetActivity.viewUrl(url, PostLookupFallbackBehavior.OPEN_IN_BROWSER)
- }
-
- override fun onViewTag(tag: String) {
- bottomSheetActivity.startActivityWithSlideInAnimation(StatusListActivity.newHashtagIntent(requireContext(), tag))
- }
-
- override fun onViewAccount(id: String) {
- bottomSheetActivity.viewAccount(id)
+ fun onViewTag(tag: String) {
+ (requireActivity() as BaseActivity).startActivityWithSlideInAnimation(StatusListActivity.newHashtagIntent(requireContext(), tag))
}
private fun processViewState(uiState: TrendingViewModel.TrendingUiState) {
+ Log.d(TAG, uiState.loadingState.name)
when (uiState.loadingState) {
TrendingViewModel.LoadingState.INITIAL -> clearLoadingState()
TrendingViewModel.LoadingState.LOADING -> applyLoadingState()
+ TrendingViewModel.LoadingState.REFRESHING -> applyRefreshingState()
TrendingViewModel.LoadingState.LOADED -> applyLoadedState(uiState.trendingViewData)
TrendingViewModel.LoadingState.ERROR_NETWORK -> networkError()
TrendingViewModel.LoadingState.ERROR_OTHER -> otherError()
@@ -203,8 +154,9 @@ class TrendingFragment :
private fun applyLoadedState(viewData: List) {
clearLoadingState()
+ adapter.submitList(viewData)
+
if (viewData.isEmpty()) {
- adapter.submitList(emptyList())
binding.recyclerView.hide()
binding.messageView.show()
binding.messageView.setup(
@@ -213,16 +165,16 @@ class TrendingFragment :
null
)
} else {
- val viewDataWithDates = listOf(viewData.first().asHeaderOrNull()) + viewData
-
- adapter.submitList(viewDataWithDates)
-
binding.recyclerView.show()
binding.messageView.hide()
}
binding.progressBar.hide()
}
+ private fun applyRefreshingState() {
+ binding.swipeRefreshLayout.isRefreshing = true
+ }
+
private fun applyLoadingState() {
binding.recyclerView.hide()
binding.messageView.hide()
@@ -297,8 +249,6 @@ class TrendingFragment :
companion object {
private const val TAG = "TrendingFragment"
- fun newInstance(): TrendingFragment {
- return TrendingFragment()
- }
+ fun newInstance() = TrendingFragment()
}
}
diff --git a/app/src/main/java/com/keylesspalace/tusky/components/trending/TrendingTagViewHolder.kt b/app/src/main/java/com/keylesspalace/tusky/components/trending/TrendingTagViewHolder.kt
new file mode 100644
index 00000000..58aad9e8
--- /dev/null
+++ b/app/src/main/java/com/keylesspalace/tusky/components/trending/TrendingTagViewHolder.kt
@@ -0,0 +1,57 @@
+/* Copyright 2023 Tusky Contributors
+ *
+ * This file is a part of Tusky.
+ *
+ * This program is free software; you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with Tusky; if not,
+ * see . */
+
+package com.keylesspalace.tusky.components.trending
+
+import androidx.recyclerview.widget.RecyclerView
+import com.keylesspalace.tusky.R
+import com.keylesspalace.tusky.databinding.ItemTrendingCellBinding
+import com.keylesspalace.tusky.util.formatNumber
+import com.keylesspalace.tusky.viewdata.TrendingViewData
+
+class TrendingTagViewHolder(
+ private val binding: ItemTrendingCellBinding
+) : RecyclerView.ViewHolder(binding.root) {
+
+ fun setup(
+ tagViewData: TrendingViewData.Tag,
+ onViewTag: (String) -> Unit
+ ) {
+ binding.tag.text = binding.root.context.getString(R.string.title_tag, tagViewData.name)
+
+ binding.graph.maxTrendingValue = tagViewData.maxTrendingValue
+ binding.graph.primaryLineData = tagViewData.usage
+ binding.graph.secondaryLineData = tagViewData.accounts
+
+ binding.totalUsage.text = formatNumber(tagViewData.usage.sum(), 1000)
+
+ val totalAccounts = tagViewData.accounts.sum()
+ binding.totalAccounts.text = formatNumber(totalAccounts, 1000)
+
+ binding.currentUsage.text = tagViewData.usage.last().toString()
+ binding.currentAccounts.text = tagViewData.usage.last().toString()
+
+ itemView.setOnClickListener {
+ onViewTag(tagViewData.name)
+ }
+
+ itemView.contentDescription =
+ itemView.context.getString(
+ R.string.accessibility_talking_about_tag,
+ totalAccounts,
+ tagViewData.name
+ )
+ }
+}
diff --git a/app/src/main/java/com/keylesspalace/tusky/components/trending/viewmodel/TrendingViewModel.kt b/app/src/main/java/com/keylesspalace/tusky/components/trending/viewmodel/TrendingViewModel.kt
index 7bf3aecf..d1877a2f 100644
--- a/app/src/main/java/com/keylesspalace/tusky/components/trending/viewmodel/TrendingViewModel.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/components/trending/viewmodel/TrendingViewModel.kt
@@ -15,11 +15,15 @@
package com.keylesspalace.tusky.components.trending.viewmodel
+import android.util.Log
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
+import at.connyduck.calladapter.networkresult.fold
import com.keylesspalace.tusky.appstore.EventHub
import com.keylesspalace.tusky.appstore.PreferenceChangedEvent
import com.keylesspalace.tusky.entity.Filter
+import com.keylesspalace.tusky.entity.end
+import com.keylesspalace.tusky.entity.start
import com.keylesspalace.tusky.network.MastodonApi
import com.keylesspalace.tusky.util.toViewData
import com.keylesspalace.tusky.viewdata.TrendingViewData
@@ -28,7 +32,7 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.filterIsInstance
import kotlinx.coroutines.launch
-import okio.IOException
+import java.io.IOException
import javax.inject.Inject
class TrendingViewModel @Inject constructor(
@@ -36,7 +40,7 @@ class TrendingViewModel @Inject constructor(
private val eventHub: EventHub
) : ViewModel() {
enum class LoadingState {
- INITIAL, LOADING, LOADED, ERROR_NETWORK, ERROR_OTHER
+ INITIAL, LOADING, REFRESHING, LOADED, ERROR_NETWORK, ERROR_OTHER
}
data class TrendingUiState(
@@ -67,37 +71,43 @@ class TrendingViewModel @Inject constructor(
*
* A tag is excluded if it is filtered by the user on their home timeline.
*/
- fun invalidate() = viewModelScope.launch {
- _uiState.value = TrendingUiState(emptyList(), LoadingState.LOADING)
-
- try {
- val deferredFilters = async { mastodonApi.getFilters() }
- val response = mastodonApi.trendingTags()
- if (!response.isSuccessful) {
- _uiState.value = TrendingUiState(emptyList(), LoadingState.ERROR_NETWORK)
- return@launch
- }
-
- val homeFilters = deferredFilters.await().getOrNull()?.filter {
- it.context.contains(Filter.Kind.HOME.kind)
- }
-
- val tags = response.body()!!
- .filter {
- homeFilters?.none { filter ->
- filter.keywords.any { keyword -> keyword.keyword.equals(it.name, ignoreCase = true) }
- } ?: false
- }
- .sortedBy { tag -> tag.history.sumOf { it.uses.toLongOrNull() ?: 0 } }
- .map { it.toViewData() }
- .asReversed()
-
- _uiState.value = TrendingUiState(tags, LoadingState.LOADED)
- } catch (e: IOException) {
- _uiState.value = TrendingUiState(emptyList(), LoadingState.ERROR_NETWORK)
- } catch (e: Exception) {
- _uiState.value = TrendingUiState(emptyList(), LoadingState.ERROR_OTHER)
+ fun invalidate(refresh: Boolean = false) = viewModelScope.launch {
+ if (refresh) {
+ _uiState.value = TrendingUiState(emptyList(), LoadingState.REFRESHING)
+ } else {
+ _uiState.value = TrendingUiState(emptyList(), LoadingState.LOADING)
}
+
+ val deferredFilters = async { mastodonApi.getFilters() }
+
+ mastodonApi.trendingTags().fold(
+ { tagResponse ->
+ val homeFilters = deferredFilters.await().getOrNull()?.filter { filter ->
+ filter.context.contains(Filter.Kind.HOME.kind)
+ }
+ val tags = tagResponse
+ .filter { tag ->
+ homeFilters?.none { filter ->
+ filter.keywords.any { keyword -> keyword.keyword.equals(tag.name, ignoreCase = true) }
+ } ?: false
+ }
+ .sortedByDescending { tag -> tag.history.sumOf { it.uses.toLongOrNull() ?: 0 } }
+ .toViewData()
+
+ val firstTag = tagResponse.first()
+ val header = TrendingViewData.Header(firstTag.start(), firstTag.end())
+
+ _uiState.value = TrendingUiState(listOf(header) + tags, LoadingState.LOADED)
+ },
+ { error ->
+ Log.w(TAG, "failed loading trending tags", error)
+ if (error is IOException) {
+ _uiState.value = TrendingUiState(emptyList(), LoadingState.ERROR_NETWORK)
+ } else {
+ _uiState.value = TrendingUiState(emptyList(), LoadingState.ERROR_OTHER)
+ }
+ }
+ )
}
companion object {
diff --git a/app/src/main/java/com/keylesspalace/tusky/entity/TrendingTagsResult.kt b/app/src/main/java/com/keylesspalace/tusky/entity/TrendingTagsResult.kt
index 7baca6fe..78669555 100644
--- a/app/src/main/java/com/keylesspalace/tusky/entity/TrendingTagsResult.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/entity/TrendingTagsResult.kt
@@ -21,15 +21,13 @@ import java.util.Date
* Mastodon API Documentation: https://docs.joinmastodon.org/methods/trends/#tags
*
* @param name The name of the hashtag (after the #). The "caturday" in "#caturday".
- * @param url The URL to your mastodon instance list for this hashtag.
+ * (@param url The URL to your mastodon instance list for this hashtag.)
* @param history A list of [TrendingTagHistory]. Each element contains metrics per day for this hashtag.
- * @param following This is not listed in the APIs at the time of writing, but an instance is delivering it.
+ * (@param following This is not listed in the APIs at the time of writing, but an instance is delivering it.)
*/
data class TrendingTag(
val name: String,
- val url: String,
- val history: List,
- val following: Boolean
+ val history: List
)
/**
diff --git a/app/src/main/java/com/keylesspalace/tusky/network/MastodonApi.kt b/app/src/main/java/com/keylesspalace/tusky/network/MastodonApi.kt
index 3eb83840..a50ca796 100644
--- a/app/src/main/java/com/keylesspalace/tusky/network/MastodonApi.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/network/MastodonApi.kt
@@ -782,5 +782,5 @@ interface MastodonApi {
suspend fun unfollowTag(@Path("name") name: String): NetworkResult
@GET("api/v1/trends/tags")
- suspend fun trendingTags(): Response>
+ suspend fun trendingTags(): NetworkResult>
}
diff --git a/app/src/main/java/com/keylesspalace/tusky/util/ViewDataUtils.kt b/app/src/main/java/com/keylesspalace/tusky/util/ViewDataUtils.kt
index 1d630f39..f6ae9e7d 100644
--- a/app/src/main/java/com/keylesspalace/tusky/util/ViewDataUtils.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/util/ViewDataUtils.kt
@@ -40,7 +40,6 @@ import com.keylesspalace.tusky.viewdata.NotificationViewData
import com.keylesspalace.tusky.viewdata.StatusViewData
import com.keylesspalace.tusky.viewdata.TrendingViewData
-@JvmName("statusToViewData")
fun Status.toViewData(
isShowingContent: Boolean,
isExpanded: Boolean,
@@ -56,7 +55,6 @@ fun Status.toViewData(
)
}
-@JvmName("notificationToViewData")
fun Notification.toViewData(
isShowingContent: Boolean,
isExpanded: Boolean,
@@ -71,9 +69,20 @@ fun Notification.toViewData(
)
}
-@JvmName("tagToViewData")
-fun TrendingTag.toViewData(): TrendingViewData.Tag {
- return TrendingViewData.Tag(
- tag = this
- )
+fun List.toViewData(): List {
+ val maxTrendingValue = flatMap { tag -> tag.history }
+ .mapNotNull { it.uses.toLongOrNull() }
+ .maxOrNull() ?: 1
+
+ return map { tag ->
+
+ val reversedHistory = tag.history.asReversed()
+
+ TrendingViewData.Tag(
+ name = tag.name,
+ usage = reversedHistory.mapNotNull { it.uses.toLongOrNull() },
+ accounts = reversedHistory.mapNotNull { it.accounts.toLongOrNull() },
+ maxTrendingValue = maxTrendingValue
+ )
+ }
}
diff --git a/app/src/main/java/com/keylesspalace/tusky/view/GraphView.kt b/app/src/main/java/com/keylesspalace/tusky/view/GraphView.kt
index 565d58a3..2aecad08 100644
--- a/app/src/main/java/com/keylesspalace/tusky/view/GraphView.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/view/GraphView.kt
@@ -22,10 +22,9 @@ import android.graphics.Path
import android.graphics.PathMeasure
import android.graphics.Rect
import android.util.AttributeSet
+import android.view.View
import androidx.annotation.ColorInt
import androidx.annotation.Dimension
-import androidx.appcompat.widget.AppCompatImageView
-import androidx.core.content.ContextCompat
import androidx.core.content.res.use
import com.keylesspalace.tusky.R
import kotlin.math.max
@@ -33,9 +32,8 @@ import kotlin.math.max
class GraphView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
- defStyleAttr: Int = 0,
- defStyleRes: Int = 0
-) : AppCompatImageView(context, attrs, defStyleAttr) {
+ defStyleAttr: Int = 0
+) : View(context, attrs, defStyleAttr) {
@get:ColorInt
@ColorInt
var primaryLineColor = 0
@@ -55,7 +53,7 @@ class GraphView @JvmOverloads constructor(
@ColorInt
var metaColor = 0
- var proportionalTrending = false
+ private var proportionalTrending = false
private lateinit var primaryLinePaint: Paint
private lateinit var secondaryLinePaint: Paint
@@ -129,16 +127,14 @@ class GraphView @JvmOverloads constructor(
private fun initFromXML(attr: AttributeSet?) {
context.obtainStyledAttributes(attr, R.styleable.GraphView).use { a ->
- primaryLineColor = ContextCompat.getColor(
- context,
+ primaryLineColor = context.getColor(
a.getResourceId(
R.styleable.GraphView_primaryLineColor,
R.color.tusky_blue
)
)
- secondaryLineColor = ContextCompat.getColor(
- context,
+ secondaryLineColor = context.getColor(
a.getResourceId(
R.styleable.GraphView_secondaryLineColor,
R.color.tusky_red
@@ -150,16 +146,14 @@ class GraphView @JvmOverloads constructor(
R.dimen.graph_line_thickness
).toFloat()
- graphColor = ContextCompat.getColor(
- context,
+ graphColor = context.getColor(
a.getResourceId(
R.styleable.GraphView_graphColor,
R.color.colorBackground
)
)
- metaColor = ContextCompat.getColor(
- context,
+ metaColor = context.getColor(
a.getResourceId(
R.styleable.GraphView_metaColor,
R.color.dividerColor
diff --git a/app/src/main/java/com/keylesspalace/tusky/viewdata/TrendingViewData.kt b/app/src/main/java/com/keylesspalace/tusky/viewdata/TrendingViewData.kt
index c018aebc..6eae7331 100644
--- a/app/src/main/java/com/keylesspalace/tusky/viewdata/TrendingViewData.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/viewdata/TrendingViewData.kt
@@ -15,9 +15,6 @@
package com.keylesspalace.tusky.viewdata
-import com.keylesspalace.tusky.entity.TrendingTag
-import com.keylesspalace.tusky.entity.end
-import com.keylesspalace.tusky.entity.start
import java.util.Date
sealed class TrendingViewData {
@@ -31,18 +28,13 @@ sealed class TrendingViewData {
get() = start.toString() + end.toString()
}
- fun asHeaderOrNull(): Header? {
- val tag = (this as? Tag)?.tag
- ?: return null
- return Header(tag.start(), tag.end())
- }
-
data class Tag(
- val tag: TrendingTag
+ val name: String,
+ val usage: List,
+ val accounts: List,
+ val maxTrendingValue: Long
) : TrendingViewData() {
override val id: String
- get() = tag.name
+ get() = name
}
-
- fun asTagOrNull() = this as? Tag
}