diff --git a/app/build.gradle b/app/build.gradle index dc240af0..cf113730 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -113,7 +113,7 @@ dependencies { implementation "androidx.fragment:fragment-ktx:1.2.5" implementation "androidx.browser:browser:1.3.0" implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0" - implementation "androidx.recyclerview:recyclerview:1.1.0" + implementation "androidx.recyclerview:recyclerview:1.2.0" implementation "androidx.exifinterface:exifinterface:1.3.2" implementation "androidx.cardview:cardview:1.0.0" implementation "androidx.preference:preference-ktx:1.1.1" diff --git a/app/src/main/java/com/keylesspalace/tusky/AccountListActivity.kt b/app/src/main/java/com/keylesspalace/tusky/AccountListActivity.kt index 71118501..7f00150f 100644 --- a/app/src/main/java/com/keylesspalace/tusky/AccountListActivity.kt +++ b/app/src/main/java/com/keylesspalace/tusky/AccountListActivity.kt @@ -46,6 +46,7 @@ class AccountListActivity : BaseActivity(), HasAndroidInjector { val type = intent.getSerializableExtra(EXTRA_TYPE) as Type val id: String? = intent.getStringExtra(EXTRA_ID) + val accountLocked: Boolean = intent.getBooleanExtra(EXTRA_ACCOUNT_LOCKED, false) setSupportActionBar(binding.includedToolbar.toolbar) supportActionBar?.apply { @@ -64,7 +65,7 @@ class AccountListActivity : BaseActivity(), HasAndroidInjector { supportFragmentManager .beginTransaction() - .replace(R.id.fragment_container, AccountListFragment.newInstance(type, id)) + .replace(R.id.fragment_container, AccountListFragment.newInstance(type, id, accountLocked)) .commit() } @@ -73,12 +74,15 @@ class AccountListActivity : BaseActivity(), HasAndroidInjector { companion object { private const val EXTRA_TYPE = "type" private const val EXTRA_ID = "id" + private const val EXTRA_ACCOUNT_LOCKED = "acc_locked" @JvmStatic - fun newIntent(context: Context, type: Type, id: String? = null): Intent { + @JvmOverloads + fun newIntent(context: Context, type: Type, id: String? = null, accountLocked: Boolean = false): Intent { return Intent(context, AccountListActivity::class.java).apply { putExtra(EXTRA_TYPE, type) putExtra(EXTRA_ID, id) + putExtra(EXTRA_ACCOUNT_LOCKED, accountLocked) } } } diff --git a/app/src/main/java/com/keylesspalace/tusky/AccountsInListFragment.kt b/app/src/main/java/com/keylesspalace/tusky/AccountsInListFragment.kt index 0151e070..df381aa1 100644 --- a/app/src/main/java/com/keylesspalace/tusky/AccountsInListFragment.kt +++ b/app/src/main/java/com/keylesspalace/tusky/AccountsInListFragment.kt @@ -181,7 +181,7 @@ class AccountsInListFragment : DialogFragment(), Injectable { binding.notificationTextView.hide() binding.acceptButton.hide() binding.rejectButton.setOnClickListener { - onRemoveFromList(getItem(holder.adapterPosition).id) + onRemoveFromList(getItem(holder.bindingAdapterPosition).id) } binding.rejectButton.contentDescription = binding.root.context.getString(R.string.action_remove_from_list) @@ -217,7 +217,7 @@ class AccountsInListFragment : DialogFragment(), Injectable { binding.notificationTextView.hide() binding.acceptButton.hide() binding.rejectButton.setOnClickListener { - val (account, inAList) = getItem(holder.adapterPosition) + val (account, inAList) = getItem(holder.bindingAdapterPosition) if (inAList) { onRemoveFromList(account.id) } else { diff --git a/app/src/main/java/com/keylesspalace/tusky/ListsActivity.kt b/app/src/main/java/com/keylesspalace/tusky/ListsActivity.kt index 04311a66..be995e9e 100644 --- a/app/src/main/java/com/keylesspalace/tusky/ListsActivity.kt +++ b/app/src/main/java/com/keylesspalace/tusky/ListsActivity.kt @@ -250,9 +250,9 @@ class ListsActivity : BaseActivity(), Injectable, HasAndroidInjector { override fun onClick(v: View) { if (v == itemView) { - onListSelected(getItem(adapterPosition).id) + onListSelected(getItem(bindingAdapterPosition).id) } else { - onMore(getItem(adapterPosition), v) + onMore(getItem(bindingAdapterPosition), v) } } } diff --git a/app/src/main/java/com/keylesspalace/tusky/MainActivity.kt b/app/src/main/java/com/keylesspalace/tusky/MainActivity.kt index d46d3d56..1628d41d 100644 --- a/app/src/main/java/com/keylesspalace/tusky/MainActivity.kt +++ b/app/src/main/java/com/keylesspalace/tusky/MainActivity.kt @@ -121,6 +121,8 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje private lateinit var glide: RequestManager + private var accountLocked: Boolean = false + private val emojiInitCallback = object : InitCallback() { override fun onInitialized() { if (!isDestroyed) { @@ -399,6 +401,14 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje startActivityWithSlideInAnimation(intent) } }, + primaryDrawerItem { + nameRes = R.string.action_view_follow_requests + iconicsIcon = GoogleMaterial.Icon.gmd_person_add + onClick = { + val intent = AccountListActivity.newIntent(context, AccountListActivity.Type.FOLLOW_REQUESTS, accountLocked = accountLocked) + startActivityWithSlideInAnimation(intent) + } + }, primaryDrawerItem { nameRes = R.string.action_lists iconicsIcon = GoogleMaterial.Icon.gmd_list @@ -660,22 +670,8 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje accountManager.updateActiveAccount(me) NotificationHelper.createNotificationChannelsForAccount(accountManager.activeAccount!!, this) - // Show follow requests in the menu, if this is a locked account. - if (me.locked && binding.mainDrawer.getDrawerItem(DRAWER_ITEM_FOLLOW_REQUESTS) == null) { - val followRequestsItem = primaryDrawerItem { - identifier = DRAWER_ITEM_FOLLOW_REQUESTS - nameRes = R.string.action_view_follow_requests - iconicsIcon = GoogleMaterial.Icon.gmd_person_add - onClick = { - val intent = Intent(this@MainActivity, AccountListActivity::class.java) - intent.putExtra("type", AccountListActivity.Type.FOLLOW_REQUESTS) - startActivityWithSlideInAnimation(intent) - } - } - binding.mainDrawer.addItemAtPosition(4, followRequestsItem) - } else if (!me.locked) { - binding.mainDrawer.removeItems(DRAWER_ITEM_FOLLOW_REQUESTS) - } + accountLocked = me.locked + updateProfiles() updateShortcut(this, accountManager.activeAccount!!) } @@ -789,7 +785,6 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje companion object { private const val TAG = "MainActivity" // logging tag private const val DRAWER_ITEM_ADD_ACCOUNT: Long = -13 - private const val DRAWER_ITEM_FOLLOW_REQUESTS: Long = 10 private const val DRAWER_ITEM_ANNOUNCEMENTS: Long = 14 const val STATUS_URL = "statusUrl" } diff --git a/app/src/main/java/com/keylesspalace/tusky/TabPreferenceActivity.kt b/app/src/main/java/com/keylesspalace/tusky/TabPreferenceActivity.kt index 413e754b..67cd9cb6 100644 --- a/app/src/main/java/com/keylesspalace/tusky/TabPreferenceActivity.kt +++ b/app/src/main/java/com/keylesspalace/tusky/TabPreferenceActivity.kt @@ -109,17 +109,17 @@ class TabPreferenceActivity : BaseActivity(), Injectable, ItemInteractionListene } override fun onMove(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder): Boolean { - val temp = currentTabs[viewHolder.adapterPosition] - currentTabs[viewHolder.adapterPosition] = currentTabs[target.adapterPosition] - currentTabs[target.adapterPosition] = temp + val temp = currentTabs[viewHolder.bindingAdapterPosition] + currentTabs[viewHolder.bindingAdapterPosition] = currentTabs[target.bindingAdapterPosition] + currentTabs[target.bindingAdapterPosition] = temp - currentTabsAdapter.notifyItemMoved(viewHolder.adapterPosition, target.adapterPosition) + currentTabsAdapter.notifyItemMoved(viewHolder.bindingAdapterPosition, target.bindingAdapterPosition) saveTabs() return true } override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) { - onTabRemoved(viewHolder.adapterPosition) + onTabRemoved(viewHolder.bindingAdapterPosition) } override fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) { diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/AccountFieldEditAdapter.kt b/app/src/main/java/com/keylesspalace/tusky/adapter/AccountFieldEditAdapter.kt index 29cbec28..f7f4553a 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/AccountFieldEditAdapter.kt +++ b/app/src/main/java/com/keylesspalace/tusky/adapter/AccountFieldEditAdapter.kt @@ -65,7 +65,7 @@ class AccountFieldEditAdapter : RecyclerView.Adapter { - int position = getAdapterPosition(); + int position = getBindingAdapterPosition(); if (position != RecyclerView.NO_POSITION) { listener.onBlock(false, id, position); } diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/FollowRequestViewHolder.kt b/app/src/main/java/com/keylesspalace/tusky/adapter/FollowRequestViewHolder.kt index f19dde82..a7e92743 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/FollowRequestViewHolder.kt +++ b/app/src/main/java/com/keylesspalace/tusky/adapter/FollowRequestViewHolder.kt @@ -51,13 +51,13 @@ class FollowRequestViewHolder( fun setupActionListener(listener: AccountActionListener, accountId: String) { binding.acceptButton.setOnClickListener { - val position = adapterPosition + val position = bindingAdapterPosition if (position != RecyclerView.NO_POSITION) { listener.onRespondToFollowRequest(true, accountId, position) } } binding.rejectButton.setOnClickListener { - val position = adapterPosition + val position = bindingAdapterPosition if (position != RecyclerView.NO_POSITION) { listener.onRespondToFollowRequest(false, accountId, position) } diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/FollowRequestsHeaderAdapter.kt b/app/src/main/java/com/keylesspalace/tusky/adapter/FollowRequestsHeaderAdapter.kt new file mode 100644 index 00000000..60ab4008 --- /dev/null +++ b/app/src/main/java/com/keylesspalace/tusky/adapter/FollowRequestsHeaderAdapter.kt @@ -0,0 +1,40 @@ +/* Copyright 2020 Tusky Contributors + * + * This file is a part of Tusky. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation; either version 3 of the + * License, or (at your option) any later version. + * + * Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even + * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. + * + * You should have received a copy of the GNU General Public License along with Tusky; if not, + * see . */ + +package com.keylesspalace.tusky.adapter + +import android.view.LayoutInflater +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.keylesspalace.tusky.R + +class FollowRequestsHeaderAdapter(private val instanceName: String, private val accountLocked: Boolean) : RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HeaderViewHolder { + val view = LayoutInflater.from(parent.context) + .inflate(R.layout.item_follow_requests_header, parent, false) as TextView + return HeaderViewHolder(view) + } + + override fun onBindViewHolder(viewHolder: HeaderViewHolder, position: Int) { + viewHolder.textView.text = viewHolder.textView.context.getString(R.string.follow_requests_info, instanceName) + } + + override fun getItemCount() = if (accountLocked) 0 else 1 + +} + +class HeaderViewHolder(var textView: TextView) : RecyclerView.ViewHolder(textView) diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/MutesAdapter.java b/app/src/main/java/com/keylesspalace/tusky/adapter/MutesAdapter.java index 20140fff..f63af6ca 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/MutesAdapter.java +++ b/app/src/main/java/com/keylesspalace/tusky/adapter/MutesAdapter.java @@ -122,9 +122,9 @@ public class MutesAdapter extends AccountAdapter { } void setupActionListener(final AccountActionListener listener) { - unmute.setOnClickListener(v -> listener.onMute(false, id, getAdapterPosition(), false)); + unmute.setOnClickListener(v -> listener.onMute(false, id, getBindingAdapterPosition(), false)); muteNotifications.setOnClickListener( - v -> listener.onMute(true, id, getAdapterPosition(), !notifications)); + v -> listener.onMute(true, id, getBindingAdapterPosition(), !notifications)); itemView.setOnClickListener(v -> listener.onViewAccount(id)); } } diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/NotificationsAdapter.java b/app/src/main/java/com/keylesspalace/tusky/adapter/NotificationsAdapter.java index 92ebbfe4..b2f12b81 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/NotificationsAdapter.java +++ b/app/src/main/java/com/keylesspalace/tusky/adapter/NotificationsAdapter.java @@ -541,8 +541,8 @@ public class NotificationsAdapter extends RecyclerView.Adapter { } contentWarningButton.setOnClickListener(view -> { - if (getAdapterPosition() != RecyclerView.NO_POSITION) { - notificationActionListener.onExpandedChange(!statusViewData.isExpanded(), getAdapterPosition()); + if (getBindingAdapterPosition() != RecyclerView.NO_POSITION) { + notificationActionListener.onExpandedChange(!statusViewData.isExpanded(), getBindingAdapterPosition()); } statusContent.setVisibility(statusViewData.isExpanded() ? View.GONE : View.VISIBLE); }); @@ -619,7 +619,7 @@ public class NotificationsAdapter extends RecyclerView.Adapter { if (statusViewData.isCollapsible() && (statusViewData.isExpanded() || !hasSpoiler)) { contentCollapseButton.setOnClickListener(view -> { - int position = getAdapterPosition(); + int position = getBindingAdapterPosition(); if (position != RecyclerView.NO_POSITION && notificationActionListener != null) { notificationActionListener.onNotificationContentCollapsedChange(!statusViewData.isCollapsed(), position); } diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/PlaceholderViewHolder.java b/app/src/main/java/com/keylesspalace/tusky/adapter/PlaceholderViewHolder.java index 2f946108..f8f1a0b5 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/PlaceholderViewHolder.java +++ b/app/src/main/java/com/keylesspalace/tusky/adapter/PlaceholderViewHolder.java @@ -41,7 +41,7 @@ public final class PlaceholderViewHolder extends RecyclerView.ViewHolder { loadMoreButton.setEnabled(true); loadMoreButton.setOnClickListener(v -> { loadMoreButton.setEnabled(false); - listener.onLoadMore(getAdapterPosition()); + listener.onLoadMore(getBindingAdapterPosition()); }); } diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/PollAdapter.kt b/app/src/main/java/com/keylesspalace/tusky/adapter/PollAdapter.kt index fa69e338..1f57cc4e 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/PollAdapter.kt +++ b/app/src/main/java/com/keylesspalace/tusky/adapter/PollAdapter.kt @@ -100,7 +100,7 @@ class PollAdapter: RecyclerView.Adapter>() { radioButton.isChecked = option.selected radioButton.setOnClickListener { pollOptions.forEachIndexed { index, pollOption -> - pollOption.selected = index == holder.adapterPosition + pollOption.selected = index == holder.bindingAdapterPosition notifyItemChanged(index) } } @@ -110,7 +110,7 @@ class PollAdapter: RecyclerView.Adapter>() { checkBox.text = EmojiCompat.get().process(emojifiedPollOptionText) checkBox.isChecked = option.selected checkBox.setOnCheckedChangeListener { _, isChecked -> - pollOptions[holder.adapterPosition].selected = isChecked + pollOptions[holder.bindingAdapterPosition].selected = isChecked } } } diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/SavedTootAdapter.java b/app/src/main/java/com/keylesspalace/tusky/adapter/SavedTootAdapter.java index 6d4889c8..af9c31d5 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/SavedTootAdapter.java +++ b/app/src/main/java/com/keylesspalace/tusky/adapter/SavedTootAdapter.java @@ -113,9 +113,9 @@ public class SavedTootAdapter extends RecyclerView.Adapter { suppr.setOnClickListener(v -> { v.setEnabled(false); - handler.delete(getAdapterPosition(), item); + handler.delete(getBindingAdapterPosition(), item); }); - view.setOnClickListener(v -> handler.click(getAdapterPosition(), item)); + view.setOnClickListener(v -> handler.click(getBindingAdapterPosition(), item)); } } } diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java b/app/src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java index 3fc27d7c..d6cee626 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java +++ b/app/src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java @@ -217,8 +217,8 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder { setContentWarningButtonText(expanded); contentWarningButton.setOnClickListener(view -> { contentWarningDescription.invalidate(); - if (getAdapterPosition() != RecyclerView.NO_POSITION) { - listener.onExpandedChange(!expanded, getAdapterPosition()); + if (getBindingAdapterPosition() != RecyclerView.NO_POSITION) { + listener.onExpandedChange(!expanded, getBindingAdapterPosition()); } setContentWarningButtonText(!expanded); @@ -513,15 +513,15 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder { sensitiveMediaWarning.setVisibility(showingContent ? View.GONE : View.VISIBLE); sensitiveMediaShow.setVisibility(showingContent ? View.VISIBLE : View.GONE); sensitiveMediaShow.setOnClickListener(v -> { - if (getAdapterPosition() != RecyclerView.NO_POSITION) { - listener.onContentHiddenChange(false, getAdapterPosition()); + if (getBindingAdapterPosition() != RecyclerView.NO_POSITION) { + listener.onContentHiddenChange(false, getBindingAdapterPosition()); } v.setVisibility(View.GONE); sensitiveMediaWarning.setVisibility(View.VISIBLE); }); sensitiveMediaWarning.setOnClickListener(v -> { - if (getAdapterPosition() != RecyclerView.NO_POSITION) { - listener.onContentHiddenChange(true, getAdapterPosition()); + if (getBindingAdapterPosition() != RecyclerView.NO_POSITION) { + listener.onContentHiddenChange(true, getBindingAdapterPosition()); } v.setVisibility(View.GONE); sensitiveMediaShow.setVisibility(View.VISIBLE); @@ -582,10 +582,10 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder { private void setAttachmentClickListener(View view, StatusActionListener listener, int index, Attachment attachment, boolean animateTransition) { view.setOnClickListener(v -> { - int position = getAdapterPosition(); + int position = getBindingAdapterPosition(); if (position != RecyclerView.NO_POSITION) { if (sensitiveMediaWarning.getVisibility() == View.VISIBLE) { - listener.onContentHiddenChange(true, getAdapterPosition()); + listener.onContentHiddenChange(true, getBindingAdapterPosition()); } else { listener.onViewMedia(position, index, animateTransition ? v : null); } @@ -627,7 +627,7 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder { displayName.setOnClickListener(profileButtonClickListener); replyButton.setOnClickListener(v -> { - int position = getAdapterPosition(); + int position = getBindingAdapterPosition(); if (position != RecyclerView.NO_POSITION) { listener.onReply(position); } @@ -635,7 +635,7 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder { if (reblogButton != null) { reblogButton.setEventListener((button, buttonState) -> { // return true to play animaion - int position = getAdapterPosition(); + int position = getBindingAdapterPosition(); if (position != RecyclerView.NO_POSITION) { if (statusDisplayOptions.confirmReblogs()) { showConfirmReblogDialog(listener, statusContent, buttonState, position); @@ -651,7 +651,7 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder { } favouriteButton.setEventListener((button, buttonState) -> { - int position = getAdapterPosition(); + int position = getBindingAdapterPosition(); if (position != RecyclerView.NO_POSITION) { listener.onFavourite(!buttonState, position); } @@ -659,7 +659,7 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder { }); bookmarkButton.setEventListener((button, buttonState) -> { - int position = getAdapterPosition(); + int position = getBindingAdapterPosition(); if (position != RecyclerView.NO_POSITION) { listener.onBookmark(!buttonState, position); } @@ -667,7 +667,7 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder { }); moreButton.setOnClickListener(v -> { - int position = getAdapterPosition(); + int position = getBindingAdapterPosition(); if (position != RecyclerView.NO_POSITION) { listener.onMore(v, position); } @@ -677,7 +677,7 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder { * just eat the clicks instead of deferring to the parent listener, but WILL respond to a * listener directly on the TextView, for whatever reason. */ View.OnClickListener viewThreadListener = v -> { - int position = getAdapterPosition(); + int position = getBindingAdapterPosition(); if (position != RecyclerView.NO_POSITION) { listener.onViewThread(position); } @@ -926,7 +926,7 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder { if (expired || poll.getVoted()) { // no voting possible View.OnClickListener viewThreadListener = v -> { - int position = getAdapterPosition(); + int position = getBindingAdapterPosition(); if (position != RecyclerView.NO_POSITION) { listener.onViewThread(position); } @@ -958,7 +958,7 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder { pollButton.setOnClickListener(v -> { - int position = getAdapterPosition(); + int position = getBindingAdapterPosition(); if (position != RecyclerView.NO_POSITION) { diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/StatusDetailedViewHolder.java b/app/src/main/java/com/keylesspalace/tusky/adapter/StatusDetailedViewHolder.java index 8755e8e8..abb8ca85 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/StatusDetailedViewHolder.java +++ b/app/src/main/java/com/keylesspalace/tusky/adapter/StatusDetailedViewHolder.java @@ -72,13 +72,13 @@ class StatusDetailedViewHolder extends StatusBaseViewHolder { } reblogs.setOnClickListener(v -> { - int position = getAdapterPosition(); + int position = getBindingAdapterPosition(); if (position != RecyclerView.NO_POSITION) { listener.onShowReblogs(position); } }); favourites.setOnClickListener(v -> { - int position = getAdapterPosition(); + int position = getBindingAdapterPosition(); if (position != RecyclerView.NO_POSITION) { listener.onShowFavs(position); } diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/StatusViewHolder.java b/app/src/main/java/com/keylesspalace/tusky/adapter/StatusViewHolder.java index 043b7b35..68d64a69 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/StatusViewHolder.java +++ b/app/src/main/java/com/keylesspalace/tusky/adapter/StatusViewHolder.java @@ -67,7 +67,7 @@ public class StatusViewHolder extends StatusBaseViewHolder { hideStatusInfo(); } else { setRebloggedByDisplayName(rebloggedByDisplayName, status, statusDisplayOptions); - statusInfo.setOnClickListener(v -> listener.onOpenReblog(getAdapterPosition())); + statusInfo.setOnClickListener(v -> listener.onOpenReblog(getBindingAdapterPosition())); } } @@ -105,7 +105,7 @@ public class StatusViewHolder extends StatusBaseViewHolder { /* input filter for TextViews have to be set before text */ if (status.isCollapsible() && (status.isExpanded() || TextUtils.isEmpty(status.getSpoilerText()))) { contentCollapseButton.setOnClickListener(view -> { - int position = getAdapterPosition(); + int position = getBindingAdapterPosition(); if (position != RecyclerView.NO_POSITION) listener.onContentCollapsedChange(!status.isCollapsed(), position); }); diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/TabAdapter.kt b/app/src/main/java/com/keylesspalace/tusky/adapter/TabAdapter.kt index e2236503..bec07f06 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/TabAdapter.kt +++ b/app/src/main/java/com/keylesspalace/tusky/adapter/TabAdapter.kt @@ -98,7 +98,7 @@ class TabAdapter(private var data: List, } } binding.removeButton.setOnClickListener { - listener.onTabRemoved(holder.adapterPosition) + listener.onTabRemoved(holder.bindingAdapterPosition) } binding.removeButton.isEnabled = removeButtonEnabled ThemeUtils.setDrawableTint( @@ -131,7 +131,7 @@ class TabAdapter(private var data: List, } else { chip.setChipIconResource(R.drawable.ic_cancel_24dp) chip.setOnClickListener { - listener.onChipClicked(tab, holder.adapterPosition, i) + listener.onChipClicked(tab, holder.bindingAdapterPosition, i) } } } @@ -141,7 +141,7 @@ class TabAdapter(private var data: List, } binding.actionChip.setOnClickListener { - listener.onActionChipClicked(tab, holder.adapterPosition) + listener.onActionChipClicked(tab, holder.bindingAdapterPosition) } } else { diff --git a/app/src/main/java/com/keylesspalace/tusky/components/compose/MediaPreviewAdapter.kt b/app/src/main/java/com/keylesspalace/tusky/components/compose/MediaPreviewAdapter.kt index 093e860f..a08aebc0 100644 --- a/app/src/main/java/com/keylesspalace/tusky/components/compose/MediaPreviewAdapter.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/compose/MediaPreviewAdapter.kt @@ -103,7 +103,7 @@ class MediaPreviewAdapter( progressImageView.layoutParams = layoutParams progressImageView.scaleType = ImageView.ScaleType.CENTER_CROP progressImageView.setOnClickListener { - onMediaClick(adapterPosition, progressImageView) + onMediaClick(bindingAdapterPosition, progressImageView) } } } diff --git a/app/src/main/java/com/keylesspalace/tusky/components/conversation/ConversationViewHolder.java b/app/src/main/java/com/keylesspalace/tusky/components/conversation/ConversationViewHolder.java index e74be628..2d2f683d 100644 --- a/app/src/main/java/com/keylesspalace/tusky/components/conversation/ConversationViewHolder.java +++ b/app/src/main/java/com/keylesspalace/tusky/components/conversation/ConversationViewHolder.java @@ -147,7 +147,7 @@ public class ConversationViewHolder extends StatusBaseViewHolder { /* input filter for TextViews have to be set before text */ if (collapsible && (expanded || TextUtils.isEmpty(spoilerText))) { contentCollapseButton.setOnClickListener(view -> { - int position = getAdapterPosition(); + int position = getBindingAdapterPosition(); if (position != RecyclerView.NO_POSITION) listener.onContentCollapsedChange(!collapsed, position); }); diff --git a/app/src/main/java/com/keylesspalace/tusky/components/drafts/DraftsAdapter.kt b/app/src/main/java/com/keylesspalace/tusky/components/drafts/DraftsAdapter.kt index 7fd224ac..5ba3716e 100644 --- a/app/src/main/java/com/keylesspalace/tusky/components/drafts/DraftsAdapter.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/drafts/DraftsAdapter.kt @@ -55,7 +55,7 @@ class DraftsAdapter( binding.draftMediaPreview.layoutManager = LinearLayoutManager(binding.root.context, RecyclerView.HORIZONTAL, false) binding.draftMediaPreview.adapter = DraftMediaAdapter { - getItem(viewHolder.adapterPosition)?.let { draft -> + getItem(viewHolder.bindingAdapterPosition)?.let { draft -> listener.onOpenDraft(draft) } } diff --git a/app/src/main/java/com/keylesspalace/tusky/components/instancemute/adapter/DomainMutesAdapter.kt b/app/src/main/java/com/keylesspalace/tusky/components/instancemute/adapter/DomainMutesAdapter.kt index de699d12..f475f394 100644 --- a/app/src/main/java/com/keylesspalace/tusky/components/instancemute/adapter/DomainMutesAdapter.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/instancemute/adapter/DomainMutesAdapter.kt @@ -24,7 +24,7 @@ class DomainMutesAdapter( holder.binding.mutedDomain.text = instance holder.binding.mutedDomainUnmute.setOnClickListener { - actionListener.mute(false, instance, holder.adapterPosition) + actionListener.mute(false, instance, holder.bindingAdapterPosition) } } diff --git a/app/src/main/java/com/keylesspalace/tusky/components/report/adapter/StatusViewHolder.kt b/app/src/main/java/com/keylesspalace/tusky/components/report/adapter/StatusViewHolder.kt index 88a246f4..90579a92 100644 --- a/app/src/main/java/com/keylesspalace/tusky/components/report/adapter/StatusViewHolder.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/report/adapter/StatusViewHolder.kt @@ -173,5 +173,5 @@ class StatusViewHolder( } } - private fun status() = getStatusForPosition(adapterPosition) + private fun status() = getStatusForPosition(bindingAdapterPosition) } \ No newline at end of file diff --git a/app/src/main/java/com/keylesspalace/tusky/fragment/AccountListFragment.kt b/app/src/main/java/com/keylesspalace/tusky/fragment/AccountListFragment.kt index 6e81ab35..cf7050b8 100644 --- a/app/src/main/java/com/keylesspalace/tusky/fragment/AccountListFragment.kt +++ b/app/src/main/java/com/keylesspalace/tusky/fragment/AccountListFragment.kt @@ -21,6 +21,7 @@ import android.view.View import androidx.fragment.app.Fragment import androidx.lifecycle.Lifecycle import androidx.preference.PreferenceManager +import androidx.recyclerview.widget.ConcatAdapter import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView @@ -31,6 +32,7 @@ import com.keylesspalace.tusky.AccountListActivity.Type import com.keylesspalace.tusky.BaseActivity import com.keylesspalace.tusky.R import com.keylesspalace.tusky.adapter.* +import com.keylesspalace.tusky.db.AccountManager import com.keylesspalace.tusky.databinding.FragmentAccountListBinding import com.keylesspalace.tusky.di.Injectable import com.keylesspalace.tusky.entity.Account @@ -56,6 +58,8 @@ class AccountListFragment : Fragment(R.layout.fragment_account_list), AccountAct @Inject lateinit var api: MastodonApi + @Inject + lateinit var accountManager: AccountManager private val binding by viewBinding(FragmentAccountListBinding::bind) @@ -90,10 +94,17 @@ class AccountListFragment : Fragment(R.layout.fragment_account_list), AccountAct adapter = when (type) { Type.BLOCKS -> BlocksAdapter(this, animateAvatar, animateEmojis) Type.MUTES -> MutesAdapter(this, animateAvatar, animateEmojis) - Type.FOLLOW_REQUESTS -> FollowRequestsAdapter(this, animateAvatar, animateEmojis) + Type.FOLLOW_REQUESTS -> { + val headerAdapter = FollowRequestsHeaderAdapter(accountManager.activeAccount!!.domain, arguments?.get(ARG_ACCOUNT_LOCKED) == true) + val followRequestsAdapter = FollowRequestsAdapter(this, animateAvatar, animateEmojis) + binding.recyclerView.adapter = ConcatAdapter(headerAdapter, followRequestsAdapter) + followRequestsAdapter + } else -> FollowAdapter(this, animateAvatar, animateEmojis) } - binding.recyclerView.adapter = adapter + if (binding.recyclerView.adapter == null) { + binding.recyclerView.adapter = adapter + } scrollListener = object : EndlessOnScrollListener(layoutManager) { override fun onLoadMore(totalItemsCount: Int, view: RecyclerView) { @@ -361,12 +372,14 @@ class AccountListFragment : Fragment(R.layout.fragment_account_list), AccountAct private const val TAG = "AccountList" // logging tag private const val ARG_TYPE = "type" private const val ARG_ID = "id" + private const val ARG_ACCOUNT_LOCKED = "acc_locked" - fun newInstance(type: Type, id: String? = null): AccountListFragment { + fun newInstance(type: Type, id: String? = null, accountLocked: Boolean = false): AccountListFragment { return AccountListFragment().apply { arguments = Bundle(2).apply { putSerializable(ARG_TYPE, type) putString(ARG_ID, id) + putBoolean(ARG_ACCOUNT_LOCKED, accountLocked) } } } diff --git a/app/src/main/java/com/keylesspalace/tusky/fragment/AccountMediaFragment.kt b/app/src/main/java/com/keylesspalace/tusky/fragment/AccountMediaFragment.kt index f6679192..c299e115 100644 --- a/app/src/main/java/com/keylesspalace/tusky/fragment/AccountMediaFragment.kt +++ b/app/src/main/java/com/keylesspalace/tusky/fragment/AccountMediaFragment.kt @@ -320,7 +320,7 @@ class AccountMediaFragment : Fragment(R.layout.fragment_timeline), RefreshableFr // saving some allocations override fun onClick(v: View?) { - viewMedia(items, adapterPosition, imageView) + viewMedia(items, bindingAdapterPosition, imageView) } } } diff --git a/app/src/main/res/layout/item_follow_requests_header.xml b/app/src/main/res/layout/item_follow_requests_header.xml new file mode 100644 index 00000000..06e5c93f --- /dev/null +++ b/app/src/main/res/layout/item_follow_requests_header.xml @@ -0,0 +1,12 @@ + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ce2cb0dd..52f777b5 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -622,6 +622,9 @@ Draft deleted The Toot you drafted a reply to has been removed + Even though your account is not locked, the %1$s staff thought you might want to review follow requests from these accounts manually. + Subscribe Unsubscribe +