Timeline a11y (#1059)
* Improve timeline accessibility * Improve a11y description and actions in timeline * Refactor timeline accessibility handling, add more actions * Update app/src/main/java/com/keylesspalace/tusky/adapter/StatusViewHolder.java Co-Authored-By: charlag <charlag@tutanota.com> * Add a11y actions for links, hashtags and mentions, enable for detailed. * A11y delegate: Add open reblogger action, cleanup * a11y delegate: add reblogs/boosts, improve interrupts * a11y delegate: add reblogs/boosts, improve interrupts * a11y delegate: add to notifications fragment
This commit is contained in:
parent
df8c78c81a
commit
479d210e64
15 changed files with 646 additions and 78 deletions
|
@ -47,6 +47,7 @@ import com.keylesspalace.tusky.network.TimelineCases;
|
|||
import com.keylesspalace.tusky.util.CollectionUtil;
|
||||
import com.keylesspalace.tusky.util.Either;
|
||||
import com.keylesspalace.tusky.util.HttpHeaderLink;
|
||||
import com.keylesspalace.tusky.util.ListStatusAccessibilityDelegate;
|
||||
import com.keylesspalace.tusky.util.ListUtils;
|
||||
import com.keylesspalace.tusky.util.PairedList;
|
||||
import com.keylesspalace.tusky.util.ThemeUtils;
|
||||
|
@ -186,6 +187,16 @@ public class NotificationsFragment extends SFragment implements
|
|||
recyclerView.setHasFixedSize(true);
|
||||
layoutManager = new LinearLayoutManager(context);
|
||||
recyclerView.setLayoutManager(layoutManager);
|
||||
recyclerView.setAccessibilityDelegateCompat(
|
||||
new ListStatusAccessibilityDelegate(recyclerView, this, (pos) -> {
|
||||
NotificationViewData notification = notifications.getPairedItem(pos);
|
||||
// We support replies only for now
|
||||
if (notification instanceof NotificationViewData.Concrete) {
|
||||
return ((NotificationViewData.Concrete) notification).getStatusViewData();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}));
|
||||
|
||||
recyclerView.addItemDecoration(new DividerItemDecoration(context, DividerItemDecoration.VERTICAL));
|
||||
|
||||
|
|
|
@ -189,7 +189,7 @@ class SearchFragment : SFragment(), StatusActionListener, Injectable {
|
|||
}
|
||||
}
|
||||
|
||||
override fun onViewMedia(position: Int, attachmentIndex: Int, view: View) {
|
||||
override fun onViewMedia(position: Int, attachmentIndex: Int, view: View?) {
|
||||
val status = searchAdapter.getStatusAtPosition(position) ?: return
|
||||
viewMedia(attachmentIndex, status, view)
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
package com.keylesspalace.tusky.fragment;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
|
@ -27,6 +28,8 @@ import android.widget.ProgressBar;
|
|||
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
import com.keylesspalace.tusky.AccountListActivity;
|
||||
import com.keylesspalace.tusky.BaseActivity;
|
||||
import com.keylesspalace.tusky.R;
|
||||
import com.keylesspalace.tusky.adapter.TimelineAdapter;
|
||||
import com.keylesspalace.tusky.appstore.BlockEvent;
|
||||
|
@ -50,6 +53,7 @@ import com.keylesspalace.tusky.repository.TimelineRepository;
|
|||
import com.keylesspalace.tusky.repository.TimelineRequestMode;
|
||||
import com.keylesspalace.tusky.util.CollectionUtil;
|
||||
import com.keylesspalace.tusky.util.Either;
|
||||
import com.keylesspalace.tusky.util.ListStatusAccessibilityDelegate;
|
||||
import com.keylesspalace.tusky.util.ListUtils;
|
||||
import com.keylesspalace.tusky.util.PairedList;
|
||||
import com.keylesspalace.tusky.util.StringUtils;
|
||||
|
@ -347,6 +351,8 @@ public class TimelineFragment extends SFragment implements
|
|||
}
|
||||
|
||||
private void setupRecyclerView() {
|
||||
recyclerView.setAccessibilityDelegateCompat(
|
||||
new ListStatusAccessibilityDelegate(recyclerView, this, statuses::getPairedItem));
|
||||
Context context = recyclerView.getContext();
|
||||
recyclerView.setHasFixedSize(true);
|
||||
layoutManager = new LinearLayoutManager(context);
|
||||
|
@ -630,6 +636,21 @@ public class TimelineFragment extends SFragment implements
|
|||
updateAdapter();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onShowReblogs(int position) {
|
||||
String statusId = statuses.get(position).asRight().getId();
|
||||
Intent intent = AccountListActivity.newIntent(getContext(), AccountListActivity.Type.REBLOGGED, statusId);
|
||||
((BaseActivity) getActivity()).startActivityWithSlideInAnimation(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onShowFavs(int position) {
|
||||
String statusId = statuses.get(position).asRight().getId();
|
||||
Intent intent = AccountListActivity.newIntent(getContext(), AccountListActivity.Type.FAVOURITED, statusId);
|
||||
((BaseActivity) getActivity()).startActivityWithSlideInAnimation(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadMore(int position) {
|
||||
//check bounds before accessing list,
|
||||
|
@ -684,7 +705,7 @@ public class TimelineFragment extends SFragment implements
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onViewMedia(int position, int attachmentIndex, @NonNull View view) {
|
||||
public void onViewMedia(int position, int attachmentIndex, @Nullable View view) {
|
||||
Status status = statuses.get(position).asRightOrNull();
|
||||
if (status == null) return;
|
||||
super.viewMedia(attachmentIndex, status, view);
|
||||
|
|
|
@ -15,37 +15,27 @@
|
|||
|
||||
package com.keylesspalace.tusky.fragment;
|
||||
|
||||
import androidx.arch.core.util.Function;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
import androidx.core.util.Pair;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
import androidx.recyclerview.widget.DividerItemDecoration;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.recyclerview.widget.SimpleItemAnimator;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
import com.keylesspalace.tusky.AccountListActivity;
|
||||
import com.keylesspalace.tusky.BaseActivity;
|
||||
import com.keylesspalace.tusky.BuildConfig;
|
||||
import com.keylesspalace.tusky.R;
|
||||
import com.keylesspalace.tusky.ViewThreadActivity;
|
||||
import com.keylesspalace.tusky.adapter.ThreadAdapter;
|
||||
import com.keylesspalace.tusky.appstore.EventHub;
|
||||
import com.keylesspalace.tusky.appstore.BlockEvent;
|
||||
import com.keylesspalace.tusky.appstore.EventHub;
|
||||
import com.keylesspalace.tusky.appstore.FavoriteEvent;
|
||||
import com.keylesspalace.tusky.appstore.ReblogEvent;
|
||||
import com.keylesspalace.tusky.appstore.StatusComposedEvent;
|
||||
|
@ -57,6 +47,7 @@ import com.keylesspalace.tusky.entity.StatusContext;
|
|||
import com.keylesspalace.tusky.interfaces.StatusActionListener;
|
||||
import com.keylesspalace.tusky.network.MastodonApi;
|
||||
import com.keylesspalace.tusky.network.TimelineCases;
|
||||
import com.keylesspalace.tusky.util.ListStatusAccessibilityDelegate;
|
||||
import com.keylesspalace.tusky.util.PairedList;
|
||||
import com.keylesspalace.tusky.util.SmartLengthInputFilter;
|
||||
import com.keylesspalace.tusky.util.ThemeUtils;
|
||||
|
@ -70,6 +61,16 @@ import java.util.Locale;
|
|||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.arch.core.util.Function;
|
||||
import androidx.core.util.Pair;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
import androidx.recyclerview.widget.DividerItemDecoration;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.recyclerview.widget.SimpleItemAnimator;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
|
@ -147,6 +148,8 @@ public final class ViewThreadFragment extends SFragment implements
|
|||
recyclerView.setHasFixedSize(true);
|
||||
LinearLayoutManager layoutManager = new LinearLayoutManager(context);
|
||||
recyclerView.setLayoutManager(layoutManager);
|
||||
recyclerView.setAccessibilityDelegateCompat(
|
||||
new ListStatusAccessibilityDelegate(recyclerView, this, statuses::getPairedItem));
|
||||
DividerItemDecoration divider = new DividerItemDecoration(
|
||||
context, layoutManager.getOrientation());
|
||||
recyclerView.addItemDecoration(divider);
|
||||
|
@ -264,7 +267,7 @@ public final class ViewThreadFragment extends SFragment implements
|
|||
}
|
||||
|
||||
private void updateStatus(int position, Status status) {
|
||||
if(position >= 0 && position < statuses.size()) {
|
||||
if (position >= 0 && position < statuses.size()) {
|
||||
|
||||
Status actionableStatus = status.getActionableStatus();
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue