Follow requests list is available. Closes #222
This commit is contained in:
parent
41088de6be
commit
7d83a9aaba
18 changed files with 403 additions and 77 deletions
|
|
@ -21,14 +21,18 @@ import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.text.Spanned;
|
import android.text.Spanned;
|
||||||
|
import android.util.ArraySet;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
|
|
||||||
import com.keylesspalace.tusky.entity.Notification;
|
import com.keylesspalace.tusky.entity.Notification;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import okhttp3.Interceptor;
|
import okhttp3.Interceptor;
|
||||||
import okhttp3.OkHttpClient;
|
import okhttp3.OkHttpClient;
|
||||||
|
|
@ -64,10 +68,7 @@ public class MessagingService extends IntentService {
|
||||||
public void onResponse(Call<List<Notification>> call,
|
public void onResponse(Call<List<Notification>> call,
|
||||||
Response<List<Notification>> response) {
|
Response<List<Notification>> response) {
|
||||||
if (response.isSuccessful()) {
|
if (response.isSuccessful()) {
|
||||||
List<Notification> notificationList = response.body();
|
onNotificationsReceived(response.body());
|
||||||
for (Notification notification : notificationList) {
|
|
||||||
NotificationMaker.make(MessagingService.this, NOTIFY_ID, notification);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -111,4 +112,21 @@ public class MessagingService extends IntentService {
|
||||||
|
|
||||||
mastodonAPI = retrofit.create(MastodonAPI.class);
|
mastodonAPI = retrofit.create(MastodonAPI.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void onNotificationsReceived(List<Notification> notificationList) {
|
||||||
|
SharedPreferences notificationsPreferences = getSharedPreferences(
|
||||||
|
"Notifications", Context.MODE_PRIVATE);
|
||||||
|
Set<String> currentIds = notificationsPreferences.getStringSet(
|
||||||
|
"current_ids", new HashSet<String>());
|
||||||
|
for (Notification notification : notificationList) {
|
||||||
|
String id = notification.id;
|
||||||
|
if (!currentIds.contains(id)) {
|
||||||
|
currentIds.add(id);
|
||||||
|
NotificationMaker.make(this, NOTIFY_ID, notification);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
notificationsPreferences.edit()
|
||||||
|
.putStringSet("current_ids", currentIds)
|
||||||
|
.apply();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@
|
||||||
<activity android:name=".EditProfileActivity" />
|
<activity android:name=".EditProfileActivity" />
|
||||||
<activity android:name=".PreferencesActivity" />
|
<activity android:name=".PreferencesActivity" />
|
||||||
<activity android:name=".FavouritesActivity" />
|
<activity android:name=".FavouritesActivity" />
|
||||||
<activity android:name=".BlocksActivity" />
|
<activity android:name=".AccountListActivity" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".ReportActivity"
|
android:name=".ReportActivity"
|
||||||
android:windowSoftInputMode="stateVisible|adjustResize" />
|
android:windowSoftInputMode="stateVisible|adjustResize" />
|
||||||
|
|
|
||||||
|
|
@ -19,4 +19,5 @@ interface AccountActionListener {
|
||||||
void onViewAccount(String id);
|
void onViewAccount(String id);
|
||||||
void onMute(final boolean mute, final String id, final int position);
|
void onMute(final boolean mute, final String id, final int position);
|
||||||
void onBlock(final boolean block, final String id, final int position);
|
void onBlock(final boolean block, final String id, final int position);
|
||||||
|
void onRespondToFollowRequest(final boolean accept, final String id, final int position);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,16 +24,17 @@ import android.support.v7.app.ActionBar;
|
||||||
import android.support.v7.widget.Toolbar;
|
import android.support.v7.widget.Toolbar;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
|
|
||||||
public class BlocksActivity extends BaseActivity {
|
public class AccountListActivity extends BaseActivity {
|
||||||
enum Type {
|
enum Type {
|
||||||
BLOCKS,
|
BLOCKS,
|
||||||
MUTES
|
MUTES,
|
||||||
|
FOLLOW_REQUESTS,
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_blocks);
|
setContentView(R.layout.activity_account_list);
|
||||||
|
|
||||||
Type type;
|
Type type;
|
||||||
Intent intent = getIntent();
|
Intent intent = getIntent();
|
||||||
|
|
@ -48,21 +49,29 @@ public class BlocksActivity extends BaseActivity {
|
||||||
ActionBar bar = getSupportActionBar();
|
ActionBar bar = getSupportActionBar();
|
||||||
if (bar != null) {
|
if (bar != null) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case MUTES: { bar.setTitle(getString(R.string.title_mutes)); break; }
|
|
||||||
case BLOCKS: { bar.setTitle(getString(R.string.title_blocks)); break; }
|
case BLOCKS: { bar.setTitle(getString(R.string.title_blocks)); break; }
|
||||||
|
case MUTES: { bar.setTitle(getString(R.string.title_mutes)); break; }
|
||||||
|
case FOLLOW_REQUESTS: {
|
||||||
|
bar.setTitle(getString(R.string.title_follow_requests));
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
bar.setDisplayHomeAsUpEnabled(true);
|
bar.setDisplayHomeAsUpEnabled(true);
|
||||||
bar.setDisplayShowHomeEnabled(true);
|
bar.setDisplayShowHomeEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
|
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
|
||||||
AccountFragment.Type fragmentType;
|
AccountListFragment.Type fragmentType;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case MUTES: { fragmentType = AccountFragment.Type.MUTES; break; }
|
|
||||||
default:
|
default:
|
||||||
case BLOCKS: { fragmentType = AccountFragment.Type.BLOCKS; break; }
|
case BLOCKS: { fragmentType = AccountListFragment.Type.BLOCKS; break; }
|
||||||
|
case MUTES: { fragmentType = AccountListFragment.Type.MUTES; break; }
|
||||||
|
case FOLLOW_REQUESTS: {
|
||||||
|
fragmentType = AccountListFragment.Type.FOLLOW_REQUESTS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Fragment fragment = AccountFragment.newInstance(fragmentType);
|
Fragment fragment = AccountListFragment.newInstance(fragmentType);
|
||||||
fragmentTransaction.add(R.id.fragment_container, fragment);
|
fragmentTransaction.add(R.id.fragment_container, fragment);
|
||||||
fragmentTransaction.commit();
|
fragmentTransaction.commit();
|
||||||
}
|
}
|
||||||
|
|
@ -38,16 +38,15 @@ import retrofit2.Call;
|
||||||
import retrofit2.Callback;
|
import retrofit2.Callback;
|
||||||
import retrofit2.Response;
|
import retrofit2.Response;
|
||||||
|
|
||||||
public class AccountFragment extends BaseFragment implements AccountActionListener {
|
public class AccountListFragment extends BaseFragment implements AccountActionListener {
|
||||||
private static final String TAG = "Account"; // logging tag
|
private static final String TAG = "AccountList"; // logging tag
|
||||||
|
|
||||||
private Call<List<Account>> listCall;
|
|
||||||
|
|
||||||
public enum Type {
|
public enum Type {
|
||||||
FOLLOWS,
|
FOLLOWS,
|
||||||
FOLLOWERS,
|
FOLLOWERS,
|
||||||
BLOCKS,
|
BLOCKS,
|
||||||
MUTES,
|
MUTES,
|
||||||
|
FOLLOW_REQUESTS,
|
||||||
}
|
}
|
||||||
|
|
||||||
private Type type;
|
private Type type;
|
||||||
|
|
@ -59,17 +58,17 @@ public class AccountFragment extends BaseFragment implements AccountActionListen
|
||||||
private TabLayout.OnTabSelectedListener onTabSelectedListener;
|
private TabLayout.OnTabSelectedListener onTabSelectedListener;
|
||||||
private MastodonAPI api;
|
private MastodonAPI api;
|
||||||
|
|
||||||
public static AccountFragment newInstance(Type type) {
|
public static AccountListFragment newInstance(Type type) {
|
||||||
Bundle arguments = new Bundle();
|
Bundle arguments = new Bundle();
|
||||||
AccountFragment fragment = new AccountFragment();
|
AccountListFragment fragment = new AccountListFragment();
|
||||||
arguments.putSerializable("type", type);
|
arguments.putSerializable("type", type);
|
||||||
fragment.setArguments(arguments);
|
fragment.setArguments(arguments);
|
||||||
return fragment;
|
return fragment;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static AccountFragment newInstance(Type type, String accountId) {
|
public static AccountListFragment newInstance(Type type, String accountId) {
|
||||||
Bundle arguments = new Bundle();
|
Bundle arguments = new Bundle();
|
||||||
AccountFragment fragment = new AccountFragment();
|
AccountListFragment fragment = new AccountListFragment();
|
||||||
arguments.putSerializable("type", type);
|
arguments.putSerializable("type", type);
|
||||||
arguments.putString("accountId", accountId);
|
arguments.putString("accountId", accountId);
|
||||||
fragment.setArguments(arguments);
|
fragment.setArguments(arguments);
|
||||||
|
|
@ -90,7 +89,7 @@ public class AccountFragment extends BaseFragment implements AccountActionListen
|
||||||
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
|
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
|
||||||
@Nullable Bundle savedInstanceState) {
|
@Nullable Bundle savedInstanceState) {
|
||||||
|
|
||||||
View rootView = inflater.inflate(R.layout.fragment_account, container, false);
|
View rootView = inflater.inflate(R.layout.fragment_account_list, container, false);
|
||||||
|
|
||||||
Context context = getContext();
|
Context context = getContext();
|
||||||
recyclerView = (RecyclerView) rootView.findViewById(R.id.recycler_view);
|
recyclerView = (RecyclerView) rootView.findViewById(R.id.recycler_view);
|
||||||
|
|
@ -108,6 +107,8 @@ public class AccountFragment extends BaseFragment implements AccountActionListen
|
||||||
adapter = new BlocksAdapter(this);
|
adapter = new BlocksAdapter(this);
|
||||||
} else if (type == Type.MUTES) {
|
} else if (type == Type.MUTES) {
|
||||||
adapter = new MutesAdapter(this);
|
adapter = new MutesAdapter(this);
|
||||||
|
} else if (type == Type.FOLLOW_REQUESTS) {
|
||||||
|
adapter = new FollowRequestsAdapter(this);
|
||||||
} else {
|
} else {
|
||||||
adapter = new FollowAdapter(this);
|
adapter = new FollowAdapter(this);
|
||||||
}
|
}
|
||||||
|
|
@ -157,12 +158,6 @@ public class AccountFragment extends BaseFragment implements AccountActionListen
|
||||||
recyclerView.addOnScrollListener(scrollListener);
|
recyclerView.addOnScrollListener(scrollListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDestroy() {
|
|
||||||
super.onDestroy();
|
|
||||||
if (listCall != null) listCall.cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroyView() {
|
public void onDestroyView() {
|
||||||
if (jumpToTopAllowed()) {
|
if (jumpToTopAllowed()) {
|
||||||
|
|
@ -189,6 +184,7 @@ public class AccountFragment extends BaseFragment implements AccountActionListen
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Call<List<Account>> listCall;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
default:
|
default:
|
||||||
case FOLLOWS: {
|
case FOLLOWS: {
|
||||||
|
|
@ -207,6 +203,10 @@ public class AccountFragment extends BaseFragment implements AccountActionListen
|
||||||
listCall = api.mutes(fromId, uptoId, null);
|
listCall = api.mutes(fromId, uptoId, null);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case FOLLOW_REQUESTS: {
|
||||||
|
listCall = api.followRequests(fromId, uptoId, null);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
callList.add(listCall);
|
callList.add(listCall);
|
||||||
listCall.enqueue(cb);
|
listCall.enqueue(cb);
|
||||||
|
|
@ -239,12 +239,14 @@ public class AccountFragment extends BaseFragment implements AccountActionListen
|
||||||
Log.e(TAG, "Fetch failure: " + exception.getMessage());
|
Log.e(TAG, "Fetch failure: " + exception.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void onViewAccount(String id) {
|
public void onViewAccount(String id) {
|
||||||
Intent intent = new Intent(getContext(), AccountActivity.class);
|
Intent intent = new Intent(getContext(), AccountActivity.class);
|
||||||
intent.putExtra("id", id);
|
intent.putExtra("id", id);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void onMute(final boolean mute, final String id, final int position) {
|
public void onMute(final boolean mute, final String id, final int position) {
|
||||||
if (api == null) {
|
if (api == null) {
|
||||||
/* If somehow an unmute button is clicked after onCreateView but before
|
/* If somehow an unmute button is clicked after onCreateView but before
|
||||||
|
|
@ -308,6 +310,7 @@ public class AccountFragment extends BaseFragment implements AccountActionListen
|
||||||
Log.e(TAG, String.format("Failed to %s account id %s", verb, id));
|
Log.e(TAG, String.format("Failed to %s account id %s", verb, id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void onBlock(final boolean block, final String id, final int position) {
|
public void onBlock(final boolean block, final String id, final int position) {
|
||||||
if (api == null) {
|
if (api == null) {
|
||||||
/* If somehow an unblock button is clicked after onCreateView but before
|
/* If somehow an unblock button is clicked after onCreateView but before
|
||||||
|
|
@ -371,6 +374,54 @@ public class AccountFragment extends BaseFragment implements AccountActionListen
|
||||||
Log.e(TAG, String.format("Failed to %s account id %s", verb, id));
|
Log.e(TAG, String.format("Failed to %s account id %s", verb, id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRespondToFollowRequest(final boolean accept, final String accountId,
|
||||||
|
final int position) {
|
||||||
|
if (api == null) {
|
||||||
|
/* If somehow an response button is clicked after onCreateView but before
|
||||||
|
* onActivityCreated, then this would get called with a null api object, so this eats
|
||||||
|
* that input. */
|
||||||
|
Log.d(TAG, "MastodonAPI isn't initialised, so follow requests can't be responded to.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Callback<Relationship> callback = new Callback<Relationship>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(Call<Relationship> call, Response<Relationship> response) {
|
||||||
|
if (response.isSuccessful()) {
|
||||||
|
onRespondToFollowRequestSuccess(position);
|
||||||
|
} else {
|
||||||
|
onRespondToFollowRequestFailure(accept, accountId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Call<Relationship> call, Throwable t) {
|
||||||
|
onRespondToFollowRequestFailure(accept, accountId);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Call<Relationship> call;
|
||||||
|
if (accept) {
|
||||||
|
call = api.authorizeFollowRequest(accountId);
|
||||||
|
} else {
|
||||||
|
call = api.rejectFollowRequest(accountId);
|
||||||
|
}
|
||||||
|
callList.add(call);
|
||||||
|
call.enqueue(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onRespondToFollowRequestSuccess(int position) {
|
||||||
|
FollowRequestsAdapter followRequestsAdapter = (FollowRequestsAdapter) adapter;
|
||||||
|
followRequestsAdapter.removeItem(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onRespondToFollowRequestFailure(boolean accept, String accountId) {
|
||||||
|
String verb = (accept) ? "accept" : "reject";
|
||||||
|
String message = String.format("Failed to %s account id %s.", verb, accountId);
|
||||||
|
Log.e(TAG, message);
|
||||||
|
}
|
||||||
|
|
||||||
private boolean jumpToTopAllowed() {
|
private boolean jumpToTopAllowed() {
|
||||||
return type == Type.FOLLOWS || type == Type.FOLLOWERS;
|
return type == Type.FOLLOWS || type == Type.FOLLOWERS;
|
||||||
}
|
}
|
||||||
|
|
@ -51,10 +51,10 @@ class AccountPagerAdapter extends FragmentPagerAdapter {
|
||||||
return TimelineFragment.newInstance(TimelineFragment.Kind.USER, accountId);
|
return TimelineFragment.newInstance(TimelineFragment.Kind.USER, accountId);
|
||||||
}
|
}
|
||||||
case 1: {
|
case 1: {
|
||||||
return AccountFragment.newInstance(AccountFragment.Type.FOLLOWS, accountId);
|
return AccountListFragment.newInstance(AccountListFragment.Type.FOLLOWS, accountId);
|
||||||
}
|
}
|
||||||
case 2: {
|
case 2: {
|
||||||
return AccountFragment.newInstance(AccountFragment.Type.FOLLOWERS, accountId);
|
return AccountListFragment.newInstance(AccountListFragment.Type.FOLLOWERS, accountId);
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,129 @@
|
||||||
|
/* Copyright 2017 Andrew Dawson
|
||||||
|
*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import android.support.v7.widget.RecyclerView;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ImageButton;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.keylesspalace.tusky.entity.Account;
|
||||||
|
import com.pkmmte.view.CircularImageView;
|
||||||
|
import com.squareup.picasso.Picasso;
|
||||||
|
|
||||||
|
import butterknife.BindView;
|
||||||
|
import butterknife.ButterKnife;
|
||||||
|
|
||||||
|
class FollowRequestsAdapter extends AccountAdapter {
|
||||||
|
private static final int VIEW_TYPE_FOLLOW_REQUEST = 0;
|
||||||
|
private static final int VIEW_TYPE_FOOTER = 1;
|
||||||
|
|
||||||
|
FollowRequestsAdapter(AccountActionListener accountActionListener) {
|
||||||
|
super(accountActionListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||||
|
switch (viewType) {
|
||||||
|
default:
|
||||||
|
case VIEW_TYPE_FOLLOW_REQUEST: {
|
||||||
|
View view = LayoutInflater.from(parent.getContext())
|
||||||
|
.inflate(R.layout.item_follow_request, parent, false);
|
||||||
|
return new FollowRequestViewHolder(view);
|
||||||
|
}
|
||||||
|
case VIEW_TYPE_FOOTER: {
|
||||||
|
View view = LayoutInflater.from(parent.getContext())
|
||||||
|
.inflate(R.layout.item_footer, parent, false);
|
||||||
|
return new FooterViewHolder(view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
|
||||||
|
if (position < accountList.size()) {
|
||||||
|
FollowRequestViewHolder holder = (FollowRequestViewHolder) viewHolder;
|
||||||
|
holder.setupWithAccount(accountList.get(position));
|
||||||
|
holder.setupActionListener(accountActionListener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemViewType(int position) {
|
||||||
|
if (position == accountList.size()) {
|
||||||
|
return VIEW_TYPE_FOOTER;
|
||||||
|
} else {
|
||||||
|
return VIEW_TYPE_FOLLOW_REQUEST;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class FollowRequestViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
@BindView(R.id.follow_request_avatar) CircularImageView avatar;
|
||||||
|
@BindView(R.id.follow_request_username) TextView username;
|
||||||
|
@BindView(R.id.follow_request_display_name) TextView displayName;
|
||||||
|
@BindView(R.id.follow_request_accept) ImageButton accept;
|
||||||
|
@BindView(R.id.follow_request_reject) ImageButton reject;
|
||||||
|
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
FollowRequestViewHolder(View itemView) {
|
||||||
|
super(itemView);
|
||||||
|
ButterKnife.bind(this, itemView);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setupWithAccount(Account account) {
|
||||||
|
id = account.id;
|
||||||
|
displayName.setText(account.getDisplayName());
|
||||||
|
String format = username.getContext().getString(R.string.status_username_format);
|
||||||
|
String formattedUsername = String.format(format, account.username);
|
||||||
|
username.setText(formattedUsername);
|
||||||
|
Picasso.with(avatar.getContext())
|
||||||
|
.load(account.avatar)
|
||||||
|
.error(R.drawable.avatar_error)
|
||||||
|
.placeholder(R.drawable.avatar_default)
|
||||||
|
.into(avatar);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setupActionListener(final AccountActionListener listener) {
|
||||||
|
accept.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
int position = getAdapterPosition();
|
||||||
|
if (position != RecyclerView.NO_POSITION) {
|
||||||
|
listener.onRespondToFollowRequest(true, id, position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
reject.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
int position = getAdapterPosition();
|
||||||
|
if (position != RecyclerView.NO_POSITION) {
|
||||||
|
listener.onRespondToFollowRequest(false, id, position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
avatar.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
listener.onViewAccount(id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -304,18 +304,22 @@ public class MainActivity extends BaseActivity implements SFragment.OnUserRemove
|
||||||
Intent intent = new Intent(MainActivity.this, FavouritesActivity.class);
|
Intent intent = new Intent(MainActivity.this, FavouritesActivity.class);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
} else if (drawerItemIdentifier == 2) {
|
} else if (drawerItemIdentifier == 2) {
|
||||||
Intent intent = new Intent(MainActivity.this, BlocksActivity.class);
|
Intent intent = new Intent(MainActivity.this, AccountListActivity.class);
|
||||||
intent.putExtra("type", BlocksActivity.Type.MUTES);
|
intent.putExtra("type", AccountListActivity.Type.MUTES);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
} else if (drawerItemIdentifier == 3) {
|
} else if (drawerItemIdentifier == 3) {
|
||||||
Intent intent = new Intent(MainActivity.this, BlocksActivity.class);
|
Intent intent = new Intent(MainActivity.this, AccountListActivity.class);
|
||||||
intent.putExtra("type", BlocksActivity.Type.BLOCKS);
|
intent.putExtra("type", AccountListActivity.Type.BLOCKS);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
} else if (drawerItemIdentifier == 4) {
|
} else if (drawerItemIdentifier == 4) {
|
||||||
Intent intent = new Intent(MainActivity.this, PreferencesActivity.class);
|
Intent intent = new Intent(MainActivity.this, PreferencesActivity.class);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
} else if (drawerItemIdentifier == 5) {
|
} else if (drawerItemIdentifier == 5) {
|
||||||
logout();
|
logout();
|
||||||
|
} else if (drawerItemIdentifier == 6) {
|
||||||
|
Intent intent = new Intent(MainActivity.this, AccountListActivity.class);
|
||||||
|
intent.putExtra("type", AccountListActivity.Type.FOLLOW_REQUESTS);
|
||||||
|
startActivity(intent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -443,36 +447,7 @@ public class MainActivity extends BaseActivity implements SFragment.OnUserRemove
|
||||||
onFetchUserInfoFailure(new Exception(response.message()));
|
onFetchUserInfoFailure(new Exception(response.message()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
onFetchUserInfoSuccess(response.body(), domain);
|
||||||
headerResult.clear();
|
|
||||||
|
|
||||||
Account me = response.body();
|
|
||||||
ImageView background = headerResult.getHeaderBackgroundView();
|
|
||||||
int backgroundWidth = background.getWidth();
|
|
||||||
int backgroundHeight = background.getHeight();
|
|
||||||
if (backgroundWidth == 0 || backgroundHeight == 0) {
|
|
||||||
/* The header ImageView may not be layed out when the verify credentials call
|
|
||||||
* returns so measure the dimensions and use those. */
|
|
||||||
background.measure(View.MeasureSpec.EXACTLY, View.MeasureSpec.EXACTLY);
|
|
||||||
backgroundWidth = background.getMeasuredWidth();
|
|
||||||
backgroundHeight = background.getMeasuredHeight();
|
|
||||||
}
|
|
||||||
|
|
||||||
Picasso.with(MainActivity.this)
|
|
||||||
.load(me.header)
|
|
||||||
.placeholder(R.drawable.account_header_missing)
|
|
||||||
.resize(backgroundWidth, backgroundHeight)
|
|
||||||
.centerCrop()
|
|
||||||
.into(background);
|
|
||||||
|
|
||||||
headerResult.addProfiles(
|
|
||||||
new ProfileDrawerItem()
|
|
||||||
.withName(me.getDisplayName())
|
|
||||||
.withEmail(String.format("%s@%s", me.username, domain))
|
|
||||||
.withIcon(me.avatar)
|
|
||||||
);
|
|
||||||
|
|
||||||
onFetchUserInfoSuccess(me.id, me.username);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -482,9 +457,48 @@ public class MainActivity extends BaseActivity implements SFragment.OnUserRemove
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onFetchUserInfoSuccess(String id, String username) {
|
private void onFetchUserInfoSuccess(Account me, String domain) {
|
||||||
loggedInAccountId = id;
|
// Add the header image and avatar from the account, into the navigation drawer header.
|
||||||
loggedInAccountUsername = username;
|
headerResult.clear();
|
||||||
|
|
||||||
|
ImageView background = headerResult.getHeaderBackgroundView();
|
||||||
|
int backgroundWidth = background.getWidth();
|
||||||
|
int backgroundHeight = background.getHeight();
|
||||||
|
if (backgroundWidth == 0 || backgroundHeight == 0) {
|
||||||
|
/* The header ImageView may not be layed out when the verify credentials call returns so
|
||||||
|
* measure the dimensions and use those. */
|
||||||
|
background.measure(View.MeasureSpec.EXACTLY, View.MeasureSpec.EXACTLY);
|
||||||
|
backgroundWidth = background.getMeasuredWidth();
|
||||||
|
backgroundHeight = background.getMeasuredHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
Picasso.with(MainActivity.this)
|
||||||
|
.load(me.header)
|
||||||
|
.placeholder(R.drawable.account_header_missing)
|
||||||
|
.resize(backgroundWidth, backgroundHeight)
|
||||||
|
.centerCrop()
|
||||||
|
.into(background);
|
||||||
|
|
||||||
|
headerResult.addProfiles(
|
||||||
|
new ProfileDrawerItem()
|
||||||
|
.withName(me.getDisplayName())
|
||||||
|
.withEmail(String.format("%s@%s", me.username, domain))
|
||||||
|
.withIcon(me.avatar)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Show follow requests in the menu, if this is a locked account.
|
||||||
|
if (me.locked) {
|
||||||
|
PrimaryDrawerItem followRequestsItem = new PrimaryDrawerItem()
|
||||||
|
.withIdentifier(6)
|
||||||
|
.withName(R.string.action_view_follow_requests)
|
||||||
|
.withSelectable(false)
|
||||||
|
.withIcon(GoogleMaterial.Icon.gmd_person_add);
|
||||||
|
drawer.addItemAtPosition(followRequestsItem, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the current login information.
|
||||||
|
loggedInAccountId = me.id;
|
||||||
|
loggedInAccountUsername = me.username;
|
||||||
getPrivatePreferences().edit()
|
getPrivatePreferences().edit()
|
||||||
.putString("loggedInAccountId", loggedInAccountId)
|
.putString("loggedInAccountId", loggedInAccountId)
|
||||||
.putString("loggedInAccountUsername", loggedInAccountUsername)
|
.putString("loggedInAccountUsername", loggedInAccountUsername)
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
<vector android:height="24dp" android:viewportHeight="35.43307"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:viewportWidth="35.43307" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
android:width="24dp"
|
||||||
<path android:fillAlpha="1" android:fillColor="#ffffff"
|
android:height="24dp"
|
||||||
android:pathData="M32.16,4.46L31.62,5.01L14.63,21.99L5.78,13.13L2.5,16.41L14.52,28.43L14.55,28.41L14.66,28.52L35.44,7.74L34.89,7.19C34.17,6.46 33.44,5.74 32.71,5.01L32.16,4.46z" />
|
android:viewportWidth="24.0"
|
||||||
<path android:fillAlpha="1" android:fillColor="#ffffff"
|
android:viewportHeight="24.0">
|
||||||
android:pathData="m1.1,6.19c-0.58,0 -1.07,0.49 -1.07,1.07l0,23.06c0,0.58 0.49,1.07 1.07,1.07l23.06,0c0.58,0 1.07,-0.49 1.07,-1.07l0,-18.89 -1.54,1.54 0,16.88 -22.12,0 0,-22.12 22.12,0 0,2.83 1.54,-1.54 0,-1.76c0,-0.58 -0.49,-1.07 -1.07,-1.07l-23.06,0z" />
|
<path
|
||||||
|
android:fillColor="#FFFFFFFF"
|
||||||
|
android:pathData="M9,16.17L4.83,12l-1.42,1.41L9,19 21,7l-1.41,-1.41z"/>
|
||||||
</vector>
|
</vector>
|
||||||
|
|
|
||||||
7
app/src/main/res/drawable/ic_check_in_box_24dp.xml
Normal file
7
app/src/main/res/drawable/ic_check_in_box_24dp.xml
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
<vector android:height="24dp" android:viewportHeight="35.43307"
|
||||||
|
android:viewportWidth="35.43307" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillAlpha="1" android:fillColor="#ffffff"
|
||||||
|
android:pathData="M32.16,4.46L31.62,5.01L14.63,21.99L5.78,13.13L2.5,16.41L14.52,28.43L14.55,28.41L14.66,28.52L35.44,7.74L34.89,7.19C34.17,6.46 33.44,5.74 32.71,5.01L32.16,4.46z" />
|
||||||
|
<path android:fillAlpha="1" android:fillColor="#ffffff"
|
||||||
|
android:pathData="m1.1,6.19c-0.58,0 -1.07,0.49 -1.07,1.07l0,23.06c0,0.58 0.49,1.07 1.07,1.07l23.06,0c0.58,0 1.07,-0.49 1.07,-1.07l0,-18.89 -1.54,1.54 0,16.88 -22.12,0 0,-22.12 22.12,0 0,2.83 1.54,-1.54 0,-1.76c0,-0.58 -0.49,-1.07 -1.07,-1.07l-23.06,0z" />
|
||||||
|
</vector>
|
||||||
9
app/src/main/res/drawable/ic_reject_24dp.xml
Normal file
9
app/src/main/res/drawable/ic_reject_24dp.xml
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24.0"
|
||||||
|
android:viewportHeight="24.0">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFFFF"
|
||||||
|
android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z"/>
|
||||||
|
</vector>
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
android:id="@+id/activity_view_thread"
|
android:id="@+id/activity_view_thread"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
tools:context="com.keylesspalace.tusky.BlocksActivity">
|
tools:context="com.keylesspalace.tusky.AccountListActivity">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
@ -13,7 +13,8 @@
|
||||||
android:id="@+id/blocked_user_avatar"
|
android:id="@+id/blocked_user_avatar"
|
||||||
android:layout_alignParentLeft="true"
|
android:layout_alignParentLeft="true"
|
||||||
android:layout_marginRight="24dp"
|
android:layout_marginRight="24dp"
|
||||||
android:layout_centerVertical="true"/>
|
android:layout_centerVertical="true"
|
||||||
|
android:contentDescription="@string/action_view_profile" />
|
||||||
|
|
||||||
<ImageButton
|
<ImageButton
|
||||||
app:srcCompat="@drawable/ic_clear_24dp"
|
app:srcCompat="@drawable/ic_clear_24dp"
|
||||||
|
|
|
||||||
80
app/src/main/res/layout/item_follow_request.xml
Normal file
80
app/src/main/res/layout/item_follow_request.xml
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="72dp"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:paddingLeft="16dp"
|
||||||
|
android:paddingRight="16dp"
|
||||||
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
|
<com.pkmmte.view.CircularImageView
|
||||||
|
android:layout_width="48dp"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:id="@+id/follow_request_avatar"
|
||||||
|
android:layout_alignParentLeft="true"
|
||||||
|
android:layout_alignParentStart="true"
|
||||||
|
android:layout_marginRight="24dp"
|
||||||
|
android:layout_marginEnd="24dp"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:contentDescription="@string/action_view_profile" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_toRightOf="@id/follow_request_avatar"
|
||||||
|
android:layout_toEndOf="@id/follow_request_avatar"
|
||||||
|
android:layout_toLeftOf="@+id/follow_request_accept"
|
||||||
|
android:layout_toStartOf="@id/follow_request_accept">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:id="@+id/follow_request_display_name"
|
||||||
|
android:text="Display name"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textColor="?android:textColorPrimary"
|
||||||
|
android:textStyle="normal|bold" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="\@username"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:id="@+id/follow_request_username"
|
||||||
|
android:textColor="?android:textColorSecondary" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
style="?attr/image_button_style"
|
||||||
|
android:id="@+id/follow_request_accept"
|
||||||
|
app:srcCompat="@drawable/ic_check_24dp"
|
||||||
|
android:layout_toLeftOf="@+id/follow_request_reject"
|
||||||
|
android:layout_toStartOf="@id/follow_request_reject"
|
||||||
|
android:layout_marginLeft="16dp"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:contentDescription="@string/action_accept" />
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
style="?attr/image_button_style"
|
||||||
|
android:id="@id/follow_request_reject"
|
||||||
|
app:srcCompat="@drawable/ic_reject_24dp"
|
||||||
|
android:layout_alignParentRight="true"
|
||||||
|
android:layout_alignParentEnd="true"
|
||||||
|
android:layout_marginLeft="16dp"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:contentDescription="@string/action_reject" />
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
@ -13,7 +13,8 @@
|
||||||
android:id="@+id/muted_user_avatar"
|
android:id="@+id/muted_user_avatar"
|
||||||
android:layout_alignParentLeft="true"
|
android:layout_alignParentLeft="true"
|
||||||
android:layout_marginRight="24dp"
|
android:layout_marginRight="24dp"
|
||||||
android:layout_centerVertical="true"/>
|
android:layout_centerVertical="true"
|
||||||
|
android:contentDescription="@string/action_view_profile" />
|
||||||
|
|
||||||
<ImageButton
|
<ImageButton
|
||||||
app:srcCompat="@drawable/ic_unmute_24dp"
|
app:srcCompat="@drawable/ic_unmute_24dp"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_save"
|
android:id="@+id/action_save"
|
||||||
android:icon="@drawable/ic_check_24dp"
|
android:icon="@drawable/ic_check_in_box_24dp"
|
||||||
android:title="@string/action_save"
|
android:title="@string/action_save"
|
||||||
app:showAsAction="always" />
|
app:showAsAction="always" />
|
||||||
</menu>
|
</menu>
|
||||||
|
|
@ -31,6 +31,7 @@
|
||||||
<string name="title_favourites">Favourites</string>
|
<string name="title_favourites">Favourites</string>
|
||||||
<string name="title_mutes">Muted users</string>
|
<string name="title_mutes">Muted users</string>
|
||||||
<string name="title_blocks">Blocked users</string>
|
<string name="title_blocks">Blocked users</string>
|
||||||
|
<string name="title_follow_requests">Follow Requests</string>
|
||||||
|
|
||||||
<string name="status_username_format">\@%s</string>
|
<string name="status_username_format">\@%s</string>
|
||||||
<string name="status_boosted_format">%s boosted</string>
|
<string name="status_boosted_format">%s boosted</string>
|
||||||
|
|
@ -78,6 +79,7 @@
|
||||||
<string name="action_view_favourites">Favourites</string>
|
<string name="action_view_favourites">Favourites</string>
|
||||||
<string name="action_view_mutes">Muted users</string>
|
<string name="action_view_mutes">Muted users</string>
|
||||||
<string name="action_view_blocks">Blocked users</string>
|
<string name="action_view_blocks">Blocked users</string>
|
||||||
|
<string name="action_view_follow_requests">Follow Requests</string>
|
||||||
<string name="action_view_thread">Thread</string>
|
<string name="action_view_thread">Thread</string>
|
||||||
<string name="action_view_media">Media</string>
|
<string name="action_view_media">Media</string>
|
||||||
<string name="action_open_in_web">Open in browser</string>
|
<string name="action_open_in_web">Open in browser</string>
|
||||||
|
|
@ -95,6 +97,8 @@
|
||||||
<string name="action_save">Save</string>
|
<string name="action_save">Save</string>
|
||||||
<string name="action_edit_profile">Edit profile</string>
|
<string name="action_edit_profile">Edit profile</string>
|
||||||
<string name="action_undo">Undo</string>
|
<string name="action_undo">Undo</string>
|
||||||
|
<string name="action_accept">Accept</string>
|
||||||
|
<string name="action_reject">Reject</string>
|
||||||
|
|
||||||
<string name="send_status_link_to">Share toot URL to…</string>
|
<string name="send_status_link_to">Share toot URL to…</string>
|
||||||
<string name="send_status_content_to">Share toot to…</string>
|
<string name="send_status_content_to">Share toot to…</string>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue