ca.rmen.android.poetassistant.main.MainActivity.java Source code

Java tutorial

Introduction

Here is the source code for ca.rmen.android.poetassistant.main.MainActivity.java

Source

/*
 * Copyright (c) 2016-2017 Carmen Alvarez
 *
 * This file is part of Poet Assistant.
 *
 * Poet Assistant 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.
 *
 * Poet Assistant 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 Poet Assistant.  If not, see <http://www.gnu.org/licenses/>.
 */

package ca.rmen.android.poetassistant.main;

import android.app.ActivityManager;
import android.app.SearchManager;
import android.content.Context;
import android.content.Intent;
import android.database.DataSetObserver;
import android.databinding.DataBindingUtil;
import android.graphics.drawable.Drawable;
import android.media.AudioManager;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.design.widget.Snackbar;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.SearchView;
import android.text.TextUtils;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.Window;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;

import javax.inject.Inject;

import ca.rmen.android.poetassistant.BuildConfig;
import ca.rmen.android.poetassistant.Constants;
import ca.rmen.android.poetassistant.DaggerHelper;
import ca.rmen.android.poetassistant.Favorites;
import ca.rmen.android.poetassistant.R;
import ca.rmen.android.poetassistant.about.AboutActivity;
import ca.rmen.android.poetassistant.databinding.ActivityMainBinding;
import ca.rmen.android.poetassistant.main.dictionaries.dictionary.Dictionary;
import ca.rmen.android.poetassistant.main.dictionaries.rt.OnFavoriteClickListener;
import ca.rmen.android.poetassistant.main.dictionaries.rt.OnWordClickListener;
import ca.rmen.android.poetassistant.main.dictionaries.rt.Rhymer;
import ca.rmen.android.poetassistant.main.dictionaries.rt.Thesaurus;
import ca.rmen.android.poetassistant.main.dictionaries.search.Search;
import ca.rmen.android.poetassistant.main.reader.ReaderFragment;
import ca.rmen.android.poetassistant.settings.SettingsActivity;
import ca.rmen.android.poetassistant.widget.CABEditText;

public class MainActivity extends AppCompatActivity implements OnWordClickListener, OnFavoriteClickListener,
        WarningNoSpaceDialogFragment.WarningNoSpaceDialogListener, CABEditText.ImeListener {

    private static final String TAG = Constants.TAG + MainActivity.class.getSimpleName();
    private static final String DIALOG_TAG = "dialog";
    private static final String EXTRA_CLEARED_HISTORY = "cleared_history";

    private Search mSearch;
    private ActivityMainBinding mBinding;
    private PagerAdapter mPagerAdapter;
    private String[] mClearedHistory;
    @Inject
    Rhymer mRhymer;
    @Inject
    Thesaurus mThesaurus;
    @Inject
    Dictionary mDictionary;
    @Inject
    Favorites mFavorites;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        if (BuildConfig.DEBUG && ActivityManager.isUserAMonkey()) {
            requestWindowFeature(Window.FEATURE_NO_TITLE);
            getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                    WindowManager.LayoutParams.FLAG_FULLSCREEN);
        }
        super.onCreate(savedInstanceState);
        Log.d(TAG, "onCreate() called with: " + "savedInstanceState = [" + savedInstanceState + "]");
        mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        setSupportActionBar(mBinding.toolbar);
        Intent intent = getIntent();
        Uri data = intent.getData();
        mPagerAdapter = new PagerAdapter(this, getSupportFragmentManager(), intent);
        mPagerAdapter.registerDataSetObserver(mAdapterChangeListener);

        // Set up the ViewPager with the sections adapter.
        mBinding.viewPager.setAdapter(mPagerAdapter);
        mBinding.viewPager.setOffscreenPageLimit(5);
        mBinding.viewPager.addOnPageChangeListener(mOnPageChangeListener);

        mBinding.tabs.setupWithViewPager(mBinding.viewPager);
        AppBarLayoutHelper.enableAutoHide(mBinding);
        mAdapterChangeListener.onChanged();

        // If the app was launched with a query for the a particular tab, focus on that tab.
        if (data != null && data.getHost() != null) {
            Tab tab = Tab.parse(data.getHost());
            if (tab == null)
                tab = Tab.DICTIONARY;
            mBinding.viewPager.setCurrentItem(mPagerAdapter.getPositionForTab(tab));
        } else if (Intent.ACTION_SEND.equals(intent.getAction())) {
            mBinding.viewPager.setCurrentItem(mPagerAdapter.getPositionForTab(Tab.READER));
        }

        mSearch = new Search(this, mBinding.viewPager);
        loadDictionaries();
        setVolumeControlStream(AudioManager.STREAM_MUSIC);
    }

    @Override
    public void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        // If the user cleared search history and rotated the device before the snackbar
        // disappeared, let's show the snackbar again to let them undo.
        if (savedInstanceState.containsKey(EXTRA_CLEARED_HISTORY)) {
            String[] clearedHistory = savedInstanceState.getStringArray(EXTRA_CLEARED_HISTORY);
            mClearedHistory = clearedHistory;
            showClearHistorySnackbar(clearedHistory);
        }
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        // If the user cleared the search history, let's save this info in case the device
        // is rotated, so we can show the snackbar again.
        if (mClearedHistory != null) {
            outState.putStringArray(EXTRA_CLEARED_HISTORY, mClearedHistory);
        }
    }

    /**
     * Load our dictionaries when the activity starts, so that the first search
     * can already be fast.
     */
    private void loadDictionaries() {
        new AsyncTask<Void, Void, Boolean>() {
            @Override
            protected Boolean doInBackground(Void... params) {
                DaggerHelper.getAppComponent(MainActivity.this).inject(MainActivity.this);
                return mRhymer.isLoaded() && mThesaurus.isLoaded() && mDictionary.isLoaded();
            }

            @Override
            protected void onPostExecute(Boolean allDictionariesAreLoaded) {
                Fragment warningNoSpaceDialogFragment = getSupportFragmentManager().findFragmentByTag(DIALOG_TAG);
                if (!allDictionariesAreLoaded && warningNoSpaceDialogFragment == null) {
                    getSupportFragmentManager().beginTransaction()
                            .add(new WarningNoSpaceDialogFragment(), DIALOG_TAG).commit();
                } else if (allDictionariesAreLoaded && warningNoSpaceDialogFragment != null) {
                    getSupportFragmentManager().beginTransaction().remove(warningNoSpaceDialogFragment).commit();
                }
            }
        }.execute();
    }

    @Override
    protected void onNewIntent(Intent intent) {
        Log.d(TAG, "onNewIntent() called with: " + "intent = [" + intent + "]");
        setIntent(intent);
        // The user entered a search term either by typing or by voice
        if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
            String query = intent.getDataString();
            if (TextUtils.isEmpty(query)) {
                query = intent.getStringExtra(SearchManager.QUERY);
            }
            if (TextUtils.isEmpty(query)) {
                CharSequence userQuery = intent.getCharSequenceExtra(SearchManager.USER_QUERY);
                if (!TextUtils.isEmpty(userQuery))
                    query = userQuery.toString();
            }
            if (TextUtils.isEmpty(query))
                return;
            mSearch.addSuggestions(query);
            mSearch.search(query);
        }
        // We got here from a deep link
        else if (Intent.ACTION_VIEW.equals(intent.getAction())) {
            Uri data = getIntent().getData();
            handleDeepLink(data);
        }
        // Play some text in the tts tab
        else if (Intent.ACTION_SEND.equals(intent.getAction())) {
            mBinding.viewPager.setCurrentItem(mPagerAdapter.getPositionForTab(Tab.READER));
            String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT);
            ReaderFragment readerFragment = (ReaderFragment) mPagerAdapter.getFragment(mBinding.viewPager,
                    Tab.READER);
            readerFragment.setText(sharedText);
        }
    }

    private void handleDeepLink(Uri uri) {
        Log.d(TAG, "handleDeepLink() called with: " + "uri = [" + uri + "]");
        if (uri == null)
            return;
        String word = uri.getLastPathSegment();
        if (Constants.DEEP_LINK_QUERY.equals(uri.getHost())) {
            mSearch.search(word);
            mBinding.viewPager.setCurrentItem(mPagerAdapter.getPositionForTab(Tab.DICTIONARY));
        } else {
            Tab tab = Tab.parse(uri.getHost());
            if (tab != null)
                mSearch.search(word, tab);
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        Log.d(TAG, "onCreateOptionsMenu() called with: " + "menu = [" + menu + "]");
        getMenuInflater().inflate(R.menu.menu_main, menu);
        SearchView searchView = (SearchView) menu.findItem(R.id.action_search).getActionView();
        mSearch.setSearchView(searchView);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (item.getItemId() == R.id.action_about) {
            Intent intent = new Intent(this, AboutActivity.class);
            startActivity(intent);
            return true;
        } else if (item.getItemId() == R.id.action_random_word) {
            mSearch.lookupRandom();
            return true;
        } else if (item.getItemId() == R.id.action_clear_search_history) {
            clearSearchHistory();
            return true;
        } else if (item.getItemId() == R.id.action_settings) {
            Intent intent = new Intent(this, SettingsActivity.class);
            startActivity(intent);
            return true;
        } else if (item.getItemId() == R.id.action_wotd_history) {
            mPagerAdapter.setExtraTab(Tab.WOTD);
            mBinding.viewPager.setCurrentItem(mPagerAdapter.getPositionForTab(Tab.WOTD));
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onWordClick(String word, Tab tab) {
        Log.d(TAG, "onWordClick() called with: " + "word = [" + word + "], tab = [" + tab + "]");
        mSearch.search(word, tab);
    }

    @Override
    public void onFavoriteToggled(final String word, boolean isFavorite) {
        if (isFavorite)
            mFavorites.addFavorite(word);
        else
            mFavorites.removeFavorite(word);
    }

    @Override
    public void onWarningNoSpaceDialogDismissed() {
        Log.v(TAG, "onWarningNoSpaceDialogDismissed");
        finish();
    }

    @Override
    public void onImeClosed() {
        // In the reader fragment, when the user taps on the EditText, the soft keyboard is opened, and UI scrolls up, hiding the AppBarLayout.
        // When the user taps back to close the soft keyboard, we should show the AppBarLayout again, or else the only way
        // for the user to access the actionbar + tabs would be to swipe left or right to another fragment.
        AppBarLayoutHelper.forceExpandAppBarLayout(mBinding.appBarLayout);
    }

    /**
     * Clears the search history, and shows a snackbar allowing to undo this clear.
     */
    private void clearSearchHistory() {
        new AsyncTask<Void, Void, String[]>() {

            @Override
            protected String[] doInBackground(Void... voids) {
                return mSearch.clearSearchHistory();
            }

            @Override
            protected void onPostExecute(String[] searchHistory) {
                if (searchHistory.length > 0) {
                    mClearedHistory = searchHistory;
                    showClearHistorySnackbar(searchHistory);
                }
            }
        }.execute();
    }

    private void showClearHistorySnackbar(String[] searchHistory) {
        Snackbar.make(mBinding.getRoot(), R.string.search_history_cleared, Constants.SNACKBAR_UNDO_LENGTH_MS)
                .setAction(R.string.action_undo, view -> mSearch.addSuggestions(searchHistory))
                .addCallback(new Snackbar.Callback() {
                    @Override
                    public void onDismissed(Snackbar snackbar, int event) {
                        mClearedHistory = null;
                    }
                }).show();
    }

    private final ViewPager.OnPageChangeListener mOnPageChangeListener = new ViewPager.SimpleOnPageChangeListener() {
        @Override
        public void onPageSelected(int position) {
            super.onPageSelected(position);

            Tab tab = mPagerAdapter.getTabForPosition(position);

            if (tab != Tab.READER) {
                // Hide the keyboard when we navigate to any tab other than the reader tab.
                InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                imm.hideSoftInputFromWindow(mBinding.viewPager.getWindowToken(), 0);
            }
            if (AppBarLayoutHelper
                    .shouldForceExpandAppBarLayout(mPagerAdapter.getFragment(mBinding.viewPager, tab))) {
                AppBarLayoutHelper.forceExpandAppBarLayout(mBinding.appBarLayout);
            }
        }
    };

    private final DataSetObserver mAdapterChangeListener = new DataSetObserver() {
        @Override
        public void onChanged() {
            for (int i = 0; i < mBinding.tabs.getTabCount(); i++) {
                Drawable icon = mPagerAdapter.getIcon(i);
                TabLayout.Tab tab = mBinding.tabs.getTabAt(i);
                if (tab != null) {
                    if (icon != null) {
                        tab.setIcon(icon);
                    }
                    if (!getResources().getBoolean(R.bool.tab_text)) {
                        tab.setText(null);
                    }
                }
            }
        }
    };

}