a5cffe0fea
* Add Dagger DI * Preemptively fix tests * Add missing licenses * DI fixes * ci fixes
710 lines
26 KiB
Java
710 lines
26 KiB
Java
/* 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.app.AlertDialog;
|
|
import android.content.Context;
|
|
import android.content.DialogInterface;
|
|
import android.content.Intent;
|
|
import android.graphics.Color;
|
|
import android.graphics.drawable.Drawable;
|
|
import android.os.Bundle;
|
|
import android.preference.PreferenceManager;
|
|
import android.support.annotation.AttrRes;
|
|
import android.support.annotation.NonNull;
|
|
import android.support.annotation.Nullable;
|
|
import android.support.design.widget.AppBarLayout;
|
|
import android.support.design.widget.CollapsingToolbarLayout;
|
|
import android.support.design.widget.FloatingActionButton;
|
|
import android.support.design.widget.Snackbar;
|
|
import android.support.design.widget.TabLayout;
|
|
import android.support.v4.app.Fragment;
|
|
import android.support.v4.content.LocalBroadcastManager;
|
|
import android.support.v4.view.ViewCompat;
|
|
import android.support.v4.view.ViewPager;
|
|
import android.support.v7.app.ActionBar;
|
|
import android.support.v7.widget.Toolbar;
|
|
import android.util.Log;
|
|
import android.view.Menu;
|
|
import android.view.MenuItem;
|
|
import android.view.View;
|
|
import android.view.ViewGroup;
|
|
import android.widget.Button;
|
|
import android.widget.ImageView;
|
|
import android.widget.TextView;
|
|
|
|
import com.keylesspalace.tusky.db.AccountEntity;
|
|
import com.keylesspalace.tusky.db.AccountManager;
|
|
import com.keylesspalace.tusky.entity.Account;
|
|
import com.keylesspalace.tusky.entity.Relationship;
|
|
import com.keylesspalace.tusky.interfaces.ActionButtonActivity;
|
|
import com.keylesspalace.tusky.interfaces.LinkListener;
|
|
import com.keylesspalace.tusky.network.MastodonApi;
|
|
import com.keylesspalace.tusky.pager.AccountPagerAdapter;
|
|
import com.keylesspalace.tusky.receiver.TimelineReceiver;
|
|
import com.keylesspalace.tusky.util.Assert;
|
|
import com.keylesspalace.tusky.util.LinkHelper;
|
|
import com.keylesspalace.tusky.util.ThemeUtils;
|
|
import com.pkmmte.view.CircularImageView;
|
|
import com.squareup.picasso.Picasso;
|
|
|
|
import java.text.NumberFormat;
|
|
import java.util.ArrayList;
|
|
import java.util.Collections;
|
|
import java.util.List;
|
|
|
|
import javax.inject.Inject;
|
|
|
|
import dagger.android.AndroidInjector;
|
|
import dagger.android.DispatchingAndroidInjector;
|
|
import dagger.android.support.HasSupportFragmentInjector;
|
|
import retrofit2.Call;
|
|
import retrofit2.Callback;
|
|
import retrofit2.Response;
|
|
|
|
public final class AccountActivity extends BaseActivity implements ActionButtonActivity,
|
|
HasSupportFragmentInjector {
|
|
private static final String TAG = "AccountActivity"; // logging tag
|
|
|
|
private enum FollowState {
|
|
NOT_FOLLOWING,
|
|
FOLLOWING,
|
|
REQUESTED,
|
|
}
|
|
|
|
@Inject
|
|
public MastodonApi mastodonApi;
|
|
@Inject
|
|
public DispatchingAndroidInjector<Fragment> dispatchingAndroidInjector;
|
|
|
|
private String accountId;
|
|
private FollowState followState;
|
|
private boolean blocking;
|
|
private boolean muting;
|
|
private boolean isSelf;
|
|
private Account loadedAccount;
|
|
|
|
private CircularImageView avatar;
|
|
private ImageView header;
|
|
private FloatingActionButton floatingBtn;
|
|
private Button followBtn;
|
|
private TextView followsYouView;
|
|
private TabLayout tabLayout;
|
|
private ImageView accountLockedView;
|
|
private View container;
|
|
private TextView followersTextView;
|
|
private TextView followingTextView;
|
|
private TextView statusesTextView;
|
|
|
|
private boolean hideFab;
|
|
private int oldOffset;
|
|
|
|
@Override
|
|
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
|
super.onCreate(savedInstanceState);
|
|
setContentView(R.layout.activity_account);
|
|
|
|
avatar = findViewById(R.id.account_avatar);
|
|
header = findViewById(R.id.account_header);
|
|
floatingBtn = findViewById(R.id.floating_btn);
|
|
followBtn = findViewById(R.id.follow_btn);
|
|
followsYouView = findViewById(R.id.account_follows_you);
|
|
tabLayout = findViewById(R.id.tab_layout);
|
|
accountLockedView = findViewById(R.id.account_locked);
|
|
container = findViewById(R.id.activity_account);
|
|
followersTextView = findViewById(R.id.followers_tv);
|
|
followingTextView = findViewById(R.id.following_tv);
|
|
statusesTextView = findViewById(R.id.statuses_btn);
|
|
|
|
if (savedInstanceState != null) {
|
|
accountId = savedInstanceState.getString("accountId");
|
|
followState = (FollowState) savedInstanceState.getSerializable("followState");
|
|
blocking = savedInstanceState.getBoolean("blocking");
|
|
muting = savedInstanceState.getBoolean("muting");
|
|
} else {
|
|
Intent intent = getIntent();
|
|
accountId = intent.getStringExtra("id");
|
|
followState = FollowState.NOT_FOLLOWING;
|
|
blocking = false;
|
|
muting = false;
|
|
}
|
|
loadedAccount = null;
|
|
|
|
// Setup the toolbar.
|
|
final Toolbar toolbar = findViewById(R.id.toolbar);
|
|
setSupportActionBar(toolbar);
|
|
ActionBar actionBar = getSupportActionBar();
|
|
if (actionBar != null) {
|
|
actionBar.setTitle(null);
|
|
actionBar.setDisplayHomeAsUpEnabled(true);
|
|
actionBar.setDisplayShowHomeEnabled(true);
|
|
}
|
|
|
|
hideFab = PreferenceManager.getDefaultSharedPreferences(this).getBoolean("fabHide", false);
|
|
|
|
// Add a listener to change the toolbar icon color when it enters/exits its collapsed state.
|
|
AppBarLayout appBarLayout = findViewById(R.id.account_app_bar_layout);
|
|
final CollapsingToolbarLayout collapsingToolbar = findViewById(R.id.collapsing_toolbar);
|
|
appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
|
|
@AttrRes
|
|
int priorAttribute = R.attr.account_toolbar_icon_tint_uncollapsed;
|
|
|
|
@Override
|
|
public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
|
|
@AttrRes int attribute;
|
|
if (collapsingToolbar.getHeight() + verticalOffset
|
|
< 2 * ViewCompat.getMinimumHeight(collapsingToolbar)) {
|
|
|
|
toolbar.setTitleTextColor(ThemeUtils.getColor(AccountActivity.this,
|
|
android.R.attr.textColorPrimary));
|
|
toolbar.setSubtitleTextColor(ThemeUtils.getColor(AccountActivity.this,
|
|
android.R.attr.textColorSecondary));
|
|
|
|
attribute = R.attr.account_toolbar_icon_tint_collapsed;
|
|
} else {
|
|
toolbar.setTitleTextColor(Color.TRANSPARENT);
|
|
toolbar.setSubtitleTextColor(Color.TRANSPARENT);
|
|
|
|
attribute = R.attr.account_toolbar_icon_tint_uncollapsed;
|
|
}
|
|
if (attribute != priorAttribute) {
|
|
priorAttribute = attribute;
|
|
Context context = toolbar.getContext();
|
|
ThemeUtils.setDrawableTint(context, toolbar.getNavigationIcon(), attribute);
|
|
ThemeUtils.setDrawableTint(context, toolbar.getOverflowIcon(), attribute);
|
|
}
|
|
|
|
if (floatingBtn != null && hideFab && !isSelf && !blocking) {
|
|
if (verticalOffset > oldOffset) {
|
|
floatingBtn.show();
|
|
}
|
|
if (verticalOffset < oldOffset) {
|
|
floatingBtn.hide();
|
|
}
|
|
}
|
|
oldOffset = verticalOffset;
|
|
}
|
|
});
|
|
|
|
// Initialise the default UI states.
|
|
floatingBtn.hide();
|
|
followBtn.setVisibility(View.GONE);
|
|
followsYouView.setVisibility(View.GONE);
|
|
|
|
// Obtain information to fill out the profile.
|
|
obtainAccount();
|
|
|
|
AccountEntity activeAccount = TuskyApplication.getInstance(this).getServiceLocator()
|
|
.get(AccountManager.class).getActiveAccount();
|
|
|
|
if (accountId.equals(activeAccount.getAccountId())) {
|
|
isSelf = true;
|
|
} else {
|
|
isSelf = false;
|
|
obtainRelationships();
|
|
}
|
|
|
|
// Setup the tabs and timeline pager.
|
|
AccountPagerAdapter adapter = new AccountPagerAdapter(getSupportFragmentManager(),
|
|
accountId);
|
|
String[] pageTitles = {
|
|
getString(R.string.title_statuses),
|
|
getString(R.string.title_media)
|
|
};
|
|
adapter.setPageTitles(pageTitles);
|
|
final ViewPager viewPager = findViewById(R.id.pager);
|
|
int pageMargin = getResources().getDimensionPixelSize(R.dimen.tab_page_margin);
|
|
viewPager.setPageMargin(pageMargin);
|
|
Drawable pageMarginDrawable = ThemeUtils.getDrawable(this, R.attr.tab_page_margin_drawable,
|
|
R.drawable.tab_page_margin_dark);
|
|
viewPager.setPageMarginDrawable(pageMarginDrawable);
|
|
viewPager.setAdapter(adapter);
|
|
viewPager.setOffscreenPageLimit(0);
|
|
tabLayout.setupWithViewPager(viewPager);
|
|
|
|
View.OnClickListener accountListClickListener = v -> {
|
|
AccountListActivity.Type type;
|
|
switch (v.getId()) {
|
|
case R.id.followers_tv:
|
|
type = AccountListActivity.Type.FOLLOWERS;
|
|
break;
|
|
case R.id.following_tv:
|
|
type = AccountListActivity.Type.FOLLOWING;
|
|
break;
|
|
default:
|
|
throw new AssertionError();
|
|
}
|
|
Intent intent = AccountListActivity.newIntent(AccountActivity.this, type,
|
|
accountId);
|
|
startActivity(intent);
|
|
};
|
|
followersTextView.setOnClickListener(accountListClickListener);
|
|
followingTextView.setOnClickListener(accountListClickListener);
|
|
|
|
statusesTextView.setOnClickListener(v -> {
|
|
// Make nice ripple effect on tab
|
|
|
|
//noinspection ConstantConditions
|
|
tabLayout.getTabAt(0).select();
|
|
final View poorTabView = ((ViewGroup) tabLayout.getChildAt(0)).getChildAt(0);
|
|
poorTabView.setPressed(true);
|
|
tabLayout.postDelayed(() -> poorTabView.setPressed(false), 300);
|
|
});
|
|
}
|
|
|
|
@Override
|
|
protected void onSaveInstanceState(Bundle outState) {
|
|
outState.putString("accountId", accountId);
|
|
outState.putSerializable("followState", followState);
|
|
outState.putBoolean("blocking", blocking);
|
|
outState.putBoolean("muting", muting);
|
|
super.onSaveInstanceState(outState);
|
|
}
|
|
|
|
private void obtainAccount() {
|
|
mastodonApi.account(accountId).enqueue(new Callback<Account>() {
|
|
@Override
|
|
public void onResponse(@NonNull Call<Account> call,
|
|
@NonNull Response<Account> response) {
|
|
if (response.isSuccessful()) {
|
|
onObtainAccountSuccess(response.body());
|
|
} else {
|
|
onObtainAccountFailure();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onFailure(@NonNull Call<Account> call, @NonNull Throwable t) {
|
|
onObtainAccountFailure();
|
|
}
|
|
});
|
|
}
|
|
|
|
private void onObtainAccountSuccess(Account account) {
|
|
loadedAccount = account;
|
|
|
|
TextView username = findViewById(R.id.account_username);
|
|
TextView displayName = findViewById(R.id.account_display_name);
|
|
TextView note = findViewById(R.id.account_note);
|
|
|
|
String usernameFormatted = String.format(
|
|
getString(R.string.status_username_format), account.getUsername());
|
|
username.setText(usernameFormatted);
|
|
|
|
displayName.setText(account.getName());
|
|
|
|
if (getSupportActionBar() != null) {
|
|
getSupportActionBar().setTitle(account.getName());
|
|
|
|
String subtitle = String.format(getString(R.string.status_username_format),
|
|
account.getUsername());
|
|
getSupportActionBar().setSubtitle(subtitle);
|
|
}
|
|
|
|
LinkHelper.setClickableText(note, account.getNote(), null, new LinkListener() {
|
|
@Override
|
|
public void onViewTag(String tag) {
|
|
Intent intent = new Intent(AccountActivity.this, ViewTagActivity.class);
|
|
intent.putExtra("hashtag", tag);
|
|
startActivity(intent);
|
|
}
|
|
|
|
@Override
|
|
public void onViewAccount(String id) {
|
|
Intent intent = new Intent(AccountActivity.this, AccountActivity.class);
|
|
intent.putExtra("id", id);
|
|
startActivity(intent);
|
|
}
|
|
});
|
|
|
|
if (account.getLocked()) {
|
|
accountLockedView.setVisibility(View.VISIBLE);
|
|
} else {
|
|
accountLockedView.setVisibility(View.GONE);
|
|
}
|
|
|
|
Picasso.with(this)
|
|
.load(account.getAvatar())
|
|
.placeholder(R.drawable.avatar_default)
|
|
.into(avatar);
|
|
Picasso.with(this)
|
|
.load(account.getHeader())
|
|
.placeholder(R.drawable.account_header_default)
|
|
.into(header);
|
|
|
|
NumberFormat numberFormat = NumberFormat.getNumberInstance();
|
|
|
|
String followersCount = numberFormat.format(account.getFollowersCount());
|
|
String followingCount = numberFormat.format(account.getFollowingCount());
|
|
String statusesCount = numberFormat.format(account.getStatusesCount());
|
|
followersTextView.setText(getString(R.string.title_x_followers, followersCount));
|
|
followingTextView.setText(getString(R.string.title_x_following, followingCount));
|
|
statusesTextView.setText(getString(R.string.title_x_statuses, statusesCount));
|
|
|
|
}
|
|
|
|
private void onObtainAccountFailure() {
|
|
Snackbar.make(tabLayout, R.string.error_generic, Snackbar.LENGTH_LONG)
|
|
.setAction(R.string.action_retry, v -> obtainAccount())
|
|
.show();
|
|
}
|
|
|
|
private void obtainRelationships() {
|
|
List<String> ids = new ArrayList<>(1);
|
|
ids.add(accountId);
|
|
mastodonApi.relationships(ids).enqueue(new Callback<List<Relationship>>() {
|
|
@Override
|
|
public void onResponse(@NonNull Call<List<Relationship>> call,
|
|
@NonNull Response<List<Relationship>> response) {
|
|
List<Relationship> relationships = response.body();
|
|
if (response.isSuccessful() && relationships != null) {
|
|
Relationship relationship = relationships.get(0);
|
|
onObtainRelationshipsSuccess(relationship);
|
|
} else {
|
|
onObtainRelationshipsFailure(new Exception(response.message()));
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onFailure(@NonNull Call<List<Relationship>> call, @NonNull Throwable t) {
|
|
onObtainRelationshipsFailure((Exception) t);
|
|
}
|
|
});
|
|
}
|
|
|
|
private void onObtainRelationshipsSuccess(Relationship relation) {
|
|
if (relation.getFollowing()) {
|
|
followState = FollowState.FOLLOWING;
|
|
} else if (relation.getRequested()) {
|
|
followState = FollowState.REQUESTED;
|
|
} else {
|
|
followState = FollowState.NOT_FOLLOWING;
|
|
}
|
|
this.blocking = relation.getBlocking();
|
|
this.muting = relation.getMuting();
|
|
|
|
if (relation.getFollowedBy()) {
|
|
followsYouView.setVisibility(View.VISIBLE);
|
|
} else {
|
|
followsYouView.setVisibility(View.GONE);
|
|
}
|
|
|
|
updateButtons();
|
|
}
|
|
|
|
private void updateFollowButton(Button button) {
|
|
switch (followState) {
|
|
case NOT_FOLLOWING: {
|
|
button.setText(R.string.action_follow);
|
|
break;
|
|
}
|
|
case REQUESTED: {
|
|
button.setText(R.string.state_follow_requested);
|
|
break;
|
|
}
|
|
case FOLLOWING: {
|
|
button.setText(R.string.action_unfollow);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void updateButtons() {
|
|
invalidateOptionsMenu();
|
|
|
|
if (!isSelf && !blocking) {
|
|
floatingBtn.show();
|
|
followBtn.setVisibility(View.VISIBLE);
|
|
|
|
updateFollowButton(followBtn);
|
|
|
|
floatingBtn.setOnClickListener(v -> mention());
|
|
|
|
followBtn.setOnClickListener(v -> {
|
|
switch (followState) {
|
|
case NOT_FOLLOWING: {
|
|
follow(accountId);
|
|
break;
|
|
}
|
|
case REQUESTED: {
|
|
showFollowRequestPendingDialog();
|
|
break;
|
|
}
|
|
case FOLLOWING: {
|
|
showUnfollowWarningDialog();
|
|
break;
|
|
}
|
|
}
|
|
updateFollowButton(followBtn);
|
|
});
|
|
} else {
|
|
floatingBtn.hide();
|
|
followBtn.setVisibility(View.GONE);
|
|
}
|
|
}
|
|
|
|
private void onObtainRelationshipsFailure(Exception exception) {
|
|
Log.e(TAG, "Could not obtain relationships. " + exception.getMessage());
|
|
}
|
|
|
|
@Override
|
|
public boolean onCreateOptionsMenu(Menu menu) {
|
|
getMenuInflater().inflate(R.menu.account_toolbar, menu);
|
|
return super.onCreateOptionsMenu(menu);
|
|
}
|
|
|
|
private String getFollowAction() {
|
|
switch (followState) {
|
|
default:
|
|
case NOT_FOLLOWING:
|
|
return getString(R.string.action_follow);
|
|
case REQUESTED:
|
|
case FOLLOWING:
|
|
return getString(R.string.action_unfollow);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean onPrepareOptionsMenu(Menu menu) {
|
|
if (!isSelf) {
|
|
MenuItem follow = menu.findItem(R.id.action_follow);
|
|
follow.setTitle(getFollowAction());
|
|
follow.setVisible(followState != FollowState.REQUESTED);
|
|
|
|
MenuItem block = menu.findItem(R.id.action_block);
|
|
String title;
|
|
if (blocking) {
|
|
title = getString(R.string.action_unblock);
|
|
} else {
|
|
title = getString(R.string.action_block);
|
|
}
|
|
block.setTitle(title);
|
|
MenuItem mute = menu.findItem(R.id.action_mute);
|
|
if (muting) {
|
|
title = getString(R.string.action_unmute);
|
|
} else {
|
|
title = getString(R.string.action_mute);
|
|
}
|
|
mute.setTitle(title);
|
|
} else {
|
|
// It shouldn't be possible to block or follow yourself.
|
|
menu.removeItem(R.id.action_follow);
|
|
menu.removeItem(R.id.action_block);
|
|
menu.removeItem(R.id.action_mute);
|
|
}
|
|
return super.onPrepareOptionsMenu(menu);
|
|
}
|
|
|
|
private void follow(final String id) {
|
|
Callback<Relationship> cb = new Callback<Relationship>() {
|
|
@Override
|
|
public void onResponse(@NonNull Call<Relationship> call,
|
|
@NonNull Response<Relationship> response) {
|
|
Relationship relationship = response.body();
|
|
if (response.isSuccessful() && relationship != null) {
|
|
if (relationship.getFollowing()) {
|
|
followState = FollowState.FOLLOWING;
|
|
} else if (relationship.getRequested()) {
|
|
followState = FollowState.REQUESTED;
|
|
Snackbar.make(container, R.string.state_follow_requested,
|
|
Snackbar.LENGTH_LONG).show();
|
|
} else {
|
|
followState = FollowState.NOT_FOLLOWING;
|
|
broadcast(TimelineReceiver.Types.UNFOLLOW_ACCOUNT, id);
|
|
}
|
|
updateButtons();
|
|
} else {
|
|
onFollowFailure(id);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onFailure(@NonNull Call<Relationship> call, @NonNull Throwable t) {
|
|
onFollowFailure(id);
|
|
}
|
|
};
|
|
|
|
Assert.expect(followState != FollowState.REQUESTED);
|
|
switch (followState) {
|
|
case NOT_FOLLOWING: {
|
|
mastodonApi.followAccount(id).enqueue(cb);
|
|
break;
|
|
}
|
|
case FOLLOWING: {
|
|
mastodonApi.unfollowAccount(id).enqueue(cb);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void onFollowFailure(final String id) {
|
|
View.OnClickListener listener = v -> follow(id);
|
|
Snackbar.make(container, R.string.error_generic, Snackbar.LENGTH_LONG)
|
|
.setAction(R.string.action_retry, listener)
|
|
.show();
|
|
}
|
|
|
|
private void showFollowRequestPendingDialog() {
|
|
new AlertDialog.Builder(this)
|
|
.setMessage(R.string.dialog_message_follow_request)
|
|
.setPositiveButton(android.R.string.ok, null)
|
|
.show();
|
|
}
|
|
|
|
private void showUnfollowWarningDialog() {
|
|
DialogInterface.OnClickListener unfollowListener = (dialogInterface, i) -> follow(accountId);
|
|
new AlertDialog.Builder(this)
|
|
.setMessage(R.string.dialog_unfollow_warning)
|
|
.setPositiveButton(android.R.string.ok, unfollowListener)
|
|
.setNegativeButton(android.R.string.cancel, null)
|
|
.show();
|
|
}
|
|
|
|
private void block(final String id) {
|
|
Callback<Relationship> cb = new Callback<Relationship>() {
|
|
@Override
|
|
public void onResponse(@NonNull Call<Relationship> call,
|
|
@NonNull Response<Relationship> response) {
|
|
Relationship relationship = response.body();
|
|
if (response.isSuccessful() && relationship != null) {
|
|
broadcast(TimelineReceiver.Types.BLOCK_ACCOUNT, id);
|
|
blocking = relationship.getBlocking();
|
|
updateButtons();
|
|
} else {
|
|
onBlockFailure(id);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onFailure(@NonNull Call<Relationship> call, @NonNull Throwable t) {
|
|
onBlockFailure(id);
|
|
}
|
|
};
|
|
if (blocking) {
|
|
mastodonApi.unblockAccount(id).enqueue(cb);
|
|
} else {
|
|
mastodonApi.blockAccount(id).enqueue(cb);
|
|
}
|
|
}
|
|
|
|
private void onBlockFailure(final String id) {
|
|
View.OnClickListener listener = v -> block(id);
|
|
Snackbar.make(container, R.string.error_generic, Snackbar.LENGTH_LONG)
|
|
.setAction(R.string.action_retry, listener)
|
|
.show();
|
|
}
|
|
|
|
private void mute(final String id) {
|
|
Callback<Relationship> cb = new Callback<Relationship>() {
|
|
@Override
|
|
public void onResponse(@NonNull Call<Relationship> call,
|
|
@NonNull Response<Relationship> response) {
|
|
Relationship relationship = response.body();
|
|
if (response.isSuccessful() && relationship != null) {
|
|
broadcast(TimelineReceiver.Types.MUTE_ACCOUNT, id);
|
|
muting = relationship.getMuting();
|
|
updateButtons();
|
|
} else {
|
|
onMuteFailure(id);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onFailure(@NonNull Call<Relationship> call, @NonNull Throwable t) {
|
|
onMuteFailure(id);
|
|
}
|
|
};
|
|
|
|
if (muting) {
|
|
mastodonApi.unmuteAccount(id).enqueue(cb);
|
|
} else {
|
|
mastodonApi.muteAccount(id).enqueue(cb);
|
|
}
|
|
}
|
|
|
|
private void onMuteFailure(final String id) {
|
|
View.OnClickListener listener = v -> mute(id);
|
|
Snackbar.make(container, R.string.error_generic, Snackbar.LENGTH_LONG)
|
|
.setAction(R.string.action_retry, listener)
|
|
.show();
|
|
}
|
|
|
|
private boolean mention() {
|
|
if (loadedAccount == null) {
|
|
// If the account isn't loaded yet, eat the input.
|
|
return false;
|
|
}
|
|
Intent intent = new ComposeActivity.IntentBuilder()
|
|
.mentionedUsernames(Collections.singleton(loadedAccount.getUsername()))
|
|
.build(this);
|
|
startActivity(intent);
|
|
return true;
|
|
}
|
|
|
|
private void broadcast(String action, String id) {
|
|
Intent intent = new Intent(action);
|
|
intent.putExtra("id", id);
|
|
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);
|
|
}
|
|
|
|
@Override
|
|
public boolean onOptionsItemSelected(MenuItem item) {
|
|
switch (item.getItemId()) {
|
|
case android.R.id.home: {
|
|
onBackPressed();
|
|
return true;
|
|
}
|
|
case R.id.action_mention: {
|
|
return mention();
|
|
}
|
|
case R.id.action_open_in_web: {
|
|
if (loadedAccount == null) {
|
|
// If the account isn't loaded yet, eat the input.
|
|
return false;
|
|
}
|
|
LinkHelper.openLink(loadedAccount.getUrl(), this);
|
|
return true;
|
|
}
|
|
case R.id.action_follow: {
|
|
follow(accountId);
|
|
return true;
|
|
}
|
|
case R.id.action_block: {
|
|
block(accountId);
|
|
return true;
|
|
}
|
|
case R.id.action_mute: {
|
|
mute(accountId);
|
|
return true;
|
|
}
|
|
}
|
|
return super.onOptionsItemSelected(item);
|
|
}
|
|
|
|
@Nullable
|
|
@Override
|
|
public FloatingActionButton getActionButton() {
|
|
if (!isSelf && !blocking) {
|
|
return floatingBtn;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public AndroidInjector<Fragment> supportFragmentInjector() {
|
|
return dispatchingAndroidInjector;
|
|
}
|
|
}
|