Refactor notifications to Kotlin & paging (#4026)

This refactors the NotificationsFragment and related classes to Kotlin &
paging.
While trying to preserve as much of the original behavior as possible,
this adds the following improvements as well:
- The "show notifications filter" preference was added again
- The "load more" button now has a background ripple effect when clicked
- The "legal" report category of Mastodon 4.2 is now supported in report
notifications
- Unknown notifications now display "unknown notification type" instead
of an empty line

Other code quality improvements:
- All views from xml layouts are now referenced via ViewBindings
- the classes responsible for showing system notifications were moved to
a new package `systemnotifications` while the classes from this
refactoring are in `notifications`
- the id of the local Tusky account is now called `tuskyAccountId` in
all places I could find

closes https://github.com/tuskyapp/Tusky/issues/3429

---------

Co-authored-by: Zongle Wang <wangzongler@gmail.com>
This commit is contained in:
Konrad Pozniak 2024-05-03 18:27:10 +02:00 committed by GitHub
commit b2c0b18c8e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
121 changed files with 6992 additions and 4654 deletions

View file

@ -1,20 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/notification_report"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingLeft="14dp"
android:paddingRight="14dp">
android:paddingStart="14dp"
android:paddingEnd="14dp"
android:paddingBottom="14dp">
<TextView
android:id="@+id/notification_top_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
android:layout_marginTop="8dp"
android:drawablePadding="10dp"
android:ellipsize="end"
@ -23,19 +22,23 @@
android:paddingStart="28dp"
android:textColor="?android:textColorSecondary"
android:textSize="?attr/status_text_medium"
app:drawableStartCompat="@drawable/ic_flag_24dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="Someone reported someone else" />
<ImageView
android:id="@+id/notification_reportee_avatar"
android:layout_width="48dp"
android:layout_height="48dp"
app:layout_constraintTop_toBottomOf="@id/notification_top_text"
app:layout_constraintLeft_toLeftOf="parent"
android:layout_marginTop="10dp"
android:layout_marginEnd="14dp"
android:layout_marginBottom="14dp"
android:contentDescription="@string/action_view_profile"
android:paddingEnd="12dp"
android:paddingBottom="12dp"
android:scaleType="centerCrop"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/notification_top_text"
tools:ignore="RtlHardcoded,RtlSymmetry"
tools:src="@drawable/avatar_default" />
@ -44,40 +47,38 @@
android:layout_width="24dp"
android:layout_height="24dp"
android:contentDescription="@string/action_view_profile"
app:layout_constraintRight_toRightOf="@id/notification_reportee_avatar"
app:layout_constraintBottom_toBottomOf="@id/notification_reportee_avatar"
/>
app:layout_constraintEnd_toEndOf="@id/notification_reportee_avatar"
tools:src="@drawable/avatar_default" />
<TextView
android:id="@+id/notification_summary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="-4dp"
android:layout_marginStart="14dp"
app:layout_constraintTop_toTopOf="@id/notification_reportee_avatar"
app:layout_constraintLeft_toRightOf="@id/notification_reporter_avatar"
android:importantForAccessibility="no"
android:layout_marginTop="6dp"
android:hyphenationFrequency="full"
android:importantForAccessibility="no"
android:lineSpacingMultiplier="1.1"
android:textColor="?android:textColorTertiary"
android:textSize="?attr/status_text_medium"
tools:ignore="NegativeMargin"
tools:text="30 minutes ago - 2 posts" />
app:layout_constraintStart_toEndOf="@id/notification_reporter_avatar"
app:layout_constraintTop_toBottomOf="@id/notification_top_text"
tools:text="30 minutes ago · 2 posts attached" />
<TextView
android:id="@+id/notification_category"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="14dp"
app:layout_constraintTop_toBottomOf="@id/notification_summary"
app:layout_constraintLeft_toRightOf="@id/notification_reporter_avatar"
android:importantForAccessibility="no"
android:hyphenationFrequency="full"
android:importantForAccessibility="no"
android:lineSpacingMultiplier="1.1"
android:paddingBottom="10dp"
android:textColor="?android:textColorTertiary"
android:textSize="?attr/status_text_medium"
android:textStyle="bold"
app:layout_constraintStart_toEndOf="@id/notification_reporter_avatar"
app:layout_constraintTop_toBottomOf="@id/notification_summary"
tools:text="Spam" />
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -1,51 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
The attributes are set to get a specific behaviour:
1. When the button is clicked, the icon should appear in the middle of the button,
with android:layout_width="wrap_content".
If this was "match_parent" the button would be the width of the FrameLayout, and
the icon would appear to the left.
2. The user should be able to click anywhere in the layout to start loading more
items.
Because the button is not full width because of #1, set android:clickable="false"
on the button and "true" on the parent so button clicks propagate to the parent
(which hosts the click listener in PlaceholderViewHolder).
For a11y, the parent sets android:focusable="true".
3. The user gets feedback that the button has been clicked with a circular progress
spinner, there's no need for the ripple effect, so disable it, by setting both
the background and rippleColor to transparent.
In theory you only need to set app:rippleColor. In testing, that works as
expected in the emulator (at API level 30), but did not work on a physical
device (Pixel 4a). It was necessary to set the background color as well.
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="72dp"
android:background="@color/dividerColorOther"
android:clickable="true"
android:focusable="true">
android:background="@color/dividerColorOther">
<com.google.android.material.button.MaterialButton
android:id="@+id/button_load_more"
style="@style/TuskyButton.TextButton.Icon"
android:layout_width="wrap_content"
<Button
android:id="@+id/loadMoreButton"
style="@style/TuskyButton.TextButton"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal"
android:clickable="false"
app:iconGravity="textStart"
android:background="@android:color/transparent"
app:rippleColor="@android:color/transparent"
android:insetTop="0dp"
android:insetBottom="0dp"
android:text="@string/load_more_placeholder_text"
android:textStyle="bold"
android:textSize="?attr/status_text_large" />
android:textSize="?attr/status_text_large"
android:textStyle="bold" />
<ProgressBar
android:id="@+id/loadMoreProgressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center" />
</FrameLayout>

View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- paddingStart = 14dp+48dp+14dp = 76dp to align with avatars of other notifications -->
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingVertical="8dp"
android:lineSpacingMultiplier="1.1"
android:textSize="?attr/status_text_medium"
android:paddingStart="76dp"
android:paddingEnd="8dp"
android:text="@string/unknown_notification_type"/>

View file

@ -686,7 +686,7 @@
<string name="pref_title_enable_swipe_for_tabs">Enable swipe gesture to switch between tabs</string>
<string name="pref_title_show_stat_inline">Show post statistics in timeline</string>
<string name="pref_title_show_notifications_filter">Show Notifications filter</string>
<string name="create_poll_title">Poll</string>
<string name="label_duration">Duration</string>
@ -718,7 +718,6 @@
<string name="warning_scheduling_interval">Mastodon has a minimum scheduling interval of 5 minutes.</string>
<string name="pref_title_show_self_username">Show username in toolbars</string>
<string name="pref_title_show_cards_in_timelines">Show link previews in timelines</string>
<string name="pref_title_show_notifications_filter">Show Notifications filter</string>
<string name="pref_title_confirm_reblogs">Show confirmation before boosting</string>
<string name="pref_title_confirm_favourites">Show confirmation before favoriting</string>
<string name="pref_title_hide_top_toolbar">Hide the title of the top toolbar</string>
@ -770,6 +769,7 @@
<string name="report_category_violation">Rule violation</string>
<string name="report_category_spam">Spam</string>
<string name="report_category_legal">Legal</string>
<string name="report_category_other">Other</string>
<string name="action_unfollow_hashtag_format">Unfollow #%1$s?</string>
@ -847,8 +847,11 @@
<string name="dialog_delete_filter_text">Delete filter \'%1$s\'?"</string>
<string name="dialog_delete_filter_positive_action">Delete</string>
<string name="dialog_save_profile_changes_message">Do you want to save your profile changes?</string>
<string name="list_reply_policy_none">No one</string>
<string name="list_reply_policy_list">Members of the list</string>
<string name="list_reply_policy_followed">Any followed user</string>
<string name="list_reply_policy_label">Show replies to</string>
<string name="unknown_notification_type">Unknown notification type</string>
</resources>

View file

@ -133,12 +133,6 @@
<item name="android:letterSpacing">0</item>
</style>
<style name="TuskyButton.TextButton.Icon">
<!-- Buttons with icons need additional padding -->
<item name="android:paddingLeft">@dimen/m3_btn_icon_btn_padding_left</item>
<item name="android:paddingRight">@dimen/m3_btn_icon_btn_padding_right</item>
</style>
<style name="TuskyTextInput" parent="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.Dense">
<item name="boxStrokeColor">@color/text_input_layout_box_stroke_color</item>
<item name="android:textColorHint">?android:attr/textColorTertiary</item>