2017-01-28 14:33:43 +11:00
|
|
|
/* Copyright 2017 Andrew Dawson
|
|
|
|
*
|
|
|
|
* This file is part of Tusky.
|
|
|
|
*
|
|
|
|
* Tusky 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.content.Context;
|
|
|
|
import android.content.Intent;
|
|
|
|
import android.content.SharedPreferences;
|
2017-01-31 15:51:02 +11:00
|
|
|
import android.net.Uri;
|
2017-01-28 14:33:43 +11:00
|
|
|
import android.os.Bundle;
|
|
|
|
import android.support.annotation.Nullable;
|
2017-01-31 15:51:02 +11:00
|
|
|
import android.support.design.widget.Snackbar;
|
2017-01-28 14:33:43 +11:00
|
|
|
import android.support.design.widget.TabLayout;
|
|
|
|
import android.support.v4.view.ViewPager;
|
|
|
|
import android.support.v7.app.ActionBar;
|
|
|
|
import android.support.v7.widget.Toolbar;
|
2017-02-02 07:20:39 +11:00
|
|
|
import android.text.method.LinkMovementMethod;
|
2017-02-03 11:18:41 +11:00
|
|
|
import android.util.TypedValue;
|
2017-01-28 14:33:43 +11:00
|
|
|
import android.view.Menu;
|
|
|
|
import android.view.MenuItem;
|
2017-01-31 15:51:02 +11:00
|
|
|
import android.view.View;
|
2017-02-23 06:13:51 +11:00
|
|
|
import android.view.ViewGroup;
|
2017-01-28 14:33:43 +11:00
|
|
|
import android.widget.TextView;
|
|
|
|
|
|
|
|
import com.android.volley.AuthFailureError;
|
|
|
|
import com.android.volley.Request;
|
|
|
|
import com.android.volley.Response;
|
|
|
|
import com.android.volley.VolleyError;
|
|
|
|
import com.android.volley.toolbox.ImageLoader;
|
|
|
|
import com.android.volley.toolbox.JsonArrayRequest;
|
|
|
|
import com.android.volley.toolbox.JsonObjectRequest;
|
|
|
|
import com.android.volley.toolbox.NetworkImageView;
|
|
|
|
|
|
|
|
import org.json.JSONArray;
|
|
|
|
import org.json.JSONException;
|
|
|
|
import org.json.JSONObject;
|
|
|
|
|
|
|
|
import java.util.HashMap;
|
|
|
|
import java.util.Map;
|
|
|
|
|
2017-02-17 05:52:55 +11:00
|
|
|
public class AccountActivity extends BaseActivity {
|
2017-01-31 15:51:02 +11:00
|
|
|
private static final String TAG = "AccountActivity"; // logging tag
|
|
|
|
|
2017-01-28 14:33:43 +11:00
|
|
|
private String domain;
|
|
|
|
private String accessToken;
|
2017-01-31 15:51:02 +11:00
|
|
|
private String accountId;
|
2017-01-28 14:33:43 +11:00
|
|
|
private boolean following = false;
|
|
|
|
private boolean blocking = false;
|
2017-02-20 11:27:15 +11:00
|
|
|
private boolean isSelf;
|
2017-01-31 15:51:02 +11:00
|
|
|
private String openInWebUrl;
|
|
|
|
private TabLayout tabLayout;
|
2017-01-28 14:33:43 +11:00
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
|
|
|
super.onCreate(savedInstanceState);
|
|
|
|
setContentView(R.layout.activity_account);
|
|
|
|
|
|
|
|
Intent intent = getIntent();
|
2017-01-31 15:51:02 +11:00
|
|
|
accountId = intent.getStringExtra("id");
|
2017-01-28 14:33:43 +11:00
|
|
|
|
|
|
|
SharedPreferences preferences = getSharedPreferences(
|
|
|
|
getString(R.string.preferences_file_key), Context.MODE_PRIVATE);
|
|
|
|
domain = preferences.getString("domain", null);
|
|
|
|
accessToken = preferences.getString("accessToken", null);
|
2017-01-31 15:51:02 +11:00
|
|
|
String loggedInAccountId = preferences.getString("loggedInAccountId", null);
|
2017-01-28 14:33:43 +11:00
|
|
|
|
|
|
|
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
|
|
|
|
setSupportActionBar(toolbar);
|
|
|
|
|
|
|
|
NetworkImageView avatar = (NetworkImageView) findViewById(R.id.account_avatar);
|
|
|
|
NetworkImageView header = (NetworkImageView) findViewById(R.id.account_header);
|
|
|
|
avatar.setDefaultImageResId(R.drawable.avatar_default);
|
|
|
|
avatar.setErrorImageResId(R.drawable.avatar_error);
|
|
|
|
header.setDefaultImageResId(R.drawable.account_header_default);
|
|
|
|
|
2017-01-31 15:51:02 +11:00
|
|
|
obtainAccount();
|
|
|
|
if (!accountId.equals(loggedInAccountId)) {
|
2017-02-20 11:27:15 +11:00
|
|
|
isSelf = false;
|
2017-01-31 15:51:02 +11:00
|
|
|
obtainRelationships();
|
|
|
|
} else {
|
|
|
|
/* Cause the options menu to update and instead show an options menu for when the
|
|
|
|
* account being shown is their own account. */
|
|
|
|
isSelf = true;
|
|
|
|
invalidateOptionsMenu();
|
|
|
|
}
|
2017-01-28 14:33:43 +11:00
|
|
|
|
|
|
|
// Setup the tabs and timeline pager.
|
2017-02-23 06:13:51 +11:00
|
|
|
AccountPagerAdapter adapter = new AccountPagerAdapter(getSupportFragmentManager(), this,
|
|
|
|
accountId);
|
2017-01-28 14:33:43 +11:00
|
|
|
String[] pageTitles = {
|
2017-01-31 15:51:02 +11:00
|
|
|
getString(R.string.title_statuses),
|
|
|
|
getString(R.string.title_follows),
|
|
|
|
getString(R.string.title_followers)
|
2017-01-28 14:33:43 +11:00
|
|
|
};
|
|
|
|
adapter.setPageTitles(pageTitles);
|
|
|
|
ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
|
2017-02-03 11:18:41 +11:00
|
|
|
int pageMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8,
|
|
|
|
getResources().getDisplayMetrics());
|
|
|
|
viewPager.setPageMargin(pageMargin);
|
2017-02-17 13:11:05 +11:00
|
|
|
viewPager.setPageMarginDrawable(R.drawable.tab_page_margin_dark);
|
2017-01-28 14:33:43 +11:00
|
|
|
viewPager.setAdapter(adapter);
|
2017-01-31 15:51:02 +11:00
|
|
|
tabLayout = (TabLayout) findViewById(R.id.tab_layout);
|
2017-01-28 14:33:43 +11:00
|
|
|
tabLayout.setupWithViewPager(viewPager);
|
2017-01-31 15:51:02 +11:00
|
|
|
for (int i = 0; i < tabLayout.getTabCount(); i++) {
|
|
|
|
TabLayout.Tab tab = tabLayout.getTabAt(i);
|
2017-02-02 07:20:39 +11:00
|
|
|
if (tab != null) {
|
2017-02-23 06:13:51 +11:00
|
|
|
tab.setCustomView(adapter.getTabView(i, tabLayout));
|
2017-02-02 07:20:39 +11:00
|
|
|
}
|
2017-01-31 15:51:02 +11:00
|
|
|
}
|
2017-01-28 14:33:43 +11:00
|
|
|
}
|
|
|
|
|
2017-01-31 15:51:02 +11:00
|
|
|
private void obtainAccount() {
|
|
|
|
String endpoint = String.format(getString(R.string.endpoint_accounts), accountId);
|
2017-01-28 14:33:43 +11:00
|
|
|
String url = "https://" + domain + endpoint;
|
|
|
|
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, url, null,
|
|
|
|
new Response.Listener<JSONObject>() {
|
|
|
|
@Override
|
|
|
|
public void onResponse(JSONObject response) {
|
2017-01-31 15:51:02 +11:00
|
|
|
Account account;
|
2017-01-28 14:33:43 +11:00
|
|
|
try {
|
2017-01-31 15:51:02 +11:00
|
|
|
account = Account.parse(response);
|
2017-01-28 14:33:43 +11:00
|
|
|
} catch (JSONException e) {
|
|
|
|
onObtainAccountFailure();
|
2017-01-31 15:51:02 +11:00
|
|
|
return;
|
2017-01-28 14:33:43 +11:00
|
|
|
}
|
2017-01-31 15:51:02 +11:00
|
|
|
onObtainAccountSuccess(account);
|
2017-01-28 14:33:43 +11:00
|
|
|
}
|
|
|
|
},
|
|
|
|
new Response.ErrorListener() {
|
|
|
|
@Override
|
|
|
|
public void onErrorResponse(VolleyError error) {
|
|
|
|
onObtainAccountFailure();
|
|
|
|
}
|
|
|
|
}) {
|
|
|
|
@Override
|
|
|
|
public Map<String, String> getHeaders() throws AuthFailureError {
|
|
|
|
Map<String, String> headers = new HashMap<>();
|
|
|
|
headers.put("Authorization", "Bearer " + accessToken);
|
|
|
|
return headers;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
VolleySingleton.getInstance(this).addToRequestQueue(request);
|
|
|
|
}
|
|
|
|
|
2017-01-31 15:51:02 +11:00
|
|
|
private void onObtainAccountSuccess(Account account) {
|
2017-01-28 14:33:43 +11:00
|
|
|
TextView username = (TextView) findViewById(R.id.account_username);
|
|
|
|
TextView displayName = (TextView) findViewById(R.id.account_display_name);
|
|
|
|
TextView note = (TextView) findViewById(R.id.account_note);
|
|
|
|
NetworkImageView avatar = (NetworkImageView) findViewById(R.id.account_avatar);
|
|
|
|
NetworkImageView header = (NetworkImageView) findViewById(R.id.account_header);
|
|
|
|
|
|
|
|
String usernameFormatted = String.format(
|
2017-01-31 15:51:02 +11:00
|
|
|
getString(R.string.status_username_format), account.username);
|
2017-01-28 14:33:43 +11:00
|
|
|
username.setText(usernameFormatted);
|
|
|
|
|
2017-01-31 15:51:02 +11:00
|
|
|
displayName.setText(account.displayName);
|
2017-01-28 14:33:43 +11:00
|
|
|
ActionBar actionBar = getSupportActionBar();
|
|
|
|
if (actionBar != null) {
|
2017-01-31 15:51:02 +11:00
|
|
|
actionBar.setTitle(account.displayName);
|
2017-01-28 14:33:43 +11:00
|
|
|
}
|
|
|
|
|
2017-01-31 15:51:02 +11:00
|
|
|
note.setText(account.note);
|
|
|
|
note.setLinksClickable(true);
|
2017-02-02 07:20:39 +11:00
|
|
|
note.setMovementMethod(LinkMovementMethod.getInstance());
|
2017-01-28 14:33:43 +11:00
|
|
|
|
|
|
|
ImageLoader imageLoader = VolleySingleton.getInstance(this).getImageLoader();
|
2017-01-31 15:51:02 +11:00
|
|
|
if (!account.avatar.isEmpty()) {
|
|
|
|
avatar.setImageUrl(account.avatar, imageLoader);
|
|
|
|
}
|
|
|
|
if (!account.header.isEmpty()) {
|
|
|
|
header.setImageUrl(account.header, imageLoader);
|
|
|
|
}
|
|
|
|
|
|
|
|
openInWebUrl = account.url;
|
|
|
|
|
|
|
|
// Add counts to the tabs in the TabLayout.
|
|
|
|
String[] counts = {
|
|
|
|
account.statusesCount,
|
|
|
|
account.followingCount,
|
|
|
|
account.followersCount,
|
|
|
|
};
|
|
|
|
for (int i = 0; i < tabLayout.getTabCount(); i++) {
|
|
|
|
TabLayout.Tab tab = tabLayout.getTabAt(i);
|
|
|
|
if (tab != null) {
|
|
|
|
View view = tab.getCustomView();
|
2017-02-02 07:20:39 +11:00
|
|
|
if (view != null) {
|
|
|
|
TextView total = (TextView) view.findViewById(R.id.total);
|
|
|
|
total.setText(counts[i]);
|
|
|
|
}
|
2017-01-31 15:51:02 +11:00
|
|
|
}
|
2017-01-28 14:33:43 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void onObtainAccountFailure() {
|
|
|
|
//TODO: help
|
2017-01-31 15:51:02 +11:00
|
|
|
Log.e(TAG, "Failed to obtain that account.");
|
2017-01-28 14:33:43 +11:00
|
|
|
}
|
|
|
|
|
2017-01-31 15:51:02 +11:00
|
|
|
private void obtainRelationships() {
|
2017-01-28 14:33:43 +11:00
|
|
|
String endpoint = getString(R.string.endpoint_relationships);
|
2017-01-31 15:51:02 +11:00
|
|
|
String url = String.format("https://%s%s?id=%s", domain, endpoint, accountId);
|
2017-01-28 14:33:43 +11:00
|
|
|
JsonArrayRequest request = new JsonArrayRequest(url,
|
|
|
|
new Response.Listener<JSONArray>() {
|
|
|
|
@Override
|
|
|
|
public void onResponse(JSONArray response) {
|
|
|
|
boolean following;
|
|
|
|
boolean blocking;
|
|
|
|
try {
|
|
|
|
JSONObject object = response.getJSONObject(0);
|
|
|
|
following = object.getBoolean("following");
|
|
|
|
blocking = object.getBoolean("blocking");
|
|
|
|
} catch (JSONException e) {
|
|
|
|
onObtainRelationshipsFailure();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
onObtainRelationshipsSuccess(following, blocking);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
new Response.ErrorListener() {
|
|
|
|
@Override
|
|
|
|
public void onErrorResponse(VolleyError error) {
|
|
|
|
onObtainRelationshipsFailure();
|
|
|
|
}
|
|
|
|
}) {
|
|
|
|
@Override
|
|
|
|
public Map<String, String> getHeaders() throws AuthFailureError {
|
|
|
|
Map<String, String> headers = new HashMap<>();
|
|
|
|
headers.put("Authorization", "Bearer " + accessToken);
|
|
|
|
return headers;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
VolleySingleton.getInstance(this).addToRequestQueue(request);
|
|
|
|
}
|
|
|
|
|
|
|
|
private void onObtainRelationshipsSuccess(boolean following, boolean blocking) {
|
|
|
|
this.following = following;
|
|
|
|
this.blocking = blocking;
|
|
|
|
if (!following || !blocking) {
|
|
|
|
invalidateOptionsMenu();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void onObtainRelationshipsFailure() {
|
|
|
|
//TODO: help
|
2017-01-31 15:51:02 +11:00
|
|
|
Log.e(TAG, "Could not obtain relationships?");
|
2017-01-28 14:33:43 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean onCreateOptionsMenu(Menu menu) {
|
|
|
|
getMenuInflater().inflate(R.menu.account_toolbar, menu);
|
|
|
|
return super.onCreateOptionsMenu(menu);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean onPrepareOptionsMenu(Menu menu) {
|
2017-01-31 15:51:02 +11:00
|
|
|
if (!isSelf) {
|
|
|
|
MenuItem follow = menu.findItem(R.id.action_follow);
|
|
|
|
String title;
|
|
|
|
if (following) {
|
|
|
|
title = getString(R.string.action_unfollow);
|
|
|
|
} else {
|
|
|
|
title = getString(R.string.action_follow);
|
|
|
|
}
|
|
|
|
follow.setTitle(title);
|
|
|
|
MenuItem block = menu.findItem(R.id.action_block);
|
|
|
|
if (blocking) {
|
|
|
|
title = getString(R.string.action_unblock);
|
|
|
|
} else {
|
|
|
|
title = getString(R.string.action_block);
|
|
|
|
}
|
|
|
|
block.setTitle(title);
|
2017-01-28 14:33:43 +11:00
|
|
|
} else {
|
2017-01-31 15:51:02 +11:00
|
|
|
// It shouldn't be possible to block or follow yourself.
|
|
|
|
menu.removeItem(R.id.action_follow);
|
|
|
|
menu.removeItem(R.id.action_block);
|
2017-01-28 14:33:43 +11:00
|
|
|
}
|
|
|
|
return super.onPrepareOptionsMenu(menu);
|
|
|
|
}
|
|
|
|
|
2017-01-31 15:51:02 +11:00
|
|
|
private void postRequest(String endpoint, Response.Listener<JSONObject> listener,
|
|
|
|
Response.ErrorListener errorListener) {
|
|
|
|
String url = "https://" + domain + endpoint;
|
|
|
|
JsonObjectRequest request = new JsonObjectRequest(Request.Method.POST, url, null, listener,
|
|
|
|
errorListener) {
|
|
|
|
@Override
|
|
|
|
public Map<String, String> getHeaders() throws AuthFailureError {
|
|
|
|
Map<String, String> headers = new HashMap<>();
|
|
|
|
headers.put("Authorization", "Bearer " + accessToken);
|
|
|
|
return headers;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
VolleySingleton.getInstance(this).addToRequestQueue(request);
|
|
|
|
}
|
|
|
|
|
|
|
|
private void follow(final String id) {
|
|
|
|
int endpointId;
|
|
|
|
if (following) {
|
|
|
|
endpointId = R.string.endpoint_unfollow;
|
|
|
|
} else {
|
|
|
|
endpointId = R.string.endpoint_follow;
|
|
|
|
}
|
|
|
|
postRequest(String.format(getString(endpointId), id),
|
|
|
|
new Response.Listener<JSONObject>() {
|
|
|
|
@Override
|
|
|
|
public void onResponse(JSONObject response) {
|
|
|
|
boolean followingValue;
|
|
|
|
try {
|
|
|
|
followingValue = response.getBoolean("following");
|
|
|
|
} catch (JSONException e) {
|
|
|
|
onFollowFailure(id);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
following = followingValue;
|
|
|
|
invalidateOptionsMenu();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
new Response.ErrorListener() {
|
|
|
|
@Override
|
|
|
|
public void onErrorResponse(VolleyError error) {
|
|
|
|
onFollowFailure(id);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2017-01-28 14:33:43 +11:00
|
|
|
|
2017-01-31 15:51:02 +11:00
|
|
|
private void onFollowFailure(final String id) {
|
|
|
|
int messageId;
|
|
|
|
if (following) {
|
|
|
|
messageId = R.string.error_unfollowing;
|
|
|
|
} else {
|
|
|
|
messageId = R.string.error_following;
|
|
|
|
}
|
|
|
|
View.OnClickListener listener = new View.OnClickListener() {
|
|
|
|
@Override
|
|
|
|
public void onClick(View v) {
|
|
|
|
follow(id);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
Snackbar.make(findViewById(R.id.activity_account), messageId, Snackbar.LENGTH_LONG)
|
|
|
|
.setAction(R.string.action_retry, listener)
|
|
|
|
.show();
|
2017-01-28 14:33:43 +11:00
|
|
|
}
|
|
|
|
|
2017-01-31 15:51:02 +11:00
|
|
|
private void block(final String id) {
|
|
|
|
int endpointId;
|
|
|
|
if (blocking) {
|
|
|
|
endpointId = R.string.endpoint_unblock;
|
|
|
|
} else {
|
|
|
|
endpointId = R.string.endpoint_block;
|
|
|
|
}
|
|
|
|
postRequest(String.format(getString(endpointId), id),
|
|
|
|
new Response.Listener<JSONObject>() {
|
|
|
|
@Override
|
|
|
|
public void onResponse(JSONObject response) {
|
|
|
|
boolean blockingValue;
|
|
|
|
try {
|
|
|
|
blockingValue = response.getBoolean("blocking");
|
|
|
|
} catch (JSONException e) {
|
|
|
|
onBlockFailure(id);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
blocking = blockingValue;
|
|
|
|
invalidateOptionsMenu();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
new Response.ErrorListener() {
|
|
|
|
@Override
|
|
|
|
public void onErrorResponse(VolleyError error) {
|
|
|
|
onBlockFailure(id);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2017-01-28 14:33:43 +11:00
|
|
|
|
2017-01-31 15:51:02 +11:00
|
|
|
private void onBlockFailure(final String id) {
|
|
|
|
int messageId;
|
|
|
|
if (blocking) {
|
|
|
|
messageId = R.string.error_unblocking;
|
|
|
|
} else {
|
|
|
|
messageId = R.string.error_blocking;
|
|
|
|
}
|
|
|
|
View.OnClickListener listener = new View.OnClickListener() {
|
|
|
|
@Override
|
|
|
|
public void onClick(View v) {
|
|
|
|
block(id);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
Snackbar.make(findViewById(R.id.activity_account), messageId, Snackbar.LENGTH_LONG)
|
|
|
|
.setAction(R.string.action_retry, listener)
|
|
|
|
.show();
|
2017-01-28 14:33:43 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean onOptionsItemSelected(MenuItem item) {
|
|
|
|
switch (item.getItemId()) {
|
|
|
|
case R.id.action_back: {
|
|
|
|
Intent intent = new Intent(this, MainActivity.class);
|
|
|
|
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
|
|
|
startActivity(intent);
|
|
|
|
return true;
|
|
|
|
}
|
2017-01-31 15:51:02 +11:00
|
|
|
case R.id.action_open_in_web: {
|
|
|
|
Uri uri = Uri.parse(openInWebUrl);
|
|
|
|
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
|
|
|
|
startActivity(intent);
|
|
|
|
return true;
|
|
|
|
}
|
2017-01-28 14:33:43 +11:00
|
|
|
case R.id.action_follow: {
|
2017-01-31 15:51:02 +11:00
|
|
|
follow(accountId);
|
2017-01-28 14:33:43 +11:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
case R.id.action_block: {
|
2017-01-31 15:51:02 +11:00
|
|
|
block(accountId);
|
2017-01-28 14:33:43 +11:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return super.onOptionsItemSelected(item);
|
|
|
|
}
|
|
|
|
}
|