<commit_before>package com.pwittchen.search.twitter.ui;

import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import butterknife.Bind;
import butterknife.BindString;
import butterknife.ButterKnife;
import com.github.pwittchen.infinitescroll.library.InfiniteScrollListener;
import com.github.pwittchen.reactivenetwork.library.ConnectivityStatus;
import com.miguelcatalan.materialsearchview.MaterialSearchView;
import com.pwittchen.search.twitter.BaseApplication;
import com.pwittchen.search.twitter.R;
import com.pwittchen.search.twitter.network.NetworkApi;
import com.pwittchen.search.twitter.twitter.TwitterApi;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import rx.Observable;
import rx.Subscriber;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Action1;
import rx.schedulers.Schedulers;
import twitter4j.Status;
import twitter4j.TwitterException;

public final class MainActivity extends AppCompatActivity {
  private String lastKeyword = "";
  private LinearLayoutManager layoutManager;

  private Subscription subDelayedSearch;
  private Subscription subSearchTweets;
  private Subscription subLoadMoreTweets;

  @Inject protected TwitterApi twitterApi;
  @Inject protected NetworkApi networkApi;

  @Bind(R.id.recycler_view_tweets) public RecyclerView recyclerViewTweets;
  @Bind(R.id.toolbar) public Toolbar toolbar;
  @Bind(R.id.search_view) public MaterialSearchView searchView;
  @Bind(R.id.message_container) public LinearLayout messageContainerLayout;
  @Bind(R.id.iv_message_container_image) public ImageView imageViewMessage;
  @Bind(R.id.tv_message_container_text) public TextView textViewMessage;
  @Bind(R.id.pb_loading_more_tweets) public ProgressBar progressLoadingMoreTweets;

  @BindString(R.string.no_internet_connection) public String msgNoInternetConnection;
  @BindString(R.string.cannot_load_more_tweets) public String msgCannotLoadMoreTweets;
  @BindString(R.string.no_tweets) public String msgNoTweets;
  @BindString(R.string.no_tweets_formatted) public String msgNoTweetsFormatted;
  @BindString(R.string.searched_formatted) public String msgSearchedFormatted;
  @BindString(R.string.api_rate_limit_exceeded) public String msgApiRateLimitExceeded;
  @BindString(R.string.error_during_search) public String msgErrorDuringSearch;

  @Override protected void onCreate(final Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    initInjections();
    initRecyclerView();
    setSupportActionBar(toolbar);
    initSearchView();
    setErrorMessage();
  }

  @Override public boolean onCreateOptionsMenu(final Menu menu) {
    getMenuInflater().inflate(R.menu.menu_main, menu);
    final MenuItem item = menu.findItem(R.id.action_search);
    searchView.setMenuItem(item);
    return true;
  }

  @Override protected void onResume() {
    super.onResume();
    setMessageOnConnectivityChange();
  }

  private void setMessageOnConnectivityChange() {
    networkApi.observeConnectivity(getApplicationContext())
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Action1<ConnectivityStatus>() {
          @Override public void call(ConnectivityStatus status) {
            if (messageContainerLayout.getVisibility() == View.VISIBLE) {
              setErrorMessage();
            }
          }
        });
  }

  private void initInjections() {
    ButterKnife.bind(this);
    ((BaseApplication) getApplication()).getComponent().inject(this);
  }

  private void initRecyclerView() {
    recyclerViewTweets.setHasFixedSize(true);
    recyclerViewTweets.setAdapter(new TweetsAdapter(this, new LinkedList<Status>()));
    layoutManager = new LinearLayoutManager(this);
    recyclerViewTweets.setLayoutManager(layoutManager);
    recyclerViewTweets.addOnScrollListener(createInfiniteScrollListener());
  }

  @NonNull private InfiniteScrollListener createInfiniteScrollListener() {
    return new InfiniteScrollListener(twitterApi.getMaxTweetsPerRequest(), layoutManager) {
      @Override public void onScrolledToEnd(final int firstVisibleItemPosition) {
        if (subLoadMoreTweets != null && !subLoadMoreTweets.isUnsubscribed()) {
          return;
        }

        final long lastTweetId = ((TweetsAdapter) recyclerViewTweets.getAdapter()).getLastTweetId();

        subLoadMoreTweets = twitterApi.searchTweets(lastKeyword, lastTweetId)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Subscriber<List<Status>>() {
              @Override public void onStart() {
                progressLoadingMoreTweets.setVisibility(View.VISIBLE);
              }

              @Override public void onCompleted() {
                // we don't have to implement this
              }

              @Override public void onError(Throwable e) {
                if (!networkApi.isConnectedToInternet(MainActivity.this)) {
                  showSnackBar(msgNoInternetConnection);
                } else {
                  showSnackBar(msgCannotLoadMoreTweets);
                }
                progressLoadingMoreTweets.setVisibility(View.GONE);
              }

              @Override public void onNext(List<Status> newTweets) {
                final TweetsAdapter newAdapter = createNewTweetsAdapter(newTweets);
                refreshView(recyclerViewTweets, newAdapter, firstVisibleItemPosition);
                progressLoadingMoreTweets.setVisibility(View.GONE);
                unsubscribe();
              }
            });
      }
    };
  }

  @NonNull private TweetsAdapter createNewTweetsAdapter(List<Status> newTweets) {
    final TweetsAdapter adapter = (TweetsAdapter) recyclerViewTweets.getAdapter();
    final List<Status> oldTweets = adapter.getTweets();
    final List<Status> tweets = new LinkedList<>();
    tweets.addAll(oldTweets);<commit_msg>moving hiding progress to onCompleted() while loading more tweets<commit_after>package com.pwittchen.search.twitter.ui;

import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import butterknife.Bind;
import butterknife.BindString;
import butterknife.ButterKnife;
import com.github.pwittchen.infinitescroll.library.InfiniteScrollListener;
import com.github.pwittchen.reactivenetwork.library.ConnectivityStatus;
import com.miguelcatalan.materialsearchview.MaterialSearchView;
import com.pwittchen.search.twitter.BaseApplication;
import com.pwittchen.search.twitter.R;
import com.pwittchen.search.twitter.network.NetworkApi;
import com.pwittchen.search.twitter.twitter.TwitterApi;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import rx.Observable;
import rx.Subscriber;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Action1;
import rx.schedulers.Schedulers;
import twitter4j.Status;
import twitter4j.TwitterException;

public final class MainActivity extends AppCompatActivity {
  private String lastKeyword = "";
  private LinearLayoutManager layoutManager;

  private Subscription subDelayedSearch;
  private Subscription subSearchTweets;
  private Subscription subLoadMoreTweets;

  @Inject protected TwitterApi twitterApi;
  @Inject protected NetworkApi networkApi;

  @Bind(R.id.recycler_view_tweets) public RecyclerView recyclerViewTweets;
  @Bind(R.id.toolbar) public Toolbar toolbar;
  @Bind(R.id.search_view) public MaterialSearchView searchView;
  @Bind(R.id.message_container) public LinearLayout messageContainerLayout;
  @Bind(R.id.iv_message_container_image) public ImageView imageViewMessage;
  @Bind(R.id.tv_message_container_text) public TextView textViewMessage;
  @Bind(R.id.pb_loading_more_tweets) public ProgressBar progressLoadingMoreTweets;

  @BindString(R.string.no_internet_connection) public String msgNoInternetConnection;
  @BindString(R.string.cannot_load_more_tweets) public String msgCannotLoadMoreTweets;
  @BindString(R.string.no_tweets) public String msgNoTweets;
  @BindString(R.string.no_tweets_formatted) public String msgNoTweetsFormatted;
  @BindString(R.string.searched_formatted) public String msgSearchedFormatted;
  @BindString(R.string.api_rate_limit_exceeded) public String msgApiRateLimitExceeded;
  @BindString(R.string.error_during_search) public String msgErrorDuringSearch;

  @Override protected void onCreate(final Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    initInjections();
    initRecyclerView();
    setSupportActionBar(toolbar);
    initSearchView();
    setErrorMessage();
  }

  @Override public boolean onCreateOptionsMenu(final Menu menu) {
    getMenuInflater().inflate(R.menu.menu_main, menu);
    final MenuItem item = menu.findItem(R.id.action_search);
    searchView.setMenuItem(item);
    return true;
  }

  @Override protected void onResume() {
    super.onResume();
    setMessageOnConnectivityChange();
  }

  private void setMessageOnConnectivityChange() {
    networkApi.observeConnectivity(getApplicationContext())
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Action1<ConnectivityStatus>() {
          @Override public void call(ConnectivityStatus status) {
            if (messageContainerLayout.getVisibility() == View.VISIBLE) {
              setErrorMessage();
            }
          }
        });
  }

  private void initInjections() {
    ButterKnife.bind(this);
    ((BaseApplication) getApplication()).getComponent().inject(this);
  }

  private void initRecyclerView() {
    recyclerViewTweets.setHasFixedSize(true);
    recyclerViewTweets.setAdapter(new TweetsAdapter(this, new LinkedList<Status>()));
    layoutManager = new LinearLayoutManager(this);
    recyclerViewTweets.setLayoutManager(layoutManager);
    recyclerViewTweets.addOnScrollListener(createInfiniteScrollListener());
  }

  @NonNull private InfiniteScrollListener createInfiniteScrollListener() {
    return new InfiniteScrollListener(twitterApi.getMaxTweetsPerRequest(), layoutManager) {
      @Override public void onScrolledToEnd(final int firstVisibleItemPosition) {
        if (subLoadMoreTweets != null && !subLoadMoreTweets.isUnsubscribed()) {
          return;
        }

        final long lastTweetId = ((TweetsAdapter) recyclerViewTweets.getAdapter()).getLastTweetId();

        subLoadMoreTweets = twitterApi.searchTweets(lastKeyword, lastTweetId)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Subscriber<List<Status>>() {
              @Override public void onStart() {
                progressLoadingMoreTweets.setVisibility(View.VISIBLE);
              }

              @Override public void onCompleted() {
                progressLoadingMoreTweets.setVisibility(View.GONE);
                unsubscribe();
              }

              @Override public void onError(Throwable e) {
                if (!networkApi.isConnectedToInternet(MainActivity.this)) {
                  showSnackBar(msgNoInternetConnection);
                } else {
                  showSnackBar(msgCannotLoadMoreTweets);
                }
                progressLoadingMoreTweets.setVisibility(View.GONE);
              }

              @Override public void onNext(List<Status> newTweets) {
                final TweetsAdapter newAdapter = createNewTweetsAdapter(newTweets);
                refreshView(recyclerViewTweets, newAdapter, firstVisibleItemPosition);
              }
            });
      }
    };
  }

  @NonNull private TweetsAdapter createNewTweetsAdapter(List<Status> newTweets) {
    final TweetsAdapter adapter = (TweetsAdapter) recyclerViewTweets.getAdapter();
    final List<Status> oldTweets = adapter.getTweets();
    final List<Status> tweets = new LinkedList<>();
    tweets.addAll(oldTweets);
{'fraction_non_alphanumeric': 0.08940576462406305, 'fraction_numerical': 0.001236380496097674, 'mean_word_length': 4.214343271555197, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1116075', 'n_tokens_mistral': 3781, 'n_tokens_neox': 3680, 'n_words': 641}