Fixes with TLSv1.1, TLSv1.2
This commit is contained in:
parent
3d23b66d81
commit
0775271098
|
@ -7,8 +7,8 @@ android {
|
|||
applicationId "fr.gouv.etalab.mastodon"
|
||||
minSdkVersion 15
|
||||
targetSdkVersion 25
|
||||
versionCode 5
|
||||
versionName "1.0.5"
|
||||
versionCode 6
|
||||
versionName "1.0.6"
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
|
|
|
@ -17,13 +17,9 @@ package fr.gouv.etalab.mastodon.activities;
|
|||
import android.content.Intent;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Color;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.text.Html;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
|
|
|
@ -49,12 +49,22 @@ public class LoginActivity extends AppCompatActivity {
|
|||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_login);
|
||||
|
||||
final Button connectionButton = (Button) findViewById(R.id.login_button);
|
||||
final Intent webviewIntent = new Intent(this, WebviewActivity.class);
|
||||
|
||||
|
||||
Button connectionButton = (Button) findViewById(R.id.login_button);
|
||||
connectionButton.setEnabled(false);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume(){
|
||||
super.onResume();
|
||||
Button connectionButton = (Button) findViewById(R.id.login_button);
|
||||
if( !connectionButton.isEnabled())
|
||||
retrievesClientId();
|
||||
}
|
||||
|
||||
private void retrievesClientId(){
|
||||
final Button connectionButton = (Button) findViewById(R.id.login_button);
|
||||
final Intent webviewIntent = new Intent(this, WebviewActivity.class);
|
||||
String action = "/api/v1/apps";
|
||||
HashMap<String,String> parameters = new HashMap<>();
|
||||
parameters.put(Helper.CLIENT_NAME, Helper.OAUTH_REDIRECT_HOST);
|
||||
|
@ -99,10 +109,8 @@ public class LoginActivity extends AppCompatActivity {
|
|||
finish();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -115,6 +115,7 @@ public class MainActivity extends AppCompatActivity
|
|||
navigationView.setNavigationItemSelectedListener(this);
|
||||
|
||||
|
||||
|
||||
//Image loader configuration
|
||||
imageLoader = ImageLoader.getInstance();
|
||||
File cacheDir = new File(getCacheDir(), getString(R.string.app_name));
|
||||
|
|
|
@ -14,7 +14,10 @@
|
|||
* see <http://www.gnu.org/licenses>. */
|
||||
package fr.gouv.etalab.mastodon.activities;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
|
@ -23,6 +26,7 @@ import android.support.design.widget.TabLayout;
|
|||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.FragmentStatePagerAdapter;
|
||||
import android.support.v4.content.LocalBroadcastManager;
|
||||
import android.support.v4.view.PagerAdapter;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
|
@ -31,6 +35,7 @@ import android.view.MenuItem;
|
|||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
|
@ -79,8 +84,9 @@ public class ShowAccountActivity extends AppCompatActivity implements OnPostActi
|
|||
private ViewPager mPager;
|
||||
private String accountId;
|
||||
private TabLayout tabLayout;
|
||||
|
||||
|
||||
private BroadcastReceiver hide_header;
|
||||
private TextView account_note;
|
||||
private String userId;
|
||||
|
||||
public enum action{
|
||||
FOLLOW,
|
||||
|
@ -96,6 +102,9 @@ public class ShowAccountActivity extends AppCompatActivity implements OnPostActi
|
|||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_show_account);
|
||||
|
||||
|
||||
|
||||
|
||||
SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
||||
imageLoader = ImageLoader.getInstance();
|
||||
statuses = new ArrayList<>();
|
||||
|
@ -111,7 +120,7 @@ public class ShowAccountActivity extends AppCompatActivity implements OnPostActi
|
|||
accountId = b.getString("accountId");
|
||||
new RetrieveRelationshipAsyncTask(getApplicationContext(), accountId,ShowAccountActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
new RetrieveAccountAsyncTask(getApplicationContext(),accountId, ShowAccountActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
|
||||
userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
|
||||
if( accountId != null && accountId.equals(userId)){
|
||||
account_follow.setVisibility(View.GONE);
|
||||
}
|
||||
|
@ -166,6 +175,30 @@ public class ShowAccountActivity extends AppCompatActivity implements OnPostActi
|
|||
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
account_note = (TextView) findViewById(R.id.account_note);
|
||||
//Register LocalBroadcast to receive selected accounts after search
|
||||
hide_header = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
boolean hide = intent.getBooleanExtra("hide", false);
|
||||
if( hide){
|
||||
account_follow.setVisibility(View.GONE);
|
||||
account_note.setVisibility(View.GONE);
|
||||
tabLayout.setVisibility(View.GONE);
|
||||
}else {
|
||||
account_follow.setVisibility(View.VISIBLE);
|
||||
if( accountId != null && accountId.equals(userId)){
|
||||
account_follow.setVisibility(View.GONE);
|
||||
}
|
||||
tabLayout.setVisibility(View.VISIBLE);
|
||||
account_note.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
};
|
||||
LocalBroadcastManager.getInstance(this).registerReceiver(hide_header, new IntentFilter(Helper.HEADER_ACCOUNT));
|
||||
|
||||
//Follow button
|
||||
account_follow.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
|
@ -208,7 +241,7 @@ public class ShowAccountActivity extends AppCompatActivity implements OnPostActi
|
|||
TextView account_dn = (TextView) findViewById(R.id.account_dn);
|
||||
TextView account_un = (TextView) findViewById(R.id.account_un);
|
||||
TextView account_ac = (TextView) findViewById(R.id.account_ac);
|
||||
TextView account_note = (TextView) findViewById(R.id.account_note);
|
||||
|
||||
if( account != null){
|
||||
setTitle(account.getAcct());
|
||||
account_dn.setText(account.getDisplay_name());
|
||||
|
@ -239,6 +272,12 @@ public class ShowAccountActivity extends AppCompatActivity implements OnPostActi
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy(){
|
||||
super.onDestroy();
|
||||
LocalBroadcastManager.getInstance(this).unregisterReceiver(hide_header);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRetrieveRelationship(Relationship relationship) {
|
||||
if( relationship.isBlocking()){
|
||||
|
@ -287,18 +326,21 @@ public class ShowAccountActivity extends AppCompatActivity implements OnPostActi
|
|||
DisplayStatusFragment displayStatusFragment = new DisplayStatusFragment();
|
||||
bundle.putSerializable("type", RetrieveFeedsAsyncTask.Type.USER);
|
||||
bundle.putString("targetedId", accountId);
|
||||
bundle.putBoolean("hideHeader",true);
|
||||
displayStatusFragment.setArguments(bundle);
|
||||
return displayStatusFragment;
|
||||
case 1:
|
||||
DisplayAccountsFragment displayAccountsFragment = new DisplayAccountsFragment();
|
||||
bundle.putSerializable("type", RetrieveAccountsAsyncTask.Type.FOLLOWING);
|
||||
bundle.putString("targetedId", accountId);
|
||||
bundle.putBoolean("hideHeader",true);
|
||||
displayAccountsFragment.setArguments(bundle);
|
||||
return displayAccountsFragment;
|
||||
case 2:
|
||||
displayAccountsFragment = new DisplayAccountsFragment();
|
||||
bundle.putSerializable("type", RetrieveAccountsAsyncTask.Type.FOLLOWERS);
|
||||
bundle.putString("targetedId", accountId);
|
||||
bundle.putBoolean("hideHeader",true);
|
||||
displayAccountsFragment.setArguments(bundle);
|
||||
return displayAccountsFragment;
|
||||
}
|
||||
|
|
|
@ -16,10 +16,12 @@ package fr.gouv.etalab.mastodon.asynctasks;
|
|||
|
||||
import android.content.Context;
|
||||
import android.os.AsyncTask;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import fr.gouv.etalab.mastodon.client.API;
|
||||
import fr.gouv.etalab.mastodon.helper.Helper;
|
||||
import fr.gouv.etalab.mastodon.interfaces.OnRetrieveFeedsInterface;
|
||||
|
||||
|
||||
|
|
|
@ -16,7 +16,6 @@ package fr.gouv.etalab.mastodon.client;
|
|||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.util.Log;
|
||||
|
||||
import com.loopj.android.http.AsyncHttpResponseHandler;
|
||||
import com.loopj.android.http.JsonHttpResponseHandler;
|
||||
|
@ -29,6 +28,10 @@ import org.json.JSONObject;
|
|||
|
||||
import java.io.InputStream;
|
||||
import java.lang.*;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.UnrecoverableKeyException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -42,6 +45,8 @@ import fr.gouv.etalab.mastodon.client.Entities.Notification;
|
|||
import fr.gouv.etalab.mastodon.client.Entities.Relationship;
|
||||
import fr.gouv.etalab.mastodon.client.Entities.Status;
|
||||
|
||||
import static fr.gouv.etalab.mastodon.helper.Helper.USER_AGENT;
|
||||
|
||||
|
||||
/**
|
||||
* Created by Thomas on 23/04/2017.
|
||||
|
@ -66,7 +71,6 @@ public class API {
|
|||
private List<Notification> notifications;
|
||||
private int tootPerPage, accountPerPage, notificationPerPage;
|
||||
private int actionCode;
|
||||
private String userId;
|
||||
|
||||
public enum StatusAction{
|
||||
FAVOURITE,
|
||||
|
@ -90,7 +94,6 @@ public class API {
|
|||
tootPerPage = sharedpreferences.getInt(Helper.SET_TOOTS_PER_PAGE, 40);
|
||||
accountPerPage = sharedpreferences.getInt(Helper.SET_ACCOUNTS_PER_PAGE, 40);
|
||||
notificationPerPage = sharedpreferences.getInt(Helper.SET_NOTIFICATIONS_PER_PAGE, 40);
|
||||
userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
|
||||
}
|
||||
|
||||
/***
|
||||
|
@ -308,7 +311,7 @@ public class API {
|
|||
}
|
||||
|
||||
/**
|
||||
* Retrieves home timeline for the account since an id *synchronously*
|
||||
* Retrieves home timeline for the account since an Id value *synchronously*
|
||||
* @return List<Status>
|
||||
*/
|
||||
public List<Status> getHomeTimelineSinceId(String since_id) {
|
||||
|
@ -352,14 +355,6 @@ public class API {
|
|||
return statuses;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves public timeline for the account *synchronously*
|
||||
* @param local boolean only local timeline
|
||||
* @return List<Status>
|
||||
*/
|
||||
public List<Status> getPublicTimeline(boolean local){
|
||||
return getPublicTimeline(local, null, null, tootPerPage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves public timeline for the account *synchronously*
|
||||
|
@ -670,10 +665,8 @@ public class API {
|
|||
if( status.getIn_reply_to_id() != null)
|
||||
params.put("in_reply_to_id", status.getIn_reply_to_id());
|
||||
if( status.getMedia_attachments() != null && status.getMedia_attachments().size() > 0 ) {
|
||||
int i = 0;
|
||||
for(Attachment attachment: status.getMedia_attachments()) {
|
||||
params.add("media_ids[]", attachment.getId());
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if( status.isSensitive())
|
||||
|
@ -704,7 +697,7 @@ public class API {
|
|||
}
|
||||
});
|
||||
}else{
|
||||
delete(action, params, new JsonHttpResponseHandler() {
|
||||
delete(action, null, new JsonHttpResponseHandler() {
|
||||
|
||||
@Override
|
||||
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
|
||||
|
@ -1167,21 +1160,39 @@ public class API {
|
|||
SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
||||
String prefKeyOauthTokenT = sharedpreferences.getString(Helper.PREF_KEY_OAUTH_TOKEN, null);
|
||||
client.addHeader("Authorization", "Bearer "+prefKeyOauthTokenT);
|
||||
client.get(getAbsoluteUrl(action), params, responseHandler);
|
||||
try {
|
||||
client.setUserAgent(USER_AGENT);
|
||||
client.setSSLSocketFactory(new MastalabSSLSocketFactory(MastalabSSLSocketFactory.getKeystore()));
|
||||
client.get(getAbsoluteUrl(action), params, responseHandler);
|
||||
} catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException | UnrecoverableKeyException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void post(String action, RequestParams params, AsyncHttpResponseHandler responseHandler) {
|
||||
SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
||||
String prefKeyOauthTokenT = sharedpreferences.getString(Helper.PREF_KEY_OAUTH_TOKEN, null);
|
||||
client.addHeader("Authorization", "Bearer "+prefKeyOauthTokenT);
|
||||
client.post(getAbsoluteUrl(action), params, responseHandler);
|
||||
try {
|
||||
client.setUserAgent(USER_AGENT);
|
||||
client.setSSLSocketFactory(new MastalabSSLSocketFactory(MastalabSSLSocketFactory.getKeystore()));
|
||||
client.post(getAbsoluteUrl(action), params, responseHandler);
|
||||
} catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException | UnrecoverableKeyException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void delete(String action, RequestParams params, AsyncHttpResponseHandler responseHandler){
|
||||
SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
||||
String prefKeyOauthTokenT = sharedpreferences.getString(Helper.PREF_KEY_OAUTH_TOKEN, null);
|
||||
client.addHeader("Authorization", "Bearer "+prefKeyOauthTokenT);
|
||||
client.delete(getAbsoluteUrl(action), params, responseHandler);
|
||||
try {
|
||||
client.setUserAgent(USER_AGENT);
|
||||
client.setSSLSocketFactory(new MastalabSSLSocketFactory(MastalabSSLSocketFactory.getKeystore()));
|
||||
client.delete(getAbsoluteUrl(action), params, responseHandler);
|
||||
} catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException | UnrecoverableKeyException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private String getAbsoluteUrl(String action) {
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
package fr.gouv.etalab.mastodon.client;
|
||||
|
||||
/**
|
||||
* Created by Thomas on 20/05/2017.
|
||||
* Custom MySSLSocketFactory
|
||||
*/
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.Socket;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.UnrecoverableKeyException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLSocket;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
|
||||
/**
|
||||
* This file is introduced to fix HTTPS Post bug on API < ICS see
|
||||
* https://code.google.com/p/android/issues/detail?id=13117#c14 <p> </p> Warning! This omits SSL
|
||||
* certificate validation on every device, use with caution
|
||||
*/
|
||||
class MastalabSSLSocketFactory extends com.loopj.android.http.MySSLSocketFactory {
|
||||
|
||||
private final SSLContext sslContext = SSLContext.getInstance("TLS");
|
||||
/**
|
||||
* Creates a new SSL Socket Factory with the given KeyStore.
|
||||
*
|
||||
* @param truststore A KeyStore to create the SSL Socket Factory in context of
|
||||
* @throws NoSuchAlgorithmException NoSuchAlgorithmException
|
||||
* @throws KeyManagementException KeyManagementException
|
||||
* @throws KeyStoreException KeyStoreException
|
||||
* @throws UnrecoverableKeyException UnrecoverableKeyException
|
||||
*/
|
||||
MastalabSSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
|
||||
super(truststore);
|
||||
X509TrustManager tm = new X509TrustManager() {
|
||||
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
|
||||
}
|
||||
|
||||
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
|
||||
}
|
||||
|
||||
public X509Certificate[] getAcceptedIssuers() {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
sslContext.init(null, new TrustManager[]{tm}, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException {
|
||||
return enableTLSOnSocket(sslContext.getSocketFactory().createSocket(socket, host, port, autoClose));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket() throws IOException {
|
||||
return enableTLSOnSocket(sslContext.getSocketFactory().createSocket());
|
||||
}
|
||||
|
||||
private Socket enableTLSOnSocket(Socket socket) {
|
||||
if(socket != null && (socket instanceof SSLSocket)) {
|
||||
((SSLSocket)socket).setEnabledProtocols(new String[] {"TLSv1.1", "TLSv1.2"});
|
||||
}
|
||||
return socket;
|
||||
}
|
||||
}
|
|
@ -14,16 +14,24 @@
|
|||
* see <http://www.gnu.org/licenses>. */
|
||||
package fr.gouv.etalab.mastodon.client;
|
||||
|
||||
import android.os.Build;
|
||||
|
||||
import com.loopj.android.http.AsyncHttpClient;
|
||||
import com.loopj.android.http.AsyncHttpResponseHandler;
|
||||
import com.loopj.android.http.RequestParams;
|
||||
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.UnrecoverableKeyException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import fr.gouv.etalab.mastodon.helper.Helper;
|
||||
|
||||
import static fr.gouv.etalab.mastodon.helper.Helper.USER_AGENT;
|
||||
|
||||
/**
|
||||
* Created by Thomas on 23/04/2017.
|
||||
* Client to call urls
|
||||
|
@ -37,13 +45,26 @@ public class OauthClient {
|
|||
|
||||
public void get(String action, HashMap<String, String> paramaters, AsyncHttpResponseHandler responseHandler) {
|
||||
client.setTimeout(5000);
|
||||
client.setUserAgent(USER_AGENT);
|
||||
RequestParams params = hashToRequestParams(paramaters);
|
||||
try {
|
||||
client.setSSLSocketFactory(new MastalabSSLSocketFactory(MastalabSSLSocketFactory.getKeystore()));
|
||||
client.post(getAbsoluteUrl(action), params, responseHandler);
|
||||
} catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException | UnrecoverableKeyException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
client.get(getAbsoluteUrl(action), params, responseHandler);
|
||||
}
|
||||
|
||||
public void post(String action, HashMap<String, String> paramaters, AsyncHttpResponseHandler responseHandler) {
|
||||
RequestParams params = hashToRequestParams(paramaters);
|
||||
client.post(getAbsoluteUrl(action), params, responseHandler);
|
||||
try {
|
||||
client.setUserAgent(USER_AGENT);
|
||||
client.setSSLSocketFactory(new MastalabSSLSocketFactory(MastalabSSLSocketFactory.getKeystore()));
|
||||
client.post(getAbsoluteUrl(action), params, responseHandler);
|
||||
} catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException | UnrecoverableKeyException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private String getAbsoluteUrl(String action) {
|
||||
|
|
|
@ -14,10 +14,12 @@ package fr.gouv.etalab.mastodon.fragments;
|
|||
* You should have received a copy of the GNU General Public License along with Thomas Schneider; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.content.LocalBroadcastManager;
|
||||
import android.support.v4.widget.SwipeRefreshLayout;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
|
@ -58,6 +60,7 @@ public class DisplayAccountsFragment extends Fragment implements OnRetrieveAccou
|
|||
private SwipeRefreshLayout swipeRefreshLayout;
|
||||
private int accountPerPage;
|
||||
private String targetedId;
|
||||
private boolean hideHeader = false;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
|
@ -69,6 +72,7 @@ public class DisplayAccountsFragment extends Fragment implements OnRetrieveAccou
|
|||
if (bundle != null) {
|
||||
type = (RetrieveAccountsAsyncTask.Type) bundle.get("type");
|
||||
targetedId = bundle.getString("targetedId", null);
|
||||
hideHeader = bundle.getBoolean("hideHeader", false);
|
||||
}
|
||||
max_id = null;
|
||||
firstLoad = true;
|
||||
|
@ -78,7 +82,7 @@ public class DisplayAccountsFragment extends Fragment implements OnRetrieveAccou
|
|||
swipeRefreshLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.swipeContainer);
|
||||
SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
||||
accountPerPage = sharedpreferences.getInt(Helper.SET_ACCOUNTS_PER_PAGE, 40);
|
||||
ListView lv_accounts = (ListView) rootView.findViewById(R.id.lv_accounts);
|
||||
final ListView lv_accounts = (ListView) rootView.findViewById(R.id.lv_accounts);
|
||||
|
||||
mainLoader = (RelativeLayout) rootView.findViewById(R.id.loader);
|
||||
nextElementLoader = (RelativeLayout) rootView.findViewById(R.id.loading_next_accounts);
|
||||
|
@ -109,6 +113,35 @@ public class DisplayAccountsFragment extends Fragment implements OnRetrieveAccou
|
|||
}
|
||||
});
|
||||
|
||||
//Hide account header when scrolling for ShowAccountActivity
|
||||
if( hideHeader ) {
|
||||
lv_accounts.setOnScrollListener(new AbsListView.OnScrollListener() {
|
||||
int lastFirstVisibleItem = 0;
|
||||
|
||||
@Override
|
||||
public void onScrollStateChanged(AbsListView view, int scrollState) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
|
||||
if (view.getId() == lv_accounts.getId() && totalItemCount > visibleItemCount) {
|
||||
final int currentFirstVisibleItem = lv_accounts.getFirstVisiblePosition();
|
||||
|
||||
if (currentFirstVisibleItem > lastFirstVisibleItem) {
|
||||
Intent intent = new Intent(Helper.HEADER_ACCOUNT);
|
||||
intent.putExtra("hide", true);
|
||||
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
|
||||
} else if (currentFirstVisibleItem < lastFirstVisibleItem) {
|
||||
Intent intent = new Intent(Helper.HEADER_ACCOUNT);
|
||||
intent.putExtra("hide", false);
|
||||
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
|
||||
}
|
||||
lastFirstVisibleItem = currentFirstVisibleItem;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
|
||||
@Override
|
||||
public void onRefresh() {
|
||||
|
@ -157,7 +190,6 @@ public class DisplayAccountsFragment extends Fragment implements OnRetrieveAccou
|
|||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void onRetrieveAccounts(List<Account> accounts) {
|
||||
|
||||
|
|
|
@ -14,10 +14,12 @@ package fr.gouv.etalab.mastodon.fragments;
|
|||
* You should have received a copy of the GNU General Public License along with Thomas Schneider; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.content.LocalBroadcastManager;
|
||||
import android.support.v4.widget.SwipeRefreshLayout;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
|
@ -25,7 +27,7 @@ import android.view.ViewGroup;
|
|||
import android.widget.AbsListView;
|
||||
import android.widget.ListView;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -46,7 +48,6 @@ import fr.gouv.etalab.mastodon.interfaces.OnRetrieveFeedsInterface;
|
|||
public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsInterface {
|
||||
|
||||
|
||||
private TextView noAction;
|
||||
private boolean flag_loading;
|
||||
private Context context;
|
||||
private AsyncTask<Void, Void, Void> asyncTask;
|
||||
|
@ -57,9 +58,9 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn
|
|||
private RelativeLayout mainLoader, nextElementLoader, textviewNoAction;
|
||||
private boolean firstLoad;
|
||||
private SwipeRefreshLayout swipeRefreshLayout;
|
||||
private int tootPerPage;
|
||||
private String targetedId;
|
||||
private String tag;
|
||||
private boolean hideHeader = false;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
|
@ -72,6 +73,7 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn
|
|||
type = (RetrieveFeedsAsyncTask.Type) bundle.get("type");
|
||||
targetedId = bundle.getString("targetedId", null);
|
||||
tag = bundle.getString("tag", null);
|
||||
hideHeader = bundle.getBoolean("hideHeader", false);
|
||||
}
|
||||
max_id = null;
|
||||
flag_loading = true;
|
||||
|
@ -80,10 +82,9 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn
|
|||
boolean isOnWifi = Helper.isOnWIFI(context);
|
||||
swipeRefreshLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.swipeContainer);
|
||||
SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
||||
tootPerPage = sharedpreferences.getInt(Helper.SET_TOOTS_PER_PAGE, 40);
|
||||
int behaviorWithAttachments = sharedpreferences.getInt(Helper.SET_ATTACHMENT_ACTION, Helper.ATTACHMENT_ALWAYS);
|
||||
|
||||
ListView lv_status = (ListView) rootView.findViewById(R.id.lv_status);
|
||||
final ListView lv_status = (ListView) rootView.findViewById(R.id.lv_status);
|
||||
|
||||
mainLoader = (RelativeLayout) rootView.findViewById(R.id.loader);
|
||||
nextElementLoader = (RelativeLayout) rootView.findViewById(R.id.loading_next_status);
|
||||
|
@ -117,6 +118,35 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn
|
|||
}
|
||||
});
|
||||
|
||||
//Hide account header when scrolling for ShowAccountActivity
|
||||
if( hideHeader ) {
|
||||
lv_status.setOnScrollListener(new AbsListView.OnScrollListener() {
|
||||
int lastFirstVisibleItem = 0;
|
||||
|
||||
@Override
|
||||
public void onScrollStateChanged(AbsListView view, int scrollState) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
|
||||
if (view.getId() == lv_status.getId() && totalItemCount > visibleItemCount) {
|
||||
final int currentFirstVisibleItem = lv_status.getFirstVisiblePosition();
|
||||
|
||||
if (currentFirstVisibleItem > lastFirstVisibleItem) {
|
||||
Intent intent = new Intent(Helper.HEADER_ACCOUNT);
|
||||
intent.putExtra("hide", true);
|
||||
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
|
||||
} else if (currentFirstVisibleItem < lastFirstVisibleItem) {
|
||||
Intent intent = new Intent(Helper.HEADER_ACCOUNT);
|
||||
intent.putExtra("hide", false);
|
||||
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
|
||||
}
|
||||
lastFirstVisibleItem = currentFirstVisibleItem;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
|
||||
@Override
|
||||
public void onRefresh() {
|
||||
|
@ -193,9 +223,7 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn
|
|||
}
|
||||
swipeRefreshLayout.setRefreshing(false);
|
||||
firstLoad = false;
|
||||
if( statuses != null && statuses.size() < tootPerPage )
|
||||
flag_loading = true;
|
||||
else
|
||||
flag_loading = false;
|
||||
flag_loading = false;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,6 +36,8 @@ import android.support.v4.app.NotificationManagerCompat;
|
|||
import android.view.WindowManager;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.loopj.android.http.BuildConfig;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.InetAddress;
|
||||
import java.text.ParseException;
|
||||
|
@ -124,9 +126,10 @@ public class Helper {
|
|||
|
||||
//Receiver
|
||||
public static final String SEARCH_VALIDATE_ACCOUNT = "search_validate_account";
|
||||
public static final String HEADER_ACCOUNT = "header_account";
|
||||
|
||||
|
||||
|
||||
//User agent
|
||||
public static final String USER_AGENT = "Mastalab/"+ BuildConfig.VERSION_NAME + " Android/"+ Build.VERSION.RELEASE;
|
||||
|
||||
/***
|
||||
* Check if the user is connected to Internet
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
android:id="@+id/drawer_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:animateLayoutChanges="true"
|
||||
android:orientation="vertical"
|
||||
>
|
||||
<LinearLayout
|
||||
|
|
Loading…
Reference in New Issue