Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor notifications to Kotlin & paging #4026

Merged
merged 105 commits into from
May 3, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
105 commits
Select commit Hold shift + click to select a range
92cb7b6
rename notifications package to systemnotifications
connyduck Sep 18, 2023
2a55757
add the "showNotificationsFilter" preference back
connyduck Sep 18, 2023
cfc8a40
Rename .java to .kt
connyduck Sep 20, 2023
075f76b
add new NotificationsFragment, implement NotificationsPagingAdapter
connyduck Sep 20, 2023
6dbd7c1
notis
connyduck Oct 30, 2023
be54fe4
Merge branch 'develop' into refactor_notifications
connyduck Oct 30, 2023
a1c1e76
support filters
connyduck Oct 31, 2023
9a821f1
Merge branch 'develop' into refactor_notifications
connyduck Dec 23, 2023
e8e0572
Merge branch 'develop' into refactor_notifications
connyduck Mar 12, 2024
16267a6
revert schema files
connyduck Mar 12, 2024
47f2049
fix build
connyduck Mar 12, 2024
bdeb899
revert schema files
connyduck Mar 12, 2024
9b4becc
new hometimeline db schema
connyduck Mar 21, 2024
61a1932
use same entities for home timeline and notifications
connyduck Mar 26, 2024
f229a41
update indizes and database cleanup
connyduck Mar 26, 2024
824c6a4
fix room warnings
connyduck Mar 26, 2024
d3b5bfe
fix codeformatting in some places
connyduck Mar 26, 2024
aab880d
implement some of the missing fragment functionality
connyduck Mar 26, 2024
bedfe01
add fetching status from db back into ViewThreadViewModel
connyduck Mar 26, 2024
17ce0be
make clearing notifications work again
connyduck Mar 26, 2024
88d79cd
add preference change listener back
connyduck Mar 26, 2024
6980bb3
Merge branch 'develop' into refactor_notifications
connyduck Mar 26, 2024
4ce685b
improve menu/filter bar
connyduck Mar 26, 2024
bf3d55c
add filter functionality back
connyduck Mar 26, 2024
f077425
remove unused code
connyduck Mar 26, 2024
f135672
add missing license headers
connyduck Mar 26, 2024
42f003b
Merge branch 'develop' into refactor_notifications
connyduck Mar 26, 2024
e5f6d83
add loading property to HomeTimelineData
connyduck Mar 26, 2024
b2c3007
fix tests
connyduck Mar 27, 2024
5a82070
remove runBlocking from tests
connyduck Mar 27, 2024
a9cee65
Merge branch 'develop' into refactor_notifications
connyduck Mar 27, 2024
5f4c476
close cursors in test
connyduck Mar 27, 2024
76bee61
Update app/src/main/java/com/keylesspalace/tusky/components/notificat…
connyduck Mar 27, 2024
e14c12e
make follow requests work again
connyduck Mar 28, 2024
1c26a02
Merge branch 'develop' into refactor_notifications
connyduck Mar 28, 2024
4cd278f
cleanup code in NotificationTypeMappers
connyduck Mar 28, 2024
44a9814
improve TimelineDao
connyduck Mar 28, 2024
f7d440e
Merge branch 'develop' into refactor_notifications
connyduck Mar 29, 2024
b2eca59
add comments to onMute/onBlock in NotificationsFragment
connyduck Mar 30, 2024
5e95fab
implement NotificationsFragment.removeItem
connyduck Mar 30, 2024
c6c091b
implement translations
connyduck Mar 30, 2024
ab5b086
implement load more
connyduck Mar 30, 2024
4615bfd
fix timeline load more
connyduck Mar 30, 2024
e0b673a
update reading order when pref changed in NotificationsFragment
connyduck Mar 31, 2024
af2add1
use NotificationsDao.delete in the appropriate places
connyduck Mar 31, 2024
4501e3d
some code cleanup
connyduck Mar 31, 2024
40d017a
update reading order when pref changed in NotificationsViewData
connyduck Mar 31, 2024
efa3ec0
adapt cache updating
connyduck Apr 1, 2024
d1c28ea
cleanup notification cache when logging out
connyduck Apr 1, 2024
4547d08
reorganize daos
connyduck Apr 1, 2024
9a41474
reorganize db entities
connyduck Apr 1, 2024
6da0112
some code cleanup
connyduck Apr 1, 2024
3f58187
regenerate lint-baseline.xml
connyduck Apr 1, 2024
924a115
fix tests
connyduck Apr 1, 2024
011d795
Merge branch 'develop' into refactor_notifications
connyduck Apr 1, 2024
6cfe884
create database migrations
connyduck Apr 2, 2024
96048cd
Merge branch 'develop' into refactor_notifications
connyduck Apr 2, 2024
ff277e1
implement click handler in StatusNotificationViewHolder
connyduck Apr 3, 2024
bb19a82
fix proguard-rules.pro
connyduck Apr 4, 2024
017c7ec
fix bugs related to boosted posts
connyduck Apr 4, 2024
13014ab
add tests for removing items by user, fix query
connyduck Apr 5, 2024
1c93c06
fix load more on the home timeline
connyduck Apr 5, 2024
5895539
fix crash when showing filtered status in home timeline
connyduck Apr 5, 2024
86db3d8
fix boosted posts losing state on refresh
connyduck Apr 5, 2024
1155915
Merge branch 'develop' into refactor_notifications
connyduck Apr 6, 2024
e3696a1
remove unused method
connyduck Apr 6, 2024
f1f3ed8
don't override equals / hashcode for Notification
connyduck Apr 6, 2024
50a6801
add CleanupDaoTest and NotificationMocker, fix cleanup bug
connyduck Apr 7, 2024
6d4976f
delete unused code
connyduck Apr 7, 2024
26b7e04
add NotificationsDaoTest
connyduck Apr 9, 2024
8032e9e
add NotificationsRemoteMediatorTest
connyduck Apr 10, 2024
077036f
Merge branch 'develop' into refactor_notifications
connyduck Apr 10, 2024
ad9b7a2
regenerate lint-baseline.xml
connyduck Apr 10, 2024
55af4a3
improve report notification layout
connyduck Apr 11, 2024
c9308ab
remove unused imports
connyduck Apr 11, 2024
654e522
improve report notification layout
connyduck Apr 12, 2024
4f14b4e
revert unnecessary change in StatusViewHolder
connyduck Apr 12, 2024
b04f2ee
remove duplicate notification type to name mapping
connyduck Apr 12, 2024
5ac34f6
various code cleanups
connyduck Apr 12, 2024
194c633
save last notification id to account
connyduck Apr 12, 2024
2cb9957
Merge branch 'develop' into refactor_notifications
connyduck Apr 14, 2024
843463e
Merge branch 'develop' into refactor_notifications
connyduck Apr 17, 2024
0e8b0c3
add jump-to-top on reselect back into NotificationsFragment
connyduck Apr 17, 2024
a6bc841
make NotificationViewData implementations data classes
connyduck Apr 17, 2024
eaaf865
use Kotlin isEmpty() instead of TextUtils.isEmpty
connyduck Apr 17, 2024
98098a1
get context from view instead of fragment when possible
connyduck Apr 17, 2024
0cb0721
move listener setup to constructor of PlaceholderViewHolder
connyduck Apr 17, 2024
0dde036
remove unused import
connyduck Apr 17, 2024
cbd9f06
fix hasSpoiler condition in StatusNotificationViewHolder
connyduck Apr 18, 2024
0a5714a
move json de/serialization completely to room converter
connyduck Apr 18, 2024
c8bf780
Merge branch 'develop' into refactor_notifications
connyduck Apr 18, 2024
ed37bb2
shorten some code in NotificationsFragment
connyduck Apr 18, 2024
9882c27
use start/end instead of left/right in item_report_notification.xml
connyduck Apr 18, 2024
7186d2e
rename mock* to fake*
connyduck Apr 18, 2024
5ba10f2
refactor respondToFollowRequest to return Deferred
connyduck Apr 18, 2024
135e619
Merge branch 'develop' into refactor_notifications
connyduck Apr 29, 2024
e6a042d
put back notification clearing and timestamp updating
connyduck Apr 29, 2024
d74dd63
Merge branch 'develop' into refactor_notifications
connyduck May 3, 2024
c5633de
change payloads param to be non-null
connyduck May 3, 2024
a78433a
use SpannableString instead of SpannableStringBuilder
connyduck May 3, 2024
a6e9fc1
CleanupDao -> DatabaseCleaner
connyduck May 3, 2024
3581e9a
improve NotificationViewData
connyduck May 3, 2024
b3a8978
don't specify executor when mapping/filtering pagingData
connyduck May 3, 2024
7f2e403
refresh notifications directly in viewmodel when responding to follow…
connyduck May 3, 2024
abf0008
refresh notifications directly in viewmodel when responding to follow…
connyduck May 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
400 changes: 398 additions & 2 deletions app/schemas/com.keylesspalace.tusky.db.AppDatabase/53.json

Large diffs are not rendered by default.

1,016 changes: 0 additions & 1,016 deletions app/schemas/com.keylesspalace.tusky.db.AppDatabase/54.json

This file was deleted.

8 changes: 4 additions & 4 deletions app/src/main/java/com/keylesspalace/tusky/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,13 @@ import com.keylesspalace.tusky.components.compose.ComposeActivity
import com.keylesspalace.tusky.components.compose.ComposeActivity.Companion.canHandleMimeType
import com.keylesspalace.tusky.components.drafts.DraftsActivity
import com.keylesspalace.tusky.components.login.LoginActivity
import com.keylesspalace.tusky.components.notifications.NotificationHelper
import com.keylesspalace.tusky.components.notifications.disableAllNotifications
import com.keylesspalace.tusky.components.notifications.enablePushNotificationsWithFallback
import com.keylesspalace.tusky.components.notifications.showMigrationNoticeIfNecessary
import com.keylesspalace.tusky.components.preference.PreferencesActivity
import com.keylesspalace.tusky.components.scheduled.ScheduledStatusActivity
import com.keylesspalace.tusky.components.search.SearchActivity
import com.keylesspalace.tusky.components.systemnotifications.NotificationHelper
import com.keylesspalace.tusky.components.systemnotifications.disableAllNotifications
import com.keylesspalace.tusky.components.systemnotifications.enablePushNotificationsWithFallback
import com.keylesspalace.tusky.components.systemnotifications.showMigrationNoticeIfNecessary
import com.keylesspalace.tusky.components.trending.TrendingActivity
import com.keylesspalace.tusky.databinding.ActivityMainBinding
import com.keylesspalace.tusky.db.AccountEntity
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/java/com/keylesspalace/tusky/TabData.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import androidx.fragment.app.Fragment
import com.keylesspalace.tusky.components.conversation.ConversationsFragment
import com.keylesspalace.tusky.components.notifications.NotificationsFragment
import com.keylesspalace.tusky.components.timeline.TimelineFragment
import com.keylesspalace.tusky.components.timeline.viewmodel.TimelineViewModel
import com.keylesspalace.tusky.components.trending.TrendingTagsFragment
import com.keylesspalace.tusky.fragment.NotificationsFragment
import java.util.Objects

/** this would be a good case for a sealed class, but that does not work nice with Room */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import androidx.work.ExistingPeriodicWorkPolicy
import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkManager
import autodispose2.AutoDisposePlugins
import com.keylesspalace.tusky.components.notifications.NotificationHelper
import com.keylesspalace.tusky.components.systemnotifications.NotificationHelper
import com.keylesspalace.tusky.di.AppInjector
import com.keylesspalace.tusky.settings.AppTheme
import com.keylesspalace.tusky.settings.NEW_INSTALL_SCHEMA_VERSION
Expand Down Expand Up @@ -132,12 +132,6 @@ class TuskyApplication : Application(), HasAndroidInjector {
editor.remove(PrefKeys.MEDIA_PREVIEW_ENABLED)
}

if (oldVersion < 2023072401) {
// The notifications filter / clear options are shown on a menu, not a separate bar,
// the preference to display them is not needed.
editor.remove(PrefKeys.Deprecated.SHOW_NOTIFICATIONS_FILTER)
}

if (oldVersion != NEW_INSTALL_SCHEMA_VERSION && oldVersion < 2023082301) {
// Default value for appTheme is now THEME_SYSTEM. If the user is upgrading and
// didn't have an explicit preference set use the previous default, so the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,12 @@ import android.text.Spanned
import android.text.style.StyleSpan
import androidx.recyclerview.widget.RecyclerView
import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.components.notifications.NotificationsViewHolder
import com.keylesspalace.tusky.databinding.ItemFollowRequestBinding
import com.keylesspalace.tusky.entity.TimelineAccount
import com.keylesspalace.tusky.interfaces.AccountActionListener
import com.keylesspalace.tusky.interfaces.LinkListener
import com.keylesspalace.tusky.util.StatusDisplayOptions
import com.keylesspalace.tusky.util.emojify
import com.keylesspalace.tusky.util.hide
import com.keylesspalace.tusky.util.loadAvatar
Expand All @@ -33,12 +35,21 @@ import com.keylesspalace.tusky.util.setClickableText
import com.keylesspalace.tusky.util.show
import com.keylesspalace.tusky.util.unicodeWrap
import com.keylesspalace.tusky.util.visible
import com.keylesspalace.tusky.viewdata.NotificationViewData

class FollowRequestViewHolder(
private val binding: ItemFollowRequestBinding,
private val linkListener: LinkListener,
private val showHeader: Boolean
) : RecyclerView.ViewHolder(binding.root) {
) : RecyclerView.ViewHolder(binding.root), NotificationsViewHolder {

override fun bind(
viewData: NotificationViewData.Concrete,
payloads: List<*>?,
statusDisplayOptions: StatusDisplayOptions
) {
TODO("Not yet implemented")
}

fun setupWithAccount(
account: TimelineAccount,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,10 @@

import com.bumptech.glide.Glide;
import com.keylesspalace.tusky.R;
import com.keylesspalace.tusky.components.notifications.ReportNotificationViewHolder;
import com.keylesspalace.tusky.databinding.ItemFollowRequestBinding;
import com.keylesspalace.tusky.databinding.ItemReportNotificationBinding;
import com.keylesspalace.tusky.databinding.ItemStatusPlaceholderBinding;
import com.keylesspalace.tusky.entity.Emoji;
import com.keylesspalace.tusky.entity.Notification;
import com.keylesspalace.tusky.entity.Status;
Expand All @@ -59,7 +61,7 @@
import com.keylesspalace.tusky.util.StatusDisplayOptions;
import com.keylesspalace.tusky.util.StringUtils;
import com.keylesspalace.tusky.util.TimestampUtils;
import com.keylesspalace.tusky.viewdata.NotificationViewData;
import com.keylesspalace.tusky.viewdata.NotificationViewData2;
import com.keylesspalace.tusky.viewdata.StatusViewData;

import java.util.Date;
Expand Down Expand Up @@ -92,11 +94,11 @@ public interface AdapterDataSource<T> {
private final StatusActionListener statusListener;
private final NotificationActionListener notificationActionListener;
private final AccountActionListener accountActionListener;
private final AdapterDataSource<NotificationViewData> dataSource;
private final AdapterDataSource<NotificationViewData2> dataSource;
private final AbsoluteTimeFormatter absoluteTimeFormatter = new AbsoluteTimeFormatter();

public NotificationsAdapter(String accountId,
AdapterDataSource<NotificationViewData> dataSource,
AdapterDataSource<NotificationViewData2> dataSource,
StatusDisplayOptions statusDisplayOptions,
StatusActionListener statusListener,
NotificationActionListener notificationActionListener,
Expand Down Expand Up @@ -137,11 +139,11 @@ public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int
case VIEW_TYPE_PLACEHOLDER: {
View view = inflater
.inflate(R.layout.item_status_placeholder, parent, false);
return new PlaceholderViewHolder(view);
return new PlaceholderViewHolder(ItemStatusPlaceholderBinding.inflate(inflater, parent, false), statusListener);
}
case VIEW_TYPE_REPORT: {
ItemReportNotificationBinding binding = ItemReportNotificationBinding.inflate(inflater, parent, false);
return new ReportNotificationViewHolder(binding);
return new ReportNotificationViewHolder(binding, notificationActionListener);
}
default:
case VIEW_TYPE_UNKNOWN: {
Expand Down Expand Up @@ -171,17 +173,17 @@ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int po
private void bindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position, @Nullable List<Object> payloads) {
Object payloadForHolder = payloads != null && !payloads.isEmpty() ? payloads.get(0) : null;
if (position < this.dataSource.getItemCount()) {
NotificationViewData notification = dataSource.getItemAt(position);
if (notification instanceof NotificationViewData.Placeholder) {
NotificationViewData2 notification = dataSource.getItemAt(position);
if (notification instanceof NotificationViewData2.Placeholder) {
if (payloadForHolder == null) {
NotificationViewData.Placeholder placeholder = ((NotificationViewData.Placeholder) notification);
NotificationViewData2.Placeholder placeholder = ((NotificationViewData2.Placeholder) notification);
PlaceholderViewHolder holder = (PlaceholderViewHolder) viewHolder;
holder.setup(statusListener, placeholder.isLoading());
holder.setup(placeholder.isLoading());
}
return;
}
NotificationViewData.Concrete concreteNotification =
(NotificationViewData.Concrete) notification;
NotificationViewData2.Concrete concreteNotification =
(NotificationViewData2.Concrete) notification;
switch (viewHolder.getItemViewType()) {
case VIEW_TYPE_STATUS: {
StatusViewHolder holder = (StatusViewHolder) viewHolder;
Expand Down Expand Up @@ -261,8 +263,8 @@ private void bindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int pos
case VIEW_TYPE_REPORT: {
if (payloadForHolder == null) {
ReportNotificationViewHolder holder = (ReportNotificationViewHolder) viewHolder;
holder.setupWithReport(concreteNotification.getAccount(), concreteNotification.getReport(), statusDisplayOptions.animateAvatars(), statusDisplayOptions.animateEmojis());
holder.setupActionListener(notificationActionListener, concreteNotification.getReport().getTargetAccount().getId(), concreteNotification.getAccount().getId(), concreteNotification.getReport().getId());
// holder.setupWithReport(concreteNotification.getAccount(), concreteNotification.getReport(), statusDisplayOptions.animateAvatars(), statusDisplayOptions.animateEmojis());
// holder.setupActionListener(notificationActionListener, concreteNotification.getReport().getTargetAccount().getId(), concreteNotification.getAccount().getId(), concreteNotification.getReport().getId());
}
}
default:
Expand Down Expand Up @@ -299,9 +301,9 @@ public boolean isMediaPreviewEnabled() {

@Override
public int getItemViewType(int position) {
NotificationViewData notification = dataSource.getItemAt(position);
if (notification instanceof NotificationViewData.Concrete) {
NotificationViewData.Concrete concrete = ((NotificationViewData.Concrete) notification);
NotificationViewData2 notification = dataSource.getItemAt(position);
if (notification instanceof NotificationViewData2.Concrete) {
NotificationViewData2.Concrete concrete = ((NotificationViewData2.Concrete) notification);
switch (concrete.getType()) {
case MENTION:
case POLL: {
Expand All @@ -327,7 +329,7 @@ public int getItemViewType(int position) {
return VIEW_TYPE_UNKNOWN;
}
}
} else if (notification instanceof NotificationViewData.Placeholder) {
} else if (notification instanceof NotificationViewData2.Placeholder) {
return VIEW_TYPE_PLACEHOLDER;
} else {
throw new AssertionError("Unknown notification type");
Expand Down Expand Up @@ -355,14 +357,14 @@ public interface NotificationActionListener {
void onNotificationContentCollapsedChange(boolean isCollapsed, int position);
}

private static class FollowViewHolder extends RecyclerView.ViewHolder {
public static class FollowViewHolder extends RecyclerView.ViewHolder {
private final TextView message;
private final TextView usernameView;
private final TextView displayNameView;
private final ImageView avatar;
private final StatusDisplayOptions statusDisplayOptions;

FollowViewHolder(View itemView, StatusDisplayOptions statusDisplayOptions) {
public FollowViewHolder(View itemView, StatusDisplayOptions statusDisplayOptions) {
super(itemView);
message = itemView.findViewById(R.id.notification_text);
usernameView = itemView.findViewById(R.id.notification_username);
Expand Down Expand Up @@ -404,7 +406,7 @@ void setupButtons(final NotificationActionListener listener, final String accoun
}
}

private static class StatusNotificationViewHolder extends RecyclerView.ViewHolder
public static class StatusNotificationViewHolder extends RecyclerView.ViewHolder
implements View.OnClickListener {

private final View container;
Expand All @@ -431,7 +433,7 @@ private static class StatusNotificationViewHolder extends RecyclerView.ViewHolde
private final int avatarRadius36dp;
private final int avatarRadius24dp;

StatusNotificationViewHolder(
public StatusNotificationViewHolder(
View itemView,
StatusDisplayOptions statusDisplayOptions,
AbsoluteTimeFormatter absoluteTimeFormatter
Expand Down Expand Up @@ -522,7 +524,7 @@ Drawable getIconWithColor(Context context, @DrawableRes int drawable, @ColorRes
return icon;
}

void setMessage(NotificationViewData.Concrete notificationViewData, LinkListener listener) {
void setMessage(NotificationViewData2.Concrete notificationViewData, LinkListener listener) {
this.statusViewData = notificationViewData.getStatusViewData();

String displayName = StringUtils.unicodeWrap(notificationViewData.getAccount().getName());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,54 +14,34 @@
* see <http://www.gnu.org/licenses>. */
package com.keylesspalace.tusky.adapter

import android.view.View
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.button.MaterialButton
import com.google.android.material.progressindicator.CircularProgressIndicatorSpec
import com.google.android.material.progressindicator.IndeterminateDrawable
import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.databinding.ItemStatusPlaceholderBinding
import com.keylesspalace.tusky.interfaces.StatusActionListener
import com.keylesspalace.tusky.util.hide
import com.keylesspalace.tusky.util.show
import com.keylesspalace.tusky.util.visible

/**
* Placeholder for different timelines.
* Placeholder for missing parts in timelines.
*
* Displays a "Load more" button for a particular status ID, or a
* circular progress wheel if the status' page is being loaded.
*
* The user can only have one "Load more" operation in progress at
* a time (determined by the adapter), so the contents of the view
* and the enabled state is driven by that.
* Displays a "Load more" button to load the gap, or a
* circular progress bar if the missing page is being loaded.
*/
class PlaceholderViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val loadMoreButton: MaterialButton = itemView.findViewById(R.id.button_load_more)
private val drawable = IndeterminateDrawable.createCircularDrawable(
itemView.context,
CircularProgressIndicatorSpec(itemView.context, null)
)

fun setup(listener: StatusActionListener, loading: Boolean) {
itemView.isEnabled = !loading
loadMoreButton.isEnabled = !loading

if (loading) {
loadMoreButton.text = ""
loadMoreButton.icon = drawable
return
}
class PlaceholderViewHolder(
private val binding: ItemStatusPlaceholderBinding,
private val listener: StatusActionListener
) : RecyclerView.ViewHolder(binding.root) {

loadMoreButton.text = itemView.context.getString(R.string.load_more_placeholder_text)
loadMoreButton.icon = null
fun setup(loading: Boolean) {
binding.loadMoreButton.visible(!loading)
binding.loadMoreProgressBar.visible(loading)

// To allow the user to click anywhere in the layout to load more content set the click
// listener on the parent layout instead of loadMoreButton.
//
// See the comments in item_status_placeholder.xml for more details.
itemView.setOnClickListener {
itemView.isEnabled = false
loadMoreButton.isEnabled = false
loadMoreButton.icon = drawable
loadMoreButton.text = ""
listener.onLoadMore(bindingAdapterPosition)
if (!loading) {
binding.loadMoreButton.setOnClickListener {
connyduck marked this conversation as resolved.
Show resolved Hide resolved
binding.loadMoreButton.hide()
binding.loadMoreProgressBar.show()
listener.onLoadMore(bindingAdapterPosition)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ private void setRebloggedByDisplayName(final CharSequence name,
}

// don't use this on the same ViewHolder as setRebloggedByDisplayName, will cause recycling issues as paddings are changed
protected void setPollInfo(final boolean ownPoll) {
public void setPollInfo(final boolean ownPoll) {
statusInfo.setText(ownPoll ? R.string.poll_ended_created : R.string.poll_ended_voted);
statusInfo.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.ic_poll_24dp, 0, 0, 0);
statusInfo.setCompoundDrawablePadding(Utils.dpToPx(statusInfo.getContext(), 10));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package com.keylesspalace.tusky.components.notifications

import androidx.recyclerview.widget.RecyclerView
import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.adapter.NotificationsAdapter.NotificationActionListener
import com.keylesspalace.tusky.databinding.ItemFollowBinding
import com.keylesspalace.tusky.entity.Notification
import com.keylesspalace.tusky.util.StatusDisplayOptions
import com.keylesspalace.tusky.util.emojify
import com.keylesspalace.tusky.util.loadAvatar
import com.keylesspalace.tusky.util.unicodeWrap
import com.keylesspalace.tusky.viewdata.NotificationViewData

class FollowViewHolder(
private val binding: ItemFollowBinding,
private val listener: NotificationActionListener,
) : RecyclerView.ViewHolder(binding.root), NotificationsViewHolder {

override fun bind(
viewData: NotificationViewData.Concrete,
payloads: List<*>?,
statusDisplayOptions: StatusDisplayOptions
) {
val context = itemView.context
val account = viewData.account
val messageTemplate =
context.getString(if (viewData.type == Notification.Type.SIGN_UP) R.string.notification_sign_up_format else R.string.notification_follow_format)
val wrappedDisplayName = account.name.unicodeWrap()

binding.notificationText.text = messageTemplate.format(wrappedDisplayName)
.emojify(account.emojis, binding.notificationText, statusDisplayOptions.animateEmojis)

binding.notificationUsername.text = context.getString(R.string.post_username_format, viewData.account.username)

val emojifiedDisplayName = wrappedDisplayName.emojify(
account.emojis,
binding.notificationDisplayName,
statusDisplayOptions.animateEmojis
)
binding.notificationDisplayName.text = emojifiedDisplayName

val avatarRadius = context.resources
.getDimensionPixelSize(R.dimen.avatar_radius_42dp)
loadAvatar(
account.avatar,
binding.notificationAvatar,
avatarRadius,
statusDisplayOptions.animateAvatars, null
)

itemView.setOnClickListener { listener.onViewAccount(account.id) }
}
}
Loading
Loading