From f23c0cc634d28a64e276eaa42db188a4e3a1bf9f Mon Sep 17 00:00:00 2001 From: Konrad Pozniak <connyduck@users.noreply.github.com> Date: Sat, 10 Jun 2023 19:47:07 +0200 Subject: [PATCH] Refactor "trending hashtags" code (#3595) - Fix codeformatting - Add new refreshing state - Disable LogConditional lint rule - Update lint-baseline --- app/lint-baseline.xml | 392 ++++++++---------- .../tusky/adapter/TrendingTagViewHolder.kt | 71 ---- .../components/trending/TrendingActivity.kt | 18 +- .../components/trending/TrendingAdapter.kt | 44 +- .../trending}/TrendingDateViewHolder.kt | 2 +- .../components/trending/TrendingFragment.kt | 84 +--- .../trending/TrendingTagViewHolder.kt | 57 +++ .../trending/viewmodel/TrendingViewModel.kt | 74 ++-- .../tusky/entity/TrendingTagsResult.kt | 8 +- .../tusky/network/MastodonApi.kt | 2 +- .../keylesspalace/tusky/util/ViewDataUtils.kt | 23 +- .../com/keylesspalace/tusky/view/GraphView.kt | 22 +- .../tusky/viewdata/TrendingViewData.kt | 18 +- 13 files changed, 335 insertions(+), 480 deletions(-) delete mode 100644 app/src/main/java/com/keylesspalace/tusky/adapter/TrendingTagViewHolder.kt rename app/src/main/java/com/keylesspalace/tusky/{adapter => components/trending}/TrendingDateViewHolder.kt (96%) create mode 100644 app/src/main/java/com/keylesspalace/tusky/components/trending/TrendingTagViewHolder.kt 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=" ~~~~~~~"> <location file="src/main/java/com/keylesspalace/tusky/components/compose/ComposeViewModel.kt" - line="255" + line="254" column="21"/> </issue> @@ -311,7 +311,7 @@ errorLine2=" ^"> <location file="src/main/res/values-bg/strings.xml" - line="200" + line="199" column="5"/> </issue> @@ -355,7 +355,7 @@ errorLine2=" ^"> <location file="src/main/res/values-eu/strings.xml" - line="238" + line="237" column="5"/> </issue> @@ -366,7 +366,7 @@ errorLine2=" ^"> <location file="src/main/res/values-sl/strings.xml" - line="260" + line="259" column="5"/> </issue> @@ -388,7 +388,7 @@ errorLine2=" ^"> <location file="src/main/res/values-bn-rIN/strings.xml" - line="288" + line="287" column="5"/> </issue> @@ -399,7 +399,7 @@ errorLine2=" ^"> <location file="src/main/res/values-cs/strings.xml" - line="289" + line="288" column="5"/> </issue> @@ -410,7 +410,7 @@ errorLine2=" ^"> <location file="src/main/res/values-fr/strings.xml" - line="289" + line="288" column="5"/> </issue> @@ -432,7 +432,7 @@ errorLine2=" ^"> <location file="src/main/res/values-ru/strings.xml" - line="309" + line="308" column="5"/> </issue> @@ -454,7 +454,7 @@ errorLine2=" ^"> <location file="src/main/res/values-sl/strings.xml" - line="317" + line="316" column="5"/> </issue> @@ -465,7 +465,7 @@ errorLine2=" ^"> <location file="src/main/res/values-ga/strings.xml" - line="320" + line="319" column="5"/> </issue> @@ -476,7 +476,7 @@ errorLine2=" ^"> <location file="src/main/res/values-cs/strings.xml" - line="339" + line="338" column="5"/> </issue> @@ -487,7 +487,7 @@ errorLine2=" ^"> <location file="src/main/res/values-cs/strings.xml" - line="344" + line="343" column="5"/> </issue> @@ -498,7 +498,7 @@ errorLine2=" ^"> <location file="src/main/res/values-bn-rIN/strings.xml" - line="348" + line="347" column="5"/> </issue> @@ -509,7 +509,7 @@ errorLine2=" ^"> <location file="src/main/res/values-cs/strings.xml" - line="354" + line="353" column="5"/> </issue> @@ -520,7 +520,7 @@ errorLine2=" ^"> <location file="src/main/res/values-cs/strings.xml" - line="380" + line="379" column="5"/> </issue> @@ -531,7 +531,7 @@ errorLine2=" ^"> <location file="src/main/res/values-cs/strings.xml" - line="394" + line="393" column="5"/> </issue> @@ -542,7 +542,7 @@ errorLine2=" ^"> <location file="src/main/res/values-cs/strings.xml" - line="399" + line="398" column="5"/> </issue> @@ -553,7 +553,7 @@ errorLine2=" ^"> <location file="src/main/res/values-cs/strings.xml" - line="404" + line="403" column="5"/> </issue> @@ -564,7 +564,7 @@ errorLine2=" ^"> <location file="src/main/res/values-bg/strings.xml" - line="440" + line="439" column="5"/> </issue> @@ -575,7 +575,7 @@ errorLine2=" ^"> <location file="src/main/res/values-cs/strings.xml" - line="492" + line="491" column="5"/> </issue> @@ -586,7 +586,7 @@ errorLine2=" ^"> <location file="src/main/res/values-cs/strings.xml" - line="497" + line="496" column="5"/> </issue> @@ -597,7 +597,7 @@ errorLine2=" ^"> <location file="src/main/res/values-cs/strings.xml" - line="502" + line="501" column="5"/> </issue> @@ -784,7 +784,7 @@ errorLine2=" ^"> <location file="src/main/res/values-es/strings.xml" - line="258" + line="257" column="17"/> </issue> @@ -795,7 +795,7 @@ errorLine2=" ^"> <location file="src/main/res/values-nb-rNO/strings.xml" - line="327" + line="326" column="43"/> </issue> @@ -806,7 +806,7 @@ errorLine2=" ^"> <location file="src/main/res/values-it/strings.xml" - line="440" + line="439" column="114"/> </issue> @@ -817,7 +817,7 @@ errorLine2=" ^"> <location file="src/main/res/values-nb-rNO/strings.xml" - line="461" + line="460" column="86"/> </issue> @@ -828,7 +828,7 @@ errorLine2=" ^"> <location file="src/main/res/values-tr/strings.xml" - line="583" + line="581" column="293"/> </issue> @@ -839,7 +839,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="src/main/res/values-fa/strings.xml" - line="233" + line="232" column="9"/> </issue> @@ -850,7 +850,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="src/main/res/values-fa/strings.xml" - line="343" + line="342" column="9"/> </issue> @@ -894,7 +894,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="src/main/res/values/strings.xml" - line="554" + line="552" column="5"/> </issue> @@ -905,7 +905,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="src/main/res/values/strings.xml" - line="775" + line="773" column="5"/> </issue> @@ -960,7 +960,7 @@ errorLine2=" ^"> <location file="src/main/res/values-es/strings.xml" - line="256" + line="255" column="5"/> </issue> @@ -971,7 +971,7 @@ errorLine2=" ^"> <location file="src/main/res/values-it/strings.xml" - line="283" + line="282" column="5"/> </issue> @@ -982,7 +982,7 @@ errorLine2=" ^"> <location file="src/main/res/values-es/strings.xml" - line="306" + line="305" column="5"/> </issue> @@ -993,7 +993,7 @@ errorLine2=" ^"> <location file="src/main/res/values-es/strings.xml" - line="311" + line="310" column="5"/> </issue> @@ -1004,7 +1004,7 @@ errorLine2=" ^"> <location file="src/main/res/values-es/strings.xml" - line="321" + line="320" column="5"/> </issue> @@ -1015,7 +1015,7 @@ errorLine2=" ^"> <location file="src/main/res/values-pt-rBR/strings.xml" - line="329" + line="328" column="5"/> </issue> @@ -1026,7 +1026,7 @@ errorLine2=" ^"> <location file="src/main/res/values-it/strings.xml" - line="333" + line="332" column="5"/> </issue> @@ -1037,7 +1037,7 @@ errorLine2=" ^"> <location file="src/main/res/values-pt-rPT/strings.xml" - line="334" + line="333" column="5"/> </issue> @@ -1048,7 +1048,7 @@ errorLine2=" ^"> <location file="src/main/res/values-it/strings.xml" - line="338" + line="337" column="5"/> </issue> @@ -1059,7 +1059,7 @@ errorLine2=" ^"> <location file="src/main/res/values-pt-rBR/strings.xml" - line="342" + line="341" column="5"/> </issue> @@ -1070,7 +1070,7 @@ errorLine2=" ^"> <location file="src/main/res/values-es/strings.xml" - line="346" + line="345" column="5"/> </issue> @@ -1081,7 +1081,7 @@ errorLine2=" ^"> <location file="src/main/res/values-pt-rBR/strings.xml" - line="347" + line="346" column="5"/> </issue> @@ -1092,7 +1092,7 @@ errorLine2=" ^"> <location file="src/main/res/values-it/strings.xml" - line="348" + line="347" column="5"/> </issue> @@ -1103,7 +1103,7 @@ errorLine2=" ^"> <location file="src/main/res/values-es/strings.xml" - line="351" + line="350" column="5"/> </issue> @@ -1114,21 +1114,21 @@ errorLine2=" ^"> <location file="src/main/res/values-pt-rBR/strings.xml" + line="354" + column="5"/> + </issue> + + <issue + id="UnusedQuantity" + message="For language "es" (Spanish) the following quantities are not relevant: `many`" + errorLine1=" <plurals name="poll_timespan_minutes">" + errorLine2=" ^"> + <location + file="src/main/res/values-es/strings.xml" line="355" column="5"/> </issue> - <issue - id="UnusedQuantity" - message="For language "es" (Spanish) the following quantities are not relevant: `many`" - errorLine1=" <plurals name="poll_timespan_minutes">" - errorLine2=" ^"> - <location - file="src/main/res/values-es/strings.xml" - line="356" - column="5"/> - </issue> - <issue id="UnusedQuantity" message="For language "es" (Spanish) the following quantities are not relevant: `many`" @@ -1136,7 +1136,7 @@ errorLine2=" ^"> <location file="src/main/res/values-es/strings.xml" - line="361" + line="360" column="5"/> </issue> @@ -1147,7 +1147,7 @@ errorLine2=" ^"> <location file="src/main/res/values-es/strings.xml" - line="367" + line="366" column="5"/> </issue> @@ -1158,7 +1158,7 @@ errorLine2=" ^"> <location file="src/main/res/values-it/strings.xml" - line="377" + line="376" column="5"/> </issue> @@ -1169,7 +1169,7 @@ errorLine2=" ^"> <location file="src/main/res/values-pt-rBR/strings.xml" - line="378" + line="377" column="5"/> </issue> @@ -1180,7 +1180,7 @@ errorLine2=" ^"> <location file="src/main/res/values-pt-rPT/strings.xml" - line="381" + line="380" column="5"/> </issue> @@ -1191,7 +1191,7 @@ errorLine2=" ^"> <location file="src/main/res/values-pt-rPT/strings.xml" - line="386" + line="385" column="5"/> </issue> @@ -1202,7 +1202,7 @@ errorLine2=" ^"> <location file="src/main/res/values-pt-rBR/strings.xml" - line="388" + line="387" column="5"/> </issue> @@ -1213,7 +1213,7 @@ errorLine2=" ^"> <location file="src/main/res/values-pt-rBR/strings.xml" - line="393" + line="392" column="5"/> </issue> @@ -1224,7 +1224,7 @@ errorLine2=" ^"> <location file="src/main/res/values-pt-rPT/strings.xml" - line="395" + line="394" column="5"/> </issue> @@ -1235,7 +1235,7 @@ errorLine2=" ^"> <location file="src/main/res/values-pt-rBR/strings.xml" - line="398" + line="397" column="5"/> </issue> @@ -1246,7 +1246,7 @@ errorLine2=" ^"> <location file="src/main/res/values-pt-rBR/strings.xml" - line="403" + line="402" column="5"/> </issue> @@ -1257,7 +1257,7 @@ errorLine2=" ^"> <location file="src/main/res/values-it/strings.xml" - line="412" + line="411" column="5"/> </issue> @@ -1268,7 +1268,7 @@ errorLine2=" ^"> <location file="src/main/res/values-it/strings.xml" - line="417" + line="416" column="5"/> </issue> @@ -1279,7 +1279,7 @@ errorLine2=" ^"> <location file="src/main/res/values-it/strings.xml" - line="422" + line="421" column="5"/> </issue> @@ -1290,7 +1290,7 @@ errorLine2=" ^"> <location file="src/main/res/values-pt-rPT/strings.xml" - line="425" + line="424" column="5"/> </issue> @@ -1301,7 +1301,7 @@ errorLine2=" ^"> <location file="src/main/res/values-it/strings.xml" - line="427" + line="426" column="5"/> </issue> @@ -1312,7 +1312,7 @@ errorLine2=" ^"> <location file="src/main/res/values-pt-rPT/strings.xml" - line="430" + line="429" column="5"/> </issue> @@ -1323,7 +1323,7 @@ errorLine2=" ^"> <location file="src/main/res/values-pt-rPT/strings.xml" - line="440" + line="439" column="5"/> </issue> @@ -1334,7 +1334,7 @@ errorLine2=" ^"> <location file="src/main/res/values-pt-rPT/strings.xml" - line="445" + line="444" column="5"/> </issue> @@ -1345,7 +1345,7 @@ errorLine2=" ^"> <location file="src/main/res/values-pt-rPT/strings.xml" - line="450" + line="449" column="5"/> </issue> @@ -1356,7 +1356,7 @@ errorLine2=" ^"> <location file="src/main/res/values-pt-rPT/strings.xml" - line="455" + line="454" column="5"/> </issue> @@ -1367,7 +1367,7 @@ errorLine2=" ^"> <location file="src/main/res/values-it/strings.xml" - line="464" + line="463" column="5"/> </issue> @@ -1378,7 +1378,7 @@ errorLine2=" ^"> <location file="src/main/res/values-pt-rBR/strings.xml" - line="470" + line="469" column="5"/> </issue> @@ -1389,7 +1389,7 @@ errorLine2=" ^"> <location file="src/main/res/values-es/strings.xml" - line="479" + line="478" column="5"/> </issue> @@ -1400,7 +1400,7 @@ errorLine2=" ^"> <location file="src/main/res/values-pt-rBR/strings.xml" - line="494" + line="493" column="5"/> </issue> @@ -1411,7 +1411,7 @@ errorLine2=" ^"> <location file="src/main/res/values-es/strings.xml" - line="500" + line="499" column="5"/> </issue> @@ -1422,7 +1422,7 @@ errorLine2=" ^"> <location file="src/main/res/values-it/strings.xml" - line="505" + line="504" column="5"/> </issue> @@ -1433,7 +1433,7 @@ errorLine2=" ^"> <location file="src/main/res/values-pt-rPT/strings.xml" - line="516" + line="515" column="5"/> </issue> @@ -2548,17 +2548,6 @@ column="13"/> </issue> - <issue - id="UnusedResources" - message="The resource `R.string.status_count_one_plus` appears to be unused" - errorLine1=" <string name="status_count_one_plus">1+</string>" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="src/main/res/values/strings.xml" - line="415" - column="13"/> - </issue> - <issue id="UnusedResources" message="The resource `R.string.filter_dialog_remove_button` appears to be unused" @@ -2577,7 +2566,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> <location file="src/main/res/values/strings.xml" - line="499" + line="497" column="13"/> </issue> @@ -2588,7 +2577,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> <location file="src/main/res/values/strings.xml" - line="503" + line="501" column="13"/> </issue> @@ -2599,7 +2588,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> <location file="src/main/res/values/strings.xml" - line="504" + line="502" column="13"/> </issue> @@ -2610,7 +2599,7 @@ errorLine2=" ~~~~~~~~~~~~"> <location file="src/main/res/values/strings.xml" - line="505" + line="503" column="13"/> </issue> @@ -2621,7 +2610,7 @@ errorLine2=" ~~~~~~~~~~~~~~"> <location file="src/main/res/values/strings.xml" - line="506" + line="504" column="13"/> </issue> @@ -2632,7 +2621,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="src/main/res/values/strings.xml" - line="507" + line="505" column="13"/> </issue> @@ -2643,7 +2632,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> <location file="src/main/res/values/strings.xml" - line="508" + line="506" column="13"/> </issue> @@ -2654,7 +2643,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> <location file="src/main/res/values/strings.xml" - line="509" + line="507" column="13"/> </issue> @@ -2665,7 +2654,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="src/main/res/values/strings.xml" - line="510" + line="508" column="13"/> </issue> @@ -2676,7 +2665,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> <location file="src/main/res/values/strings.xml" - line="512" + line="510" column="13"/> </issue> @@ -2687,7 +2676,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="src/main/res/values/strings.xml" - line="597" + line="595" column="13"/> </issue> @@ -2698,7 +2687,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="src/main/res/values/strings.xml" - line="598" + line="596" column="13"/> </issue> @@ -2709,7 +2698,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~"> <location file="src/main/res/values/strings.xml" - line="612" + line="610" column="13"/> </issue> @@ -2720,7 +2709,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="src/main/res/values/strings.xml" - line="614" + line="612" column="13"/> </issue> @@ -2731,7 +2720,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="src/main/res/values/strings.xml" - line="615" + line="613" column="13"/> </issue> @@ -2742,7 +2731,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="src/main/res/values/strings.xml" - line="618" + line="616" column="13"/> </issue> @@ -2753,7 +2742,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> <location file="src/main/res/values/strings.xml" - line="663" + line="661" column="13"/> </issue> @@ -2764,7 +2753,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="src/main/res/values/strings.xml" - line="712" + line="710" column="13"/> </issue> @@ -2775,7 +2764,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="src/main/res/values/strings.xml" - line="718" + line="716" column="13"/> </issue> @@ -2786,7 +2775,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="src/main/res/values/strings.xml" - line="759" + line="757" column="13"/> </issue> @@ -2797,7 +2786,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="src/main/res/values/strings.xml" - line="796" + line="794" column="13"/> </issue> @@ -4157,7 +4146,7 @@ <issue id="SyntheticAccessor" message="Access to `private` method `getBinding` of class `MainActivity` requires synthetic accessor" - errorLine1=" binding.mainToolbar.title = tabs[tab.position].title(this@MainActivity)" + errorLine1=" binding.mainToolbar.title = tab.contentDescription" errorLine2=" ~~~~~~~"> <location file="src/main/java/com/keylesspalace/tusky/MainActivity.kt" @@ -4498,12 +4487,12 @@ <issue id="SyntheticAccessor" message="Access to `private` method `getBinding` of class `NotificationsFragment` requires synthetic accessor" - errorLine1=" binding.recyclerView.scrollBy(0, Utils.dpToPx(requireContext(), -30))" - errorLine2=" ~~~~~~~"> + errorLine1=" binding.recyclerView.scrollBy(0, Utils.dpToPx(requireContext(), -30))" + errorLine2=" ~~~~~~~"> <location file="src/main/java/com/keylesspalace/tusky/components/notifications/NotificationsFragment.kt" - line="214" - column="25"/> + line="215" + column="29"/> </issue> <issue @@ -4634,7 +4623,7 @@ errorLine2=" ~~~~~~~"> <location file="src/main/java/com/keylesspalace/tusky/components/trending/TrendingFragment.kt" - line="124" + line="81" column="21"/> </issue> @@ -4645,29 +4634,29 @@ errorLine2=" ~~~~~~~"> <location file="src/main/java/com/keylesspalace/tusky/components/trending/TrendingFragment.kt" - line="126" + line="83" column="29"/> </issue> <issue id="SyntheticAccessor" message="Access to `private` method `formatNumber` of class `Companion` requires synthetic accessor" - errorLine1=" binding.totalUsage.text = formatNumber(totalUsage)" + errorLine1=" binding.totalUsage.text = formatNumber(tagViewData.usage.sum())" errorLine2=" ~~~~~~~~~~~~"> <location - file="src/main/java/com/keylesspalace/tusky/adapter/TrendingTagViewHolder.kt" - line="42" + file="src/main/java/com/keylesspalace/tusky/components/trending/TrendingTagViewHolder.kt" + line="40" column="35"/> </issue> <issue id="SyntheticAccessor" message="Access to `private` method `formatNumber` of class `Companion` requires synthetic accessor" - errorLine1=" binding.totalUsage.text = formatNumber(totalUsage)" + errorLine1=" binding.totalUsage.text = formatNumber(tagViewData.usage.sum())" errorLine2=" ~~~~~~~~~~~~"> <location - file="src/main/java/com/keylesspalace/tusky/adapter/TrendingTagViewHolder.kt" - line="42" + file="src/main/java/com/keylesspalace/tusky/components/trending/TrendingTagViewHolder.kt" + line="40" column="35"/> </issue> @@ -4677,8 +4666,8 @@ errorLine1=" binding.totalAccounts.text = formatNumber(totalAccounts)" errorLine2=" ~~~~~~~~~~~~"> <location - file="src/main/java/com/keylesspalace/tusky/adapter/TrendingTagViewHolder.kt" - line="45" + file="src/main/java/com/keylesspalace/tusky/components/trending/TrendingTagViewHolder.kt" + line="43" column="38"/> </issue> @@ -4688,8 +4677,8 @@ errorLine1=" binding.totalAccounts.text = formatNumber(totalAccounts)" errorLine2=" ~~~~~~~~~~~~"> <location - file="src/main/java/com/keylesspalace/tusky/adapter/TrendingTagViewHolder.kt" - line="45" + file="src/main/java/com/keylesspalace/tusky/components/trending/TrendingTagViewHolder.kt" + line="43" column="38"/> </issue> @@ -4843,7 +4832,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="src/main/res/values-ja/strings.xml" - line="287" + line="286" column="37"/> </issue> @@ -4854,7 +4843,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="src/main/res/values-sl/strings.xml" - line="287" + line="286" column="37"/> </issue> @@ -4865,7 +4854,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="src/main/res/values-it/strings.xml" - line="314" + line="313" column="37"/> </issue> @@ -4876,7 +4865,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="src/main/res/values-ga/strings.xml" - line="345" + line="344" column="37"/> </issue> @@ -4920,7 +4909,7 @@ errorLine2=" ~~~~~~~~~~"> <location file="src/main/res/values-ko/strings.xml" - line="374" + line="373" column="54"/> </issue> @@ -5019,7 +5008,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> <location file="src/main/res/values-bn-rBD/strings.xml" - line="90" + line="89" column="32"/> </issue> @@ -5030,7 +5019,7 @@ errorLine2=" ~~~~~~~~~"> <location file="src/main/res/values-bn-rBD/strings.xml" - line="94" + line="93" column="43"/> </issue> @@ -5041,7 +5030,7 @@ errorLine2=" ~~~~~~~~~"> <location file="src/main/res/values-bn-rBD/strings.xml" - line="95" + line="94" column="43"/> </issue> @@ -5052,7 +5041,7 @@ errorLine2=" ~~~~~~~~~"> <location file="src/main/res/values-bn-rBD/strings.xml" - line="96" + line="95" column="41"/> </issue> @@ -5063,7 +5052,7 @@ errorLine2=" ~~~~~~~~~"> <location file="src/main/res/values-bn-rBD/strings.xml" - line="97" + line="96" column="40"/> </issue> @@ -5074,18 +5063,18 @@ errorLine2=" ~~~~~~~~~"> <location file="src/main/res/values-bn-rBD/strings.xml" - line="98" + line="97" column="41"/> </issue> <issue id="TypographyQuotes" message="Replace straight quotes (") with directional quotes (“”, &#8220; and &#8221;) ?" - errorLine1=" <string name="dialog_whats_an_instance">কোনও উদাহরণের ঠিকানা বা ডোমেন এখানে প্রবেশ করা যেতে পারে যেমন mastodon.social, icosahedron.website, social.tchncs.de, এবং &lt;a href=\"https://instances.social\"&gt; আরও! &lt;/a&gt; " + errorLine1=" <string name="dialog_whats_an_instance">কোনও উদাহরণের ঠিকানা বা ডোমেন এখানে প্রবেশ করা যেতে পারে যেমন mastodon.social, icosahedron.website, social.tchncs.de, এবং &lt;a href=\"https://instances.social\"&gt; আরও! &lt;/a&gt;" errorLine2=" ^"> <location file="src/main/res/values-bn-rBD/strings.xml" - line="184" + line="183" column="45"/> </issue> @@ -5118,7 +5107,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~"> <location file="src/main/res/values-bn-rBD/strings.xml" - line="224" + line="223" column="35"/> </issue> @@ -5129,7 +5118,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> <location file="src/main/res/values-bn-rBD/strings.xml" - line="226" + line="225" column="35"/> </issue> @@ -5140,7 +5129,7 @@ errorLine2=" ^"> <location file="src/main/res/values-bg/strings.xml" - line="264" + line="263" column="45"/> </issue> @@ -5151,7 +5140,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="src/main/res/values-bn-rBD/strings.xml" - line="342" + line="341" column="45"/> </issue> @@ -5162,7 +5151,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> <location file="src/main/res/values-bn-rBD/strings.xml" - line="377" + line="376" column="43"/> </issue> @@ -5173,7 +5162,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="src/main/res/values-bn-rBD/strings.xml" - line="379" + line="378" column="40"/> </issue> @@ -5184,7 +5173,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~"> <location file="src/main/res/values-bn-rBD/strings.xml" - line="387" + line="386" column="44"/> </issue> @@ -5195,17 +5184,10 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="src/main/res/values/strings.xml" - line="745" + line="743" column="55"/> </issue> - <issue - id="ConvertToWebp" - message="One or more images in this project can be converted to the WebP format which typically results in smaller file sizes, even for lossless conversion"> - <location - file="src/blue/res/mipmap-xxxhdpi/ic_launcher.png"/> - </issue> - <issue id="SelectableText" message="Consider making the text value selectable by specifying `android:textIsSelectable="true"`" @@ -5675,7 +5657,7 @@ errorLine2=" ~~~~~~~~"> <location file="src/main/res/layout/item_follow.xml" - line="57" + line="59" column="6"/> </issue> @@ -5686,7 +5668,7 @@ errorLine2=" ~~~~~~~~"> <location file="src/main/res/layout/item_follow_request.xml" - line="10" + line="11" column="6"/> </issue> @@ -5697,7 +5679,7 @@ errorLine2=" ~~~~~~~~"> <location file="src/main/res/layout/item_follow_request.xml" - line="47" + line="49" column="6"/> </issue> @@ -5708,7 +5690,7 @@ errorLine2=" ~~~~~~~~"> <location file="src/main/res/layout/item_follow_request.xml" - line="63" + line="65" column="6"/> </issue> @@ -6192,7 +6174,7 @@ errorLine2=" ~~~~~~~~"> <location file="src/main/res/layout/item_status_notification.xml" - line="11" + line="12" column="6"/> </issue> @@ -6203,7 +6185,7 @@ errorLine2=" ~~~~~~~~"> <location file="src/main/res/layout/item_status_notification.xml" - line="48" + line="49" column="6"/> </issue> @@ -6214,7 +6196,7 @@ errorLine2=" ~~~~~~~~"> <location file="src/main/res/layout/item_status_notification.xml" - line="69" + line="71" column="6"/> </issue> @@ -6225,7 +6207,7 @@ errorLine2=" ~~~~~~~~"> <location file="src/main/res/layout/item_status_notification.xml" - line="83" + line="85" column="6"/> </issue> @@ -6588,7 +6570,7 @@ errorLine2=" ~~~~~~~~~"> <location file="src/main/res/layout/item_status_notification.xml" - line="41" + line="42" column="6"/> </issue> @@ -6702,28 +6684,6 @@ column="9"/> </issue> - <issue - id="RtlSymmetry" - message="When you define `paddingStart` you should probably also define `paddingEnd` for right-to-left symmetry" - errorLine1=" android:paddingStart="16dp"" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> - <location - file="src/main/res/layout/item_follow_request.xml" - line="7" - column="5"/> - </issue> - - <issue - id="RtlSymmetry" - message="When you define `paddingStart` you should probably also define `paddingEnd` for right-to-left symmetry" - errorLine1=" android:paddingStart="28dp"" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> - <location - file="src/main/res/layout/item_follow_request.xml" - line="19" - column="9"/> - </issue> - <issue id="RtlSymmetry" message="When you define `paddingStart` you should probably also define `paddingEnd` for right-to-left symmetry" @@ -6753,7 +6713,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> <location file="src/main/res/layout/item_status_notification.xml" - line="21" + line="22" column="9"/> </issue> @@ -7369,7 +7329,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~"> <location file="src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java" - line="485" + line="492" column="19"/> </issue> @@ -7380,7 +7340,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> <location file="src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java" - line="487" + line="494" column="19"/> </issue> @@ -7391,7 +7351,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~"> <location file="src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java" - line="578" + line="585" column="34"/> </issue> @@ -7402,7 +7362,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> <location file="src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java" - line="579" + line="586" column="40"/> </issue> @@ -7413,7 +7373,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> <location file="src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java" - line="624" + line="631" column="39"/> </issue> @@ -7424,7 +7384,7 @@ errorLine2=" ~~~~~~"> <location file="src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java" - line="625" + line="632" column="39"/> </issue> @@ -7435,7 +7395,7 @@ errorLine2=" ~~~~~~"> <location file="src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java" - line="626" + line="633" column="39"/> </issue> @@ -7446,7 +7406,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> <location file="src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java" - line="627" + line="634" column="33"/> </issue> @@ -7457,7 +7417,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> <location file="src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java" - line="750" + line="753" column="33"/> </issue> @@ -7468,7 +7428,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> <location file="src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java" - line="750" + line="753" column="71"/> </issue> @@ -7479,7 +7439,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> <location file="src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java" - line="751" + line="754" column="33"/> </issue> @@ -7490,7 +7450,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~"> <location file="src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java" - line="844" + line="846" column="55"/> </issue> @@ -7501,7 +7461,7 @@ errorLine2=" ~~~~~~~~~~~~"> <location file="src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java" - line="919" + line="921" column="22"/> </issue> @@ -7512,7 +7472,7 @@ errorLine2=" ~~~~~~~"> <location file="src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java" - line="919" + line="921" column="60"/> </issue> @@ -7523,7 +7483,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~"> <location file="src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java" - line="919" + line="921" column="77"/> </issue> @@ -7534,7 +7494,7 @@ errorLine2=" ~~~~~~~~~~~~"> <location file="src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java" - line="968" + line="970" column="15"/> </issue> @@ -7545,7 +7505,7 @@ errorLine2=" ~~~~~~~"> <location file="src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java" - line="968" + line="970" column="40"/> </issue> @@ -7556,7 +7516,7 @@ errorLine2=" ~~~~~~~~~~~~"> <location file="src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java" - line="977" + line="979" column="15"/> </issue> @@ -7567,7 +7527,7 @@ errorLine2=" ~~~~~~~"> <location file="src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java" - line="977" + line="979" column="43"/> </issue> @@ -7578,7 +7538,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> <location file="src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java" - line="1078" + line="1080" column="19"/> </issue> @@ -7589,7 +7549,7 @@ errorLine2=" ~~~~~~~~~~~~"> <location file="src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java" - line="1080" + line="1082" column="19"/> </issue> @@ -7600,7 +7560,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> <location file="src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java" - line="1081" + line="1083" column="19"/> </issue> @@ -7611,7 +7571,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> <location file="src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java" - line="1082" + line="1084" column="19"/> </issue> 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 <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) - } -} 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<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) } } 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<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 } } } 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 <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 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<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() } } 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 <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 + ) + } +} 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<TrendingTagHistory>, - val following: Boolean + val history: List<TrendingTagHistory> ) /** 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<HashTag> @GET("api/v1/trends/tags") - suspend fun trendingTags(): Response<List<TrendingTag>> + suspend fun trendingTags(): NetworkResult<List<TrendingTag>> } 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<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 + ) + } } 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<Long>, + val accounts: List<Long>, + val maxTrendingValue: Long ) : TrendingViewData() { override val id: String - get() = tag.name + get() = name } - - fun asTagOrNull() = this as? Tag }