Refactor "trending hashtags" code (#3595)

- Fix codeformatting
- Add new refreshing state
- Disable LogConditional lint rule
- Update lint-baseline
This commit is contained in:
Konrad Pozniak 2023-06-10 19:47:07 +02:00 committed by GitHub
parent 071e00774e
commit f23c0cc634
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 335 additions and 480 deletions

File diff suppressed because it is too large Load diff

View file

@ -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 <http://www.gnu.org/licenses>. */
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<TrendingTagHistory>, 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)
}
}

View file

@ -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<Any>
@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)
}
}

View file

@ -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<TrendingViewData, RecyclerView.ViewHolder>(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
}
}
}

View file

@ -13,7 +13,7 @@
* You should have received a copy of the GNU General Public License along with Tusky; if not,
* see <http://www.gnu.org/licenses>. */
package com.keylesspalace.tusky.adapter
package com.keylesspalace.tusky.components.trending
import androidx.recyclerview.widget.RecyclerView
import com.keylesspalace.tusky.R

View file

@ -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<TrendingViewData>) {
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()
}
}

View file

@ -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 <http://www.gnu.org/licenses>. */
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
)
}
}

View file

@ -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 {

View file

@ -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<TrendingTagHistory>,
val following: Boolean
val history: List<TrendingTagHistory>
)
/**

View file

@ -782,5 +782,5 @@ interface MastodonApi {
suspend fun unfollowTag(@Path("name") name: String): NetworkResult<HashTag>
@GET("api/v1/trends/tags")
suspend fun trendingTags(): Response<List<TrendingTag>>
suspend fun trendingTags(): NetworkResult<List<TrendingTag>>
}

View file

@ -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<TrendingTag>.toViewData(): List<TrendingViewData.Tag> {
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
)
}
}

View file

@ -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

View file

@ -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<Long>,
val accounts: List<Long>,
val maxTrendingValue: Long
) : TrendingViewData() {
override val id: String
get() = tag.name
get() = name
}
fun asTagOrNull() = this as? Tag
}