org.kiwix.kiwixmobile.KiwixMobileActivity.java Source code

Java tutorial

Introduction

Here is the source code for org.kiwix.kiwixmobile.KiwixMobileActivity.java

Source

/*
 * Copyright 2013 Rashiq Ahmad <rashiq.z@gmail.com>
 *
 * 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
 * any later version.
 *
 * This program 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 this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301, USA.
 */

package org.kiwix.kiwixmobile;

import android.Manifest;
import android.app.Activity;
import android.appwidget.AppWidgetManager;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.support.design.widget.CoordinatorLayout;
import android.support.design.widget.Snackbar;
import android.support.design.widget.TabLayout;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AlertDialog;
import android.support.v7.view.menu.ActionMenuItemView;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.text.SpannableString;
import android.text.style.ForegroundColorSpan;
import android.util.AttributeSet;
import android.util.Log;
import android.view.ActionMode;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.Toast;

import org.json.JSONArray;
import org.kiwix.kiwixmobile.base.BaseActivity;
import org.kiwix.kiwixmobile.bookmarks_view.BookmarksActivity;
import org.kiwix.kiwixmobile.database.BookmarksDao;
import org.kiwix.kiwixmobile.database.KiwixDatabase;
import org.kiwix.kiwixmobile.di.components.ApplicationComponent;
import org.kiwix.kiwixmobile.settings.KiwixSettingsActivity;
import org.kiwix.kiwixmobile.utils.DimenUtils;
import org.kiwix.kiwixmobile.utils.DocumentParser;
import org.kiwix.kiwixmobile.utils.KiwixSearchWidget;
import org.kiwix.kiwixmobile.utils.KiwixTextToSpeech;
import org.kiwix.kiwixmobile.utils.LanguageUtils;
import org.kiwix.kiwixmobile.utils.NetworkUtils;
import org.kiwix.kiwixmobile.utils.RateAppCounter;
import org.kiwix.kiwixmobile.utils.StyleUtils;
import org.kiwix.kiwixmobile.utils.files.FileReader;
import org.kiwix.kiwixmobile.utils.files.FileUtils;
import org.kiwix.kiwixmobile.views.AnimatedProgressBar;
import org.kiwix.kiwixmobile.views.CompatFindActionModeCallback;
import org.kiwix.kiwixmobile.views.web.KiwixWebView;
import org.kiwix.kiwixmobile.views.web.ToolbarScrollingKiwixWebView;
import org.kiwix.kiwixmobile.views.web.ToolbarStaticKiwixWebView;
import org.kiwix.kiwixmobile.zim_manager.ZimManageActivity;
import org.kiwix.kiwixmobile.zim_manager.library_view.LibraryFragment;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import javax.inject.Inject;

import butterknife.BindView;
import butterknife.ButterKnife;
import okhttp3.OkHttpClient;

import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static org.kiwix.kiwixmobile.TableDrawerAdapter.DocumentSection;
import static org.kiwix.kiwixmobile.TableDrawerAdapter.TableClickListener;
import static org.kiwix.kiwixmobile.utils.StyleUtils.dialogStyle;

public class KiwixMobileActivity extends BaseActivity implements WebViewCallback {

    public static final int REQUEST_FILE_SEARCH = 1236;

    public static final int REQUEST_STORAGE_PERMISSION = 1;

    private static final int REQUEST_FILE_SELECT = 1234;

    private static final int REQUEST_PREFERENCES = 1235;

    private static final int BOOKMARK_CHOSEN_REQUEST = 1;

    public static final String TAG_KIWIX = "kiwix";

    public static final String TAG_FILE_SEARCHED = "searchedarticle";

    private static final String TAG_CURRENT_FILE = "currentzimfile";

    private static final String TAG_CURRENT_ARTICLES = "currentarticles";

    private static final String TAG_CURRENT_POSITIONS = "currentpositions";

    private static final String TAG_CURRENT_TAB = "currenttab";

    public static final String PREF_NIGHT_MODE = "pref_nightmode";

    private static final String PREF_KIWIX_MOBILE = "kiwix-mobile";

    private static final String PREF_BACK_TO_TOP = "pref_backtotop";

    private static final String PREF_HIDE_TOOLBAR = "pref_hidetoolbar";

    private static final String PREF_ZOOM = "pref_zoom_slider";

    private static final String PREF_ZOOM_ENABLED = "pref_zoom_enabled";

    private static final String PREF_FULLSCREEN = "pref_fullscreen";

    private static final String PREF_NEW_TAB_BACKGROUND = "pref_newtab_background";

    public static final String PREF_FULL_TEXT_SEARCH = "pref_full_text_search";

    public static final String PREF_STORAGE = "pref_selected_storage";

    public static final String PREF_STORAGE_TITLE = "pref_selected_title";

    public static final String contactEmailAddress = "android@kiwix.org";

    public static boolean isFullscreenOpened;

    private boolean isBackToTopEnabled = false;

    private boolean wasHideToolbar = false;

    private boolean isHideToolbar = false;

    private boolean isSpeaking = false;

    protected boolean requestClearHistoryAfterLoad = false;

    protected boolean requestInitAllMenuItems = false;

    private boolean isOpenNewTabInBackground;

    public static boolean refresh;

    public static boolean wifiOnly;

    private static Uri KIWIX_LOCAL_MARKET_URI;

    private static Uri KIWIX_BROWSER_MARKET_URI;

    private String documentParserJs;

    public static boolean nightMode;

    private DocumentParser documentParser;

    public List<TableDrawerAdapter.DocumentSection> documentSections;

    public Menu menu;

    private ArrayList<String> bookmarks;

    private List<KiwixWebView> mWebViews = new ArrayList<>();

    private KiwixTextToSpeech tts;

    private CompatFindActionModeCallback compatCallback;

    private TabDrawerAdapter tabDrawerAdapter;

    private int currentWebViewIndex = 0;

    private File file;

    private ActionMode actionMode = null;

    private KiwixWebView tempForUndo;

    private RateAppCounter visitCounterPref;

    private int tempVisitCount;

    private boolean isFirstRun;

    private SharedPreferences settings;

    private BookmarksDao bookmarksDao;

    @BindView(R.id.toolbar)
    Toolbar toolbar;

    @BindView(R.id.button_backtotop)
    Button backToTopButton;

    @BindView(R.id.button_stop_tts)
    Button stopTTSButton;

    @BindView(R.id.button_pause_tts)
    Button pauseTTSButton;

    @BindView(R.id.tts_controls)
    LinearLayout TTSControls;

    @BindView(R.id.toolbar_layout)
    RelativeLayout toolbarContainer;

    @BindView(R.id.progress_view)
    AnimatedProgressBar progressBar;

    @BindView(R.id.FullscreenControlButton)
    ImageButton exitFullscreenButton;

    @BindView(R.id.snackbar_layout)
    CoordinatorLayout snackbarLayout;

    @BindView(R.id.new_tab_button)
    RelativeLayout newTabButton;

    @BindView(R.id.drawer_layout)
    DrawerLayout drawerLayout;

    @BindView(R.id.left_drawer)
    LinearLayout tabDrawerLeftContainer;

    @BindView(R.id.right_drawer)
    LinearLayout tableDrawerRightContainer;

    @BindView(R.id.left_drawer_list)
    RecyclerView tabDrawerLeft;

    @BindView(R.id.right_drawer_list)
    RecyclerView tableDrawerRight;

    @BindView(R.id.content_frame)
    FrameLayout contentFrame;

    @BindView(R.id.action_back_button)
    ImageView tabBackButton;

    @BindView(R.id.action_forward_button)
    ImageView tabForwardButton;

    @BindView(R.id.action_back)
    View tabBackButtonContainer;

    @BindView(R.id.action_forward)
    View tabForwardButtonContainer;

    @BindView(R.id.page_bottom_tab_layout)
    TabLayout pageBottomTabLayout;

    @Inject
    OkHttpClient okHttpClient;

    @Override
    public void onActionModeStarted(ActionMode mode) {
        if (actionMode == null) {
            actionMode = mode;
            Menu menu = mode.getMenu();
            // Inflate custom menu icon.
            getMenuInflater().inflate(R.menu.menu_webview_action, menu);
            readAloudSelection(menu);
        }
        super.onActionModeStarted(mode);
    }

    @Override
    public void onActionModeFinished(ActionMode mode) {
        actionMode = null;
        super.onActionModeFinished(mode);
    }

    private void readAloudSelection(Menu menu) {
        if (menu != null) {
            menu.findItem(R.id.menu_speak_text).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
                @Override
                public boolean onMenuItemClick(MenuItem item) {
                    Log.i(TAG_KIWIX, "Speaking selection.");
                    tts.readSelection(getCurrentWebView());
                    if (actionMode != null) {
                        actionMode.finish();
                    }
                    return true;
                }
            });
        }
    }

    @NonNull
    private final TabLayout.OnTabSelectedListener pageBottomTabListener = new TabLayout.OnTabSelectedListener() {
        @Override
        public void onTabSelected(TabLayout.Tab tab) {
            PageBottomTab.of(tab.getPosition()).select(pageActionTabsCallback);
        }

        @Override
        public void onTabUnselected(TabLayout.Tab tab) {
        }

        @Override
        public void onTabReselected(TabLayout.Tab tab) {
            onTabSelected(tab);
        }
    };

    private PageBottomTab.Callback pageActionTabsCallback = new PageBottomTab.Callback() {
        @Override
        public void onHomeTabSelected() {
            openMainPage();
        }

        @Override
        public void onFindInPageTabSelected() {
            compatCallback.setActive();
            compatCallback.setWebView(getCurrentWebView());
            startSupportActionMode(compatCallback);
            compatCallback.showSoftInput();
        }

        @Override
        public void onFullscreenTabSelected() {
            if (isFullscreenOpened) {
                closeFullScreen();
            } else {
                openFullScreen();
            }
        }

        @Override
        public void onRandomArticleTabSelected() {
            openRandomArticle();
        }
    };

    @Override
    public void onCreate(Bundle savedInstanceState) {
        SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
        wifiOnly = sharedPreferences.getBoolean(KiwixSettingsActivity.PREF_WIFI_ONLY, true);
        nightMode = KiwixSettingsActivity.nightMode(sharedPreferences);
        if (nightMode) {
            setTheme(R.style.AppTheme_Night);
        }
        super.onCreate(savedInstanceState);
        handleLocaleCheck();
        setContentView(R.layout.main);
        ButterKnife.bind(this);

        setUpToolbar();

        checkForRateDialog();

        initPlayStoreUri();

        isHideToolbar = sharedPreferences.getBoolean(PREF_HIDE_TOOLBAR, false);

        FileReader fileReader = new FileReader();
        documentParserJs = fileReader.readFile("js/documentParser.js", this);

        newTabButton.setOnClickListener((View view) -> newTab());
        tabForwardButtonContainer.setOnClickListener((View view) -> {
            if (getCurrentWebView().canGoForward()) {
                getCurrentWebView().goForward();
            }
        });
        tabBackButtonContainer.setOnClickListener((View view) -> {
            if (getCurrentWebView().canGoBack()) {
                getCurrentWebView().goBack();
            }
        });

        documentSections = new ArrayList<>();
        tabDrawerAdapter = new TabDrawerAdapter(mWebViews);
        tabDrawerLeft.setLayoutManager(new LinearLayoutManager(this));
        tabDrawerLeft.setAdapter(tabDrawerAdapter);
        tableDrawerRight.setLayoutManager(new LinearLayoutManager(this));

        TableDrawerAdapter tableDrawerAdapter = new TableDrawerAdapter();
        tableDrawerRight.setAdapter(tableDrawerAdapter);
        tableDrawerAdapter.setTableClickListener(new TableClickListener() {
            @Override
            public void onHeaderClick(View view) {
                getCurrentWebView().setScrollY(0);
                drawerLayout.closeDrawer(GravityCompat.END);
            }

            @Override
            public void onSectionClick(View view, int position) {
                getCurrentWebView().loadUrl("javascript:document.getElementById('"
                        + documentSections.get(position).id + "').scrollIntoView();");

                drawerLayout.closeDrawers();
            }
        });

        tableDrawerAdapter.notifyDataSetChanged();

        tabDrawerAdapter.setTabClickListener(new TabDrawerAdapter.TabClickListener() {
            @Override
            public void onSelectTab(View view, int position) {
                selectTab(position);
            }

            @Override
            public void onCloseTab(View view, int position) {
                closeTab(position);
            }
        });

        ActionBarDrawerToggle drawerToggle = new KiwixActionBarDrawerToggle(this, drawerLayout, toolbar);

        drawerLayout.addDrawerListener(drawerToggle);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setHomeButtonEnabled(true);
        drawerToggle.syncState();

        compatCallback = new CompatFindActionModeCallback(this);
        setUpTTS();
        documentParser = new DocumentParser(new DocumentParser.SectionsListener() {
            @Override
            public void sectionsLoaded(String title, List<DocumentSection> sections) {
                documentSections.addAll(sections);
                tableDrawerAdapter.setTitle(title);
                tableDrawerAdapter.setSections(documentSections);
                tableDrawerAdapter.notifyDataSetChanged();
            }

            @Override
            public void clearSections() {
                documentSections.clear();
                tableDrawerAdapter.notifyDataSetChanged();
            }
        });

        manageExternalLaunchAndRestoringViewState();
        setUpExitFullscreenButton();
        loadPrefs();
        updateTitle(ZimContentProvider.getZimFileTitle());

        Intent i = getIntent();
        if (i.getBooleanExtra("library", false)) {
            manageZimFiles(2);
        }
        if (i.hasExtra(TAG_FILE_SEARCHED)) {
            searchForTitle(i.getStringExtra(TAG_FILE_SEARCHED));
            selectTab(mWebViews.size() - 1);
        }
        if (i.hasExtra("choseXURL")) {
            newTab();
            getCurrentWebView().loadUrl(i.getStringExtra("choseXURL"));
        }
        if (i.hasExtra("choseXTitle")) {
            newTab();
            getCurrentWebView().loadUrl(i.getStringExtra("choseXTitle"));
        }
        if (i.hasExtra("zimFile")) {
            File file = new File(FileUtils.getFileName(i.getStringExtra("zimFile")));
            LibraryFragment.mService.cancelNotification(i.getIntExtra("notificationID", 0));
            Uri uri = Uri.fromFile(file);

            finish();
            Intent zimFile = new Intent(KiwixMobileActivity.this, KiwixMobileActivity.class);
            zimFile.setData(uri);
            startActivity(zimFile);
        }

        pageBottomTabLayout.addOnTabSelectedListener(pageBottomTabListener);

        wasHideToolbar = isHideToolbar;
    }

    private void initPlayStoreUri() {
        KIWIX_LOCAL_MARKET_URI = Uri.parse("market://details?id=" + getPackageName());
        KIWIX_BROWSER_MARKET_URI = Uri.parse("http://play.google.com/store/apps/details?id=" + getPackageName());
    }

    private void checkForRateDialog() {
        settings = PreferenceManager.getDefaultSharedPreferences(this);
        isFirstRun = settings.getBoolean("isFirstRun", true);
        visitCounterPref = new RateAppCounter(this);
        tempVisitCount = visitCounterPref.getCount();
        ++tempVisitCount;
        visitCounterPref.setCount(tempVisitCount);

        if (tempVisitCount >= 5 && !visitCounterPref.getNoThanksState() && NetworkUtils.isNetworkAvailable(this)
                && !BuildConfig.DEBUG) {
            showRateDialog();
        }
    }

    public void showRateDialog() {
        String title = getString(R.string.rate_dialog_title);
        String message = getString(R.string.rate_dialog_msg_1) + " " + getString(R.string.app_name)
                + getString(R.string.rate_dialog_msg_2);
        String positive = getString(R.string.rate_dialog_positive);
        String negative = getString(R.string.rate_dialog_negative);
        String neutral = getString(R.string.rate_dialog_neutral);

        new AlertDialog.Builder(this, dialogStyle()).setTitle(title).setMessage(message)
                .setPositiveButton(positive, (dialog, id) -> {
                    visitCounterPref.setNoThanksState(true);
                    goToRateApp();
                }).setNegativeButton(negative, (dialog, id) -> {
                    visitCounterPref.setNoThanksState(true);
                }).setNeutralButton(neutral, (dialog, id) -> {
                    tempVisitCount = 0;
                    visitCounterPref.setCount(tempVisitCount);
                }).setIcon(ContextCompat.getDrawable(this, R.mipmap.kiwix_icon)).show();
    }

    private void setUpToolbar() {

        setSupportActionBar(toolbar);
    }

    private void goToSearch(boolean isVoice) {
        final String zimFile = ZimContentProvider.getZimFile();
        saveTabStates();
        Intent i = new Intent(KiwixMobileActivity.this, SearchActivity.class);
        i.putExtra("zimFile", zimFile);
        if (isVoice) {
            i.putExtra("isWidgetVoice", true);
        }
        startActivityForResult(i, REQUEST_FILE_SEARCH);
    }

    private void goToRateApp() {

        Intent goToMarket = new Intent(Intent.ACTION_VIEW, KIWIX_LOCAL_MARKET_URI);

        goToMarket.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET
                | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);

        try {
            startActivity(goToMarket);
        } catch (ActivityNotFoundException e) {
            startActivity(new Intent(Intent.ACTION_VIEW, KIWIX_BROWSER_MARKET_URI));
        }
    }

    private void updateTitle(String zimFileTitle) {
        if (zimFileTitle == null || zimFileTitle.trim().isEmpty()) {
            getSupportActionBar().setTitle(createMenuText(getString(R.string.app_name)));
        } else {
            getSupportActionBar().setTitle(createMenuText(zimFileTitle));
        }
    }

    private void setUpTTS() {
        tts = new KiwixTextToSpeech(this, () -> {
            if (menu != null) {
                menu.findItem(R.id.menu_read_aloud).setVisible(true);
            }
        }, new KiwixTextToSpeech.OnSpeakingListener() {
            @Override
            public void onSpeakingStarted() {
                isSpeaking = true;
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        menu.findItem(R.id.menu_read_aloud)
                                .setTitle(createMenuItem(getResources().getString(R.string.menu_read_aloud_stop)));
                        TTSControls.setVisibility(View.VISIBLE);
                    }
                });
            }

            @Override
            public void onSpeakingEnded() {
                isSpeaking = false;
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        menu.findItem(R.id.menu_read_aloud)
                                .setTitle(createMenuItem(getResources().getString(R.string.menu_read_aloud)));
                        TTSControls.setVisibility(View.GONE);
                        pauseTTSButton.setText(R.string.tts_pause);
                    }
                });
            }
        });

        pauseTTSButton.setOnClickListener(view -> {
            if (tts.currentTTSTask == null) {
                tts.stop();
                return;
            }

            if (tts.currentTTSTask.paused) {
                tts.pauseOrResume();
                pauseTTSButton.setText(R.string.tts_pause);
            } else {
                tts.pauseOrResume();
                pauseTTSButton.setText(R.string.tts_resume);
            }
        });

        stopTTSButton.setOnClickListener((View view) -> tts.stop());
    }

    // Reset the Locale and change the font of all TextViews and its subclasses, if necessary
    private void handleLocaleCheck() {
        LanguageUtils.handleLocaleChange(this);
        new LanguageUtils(this).changeFont(getLayoutInflater());
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // TODO create a base Activity class that class this.
        FileUtils.deleteCachedFiles(this);
        tts.shutdown();
    }

    @Override
    protected void setupDagger(ApplicationComponent appComponent) {
        appComponent.inject(this);
    }

    private void updateTableOfContents() {
        getCurrentWebView().loadUrl("javascript:(" + documentParserJs + ")()");
    }

    private void shrinkDrawers() {
        ViewGroup.MarginLayoutParams leftLayoutMargins = (ViewGroup.MarginLayoutParams) tabDrawerLeftContainer
                .getLayoutParams(),
                rightLayoutMargins = (ViewGroup.MarginLayoutParams) tableDrawerRightContainer.getLayoutParams();

        leftLayoutMargins.topMargin = DimenUtils.getToolbarHeight(KiwixMobileActivity.this);
        rightLayoutMargins.topMargin = DimenUtils.getToolbarHeight(KiwixMobileActivity.this);
        tabDrawerLeftContainer.setLayoutParams(leftLayoutMargins);
        tableDrawerRightContainer.setLayoutParams(rightLayoutMargins);
    }

    private void expandDrawers() {
        ViewGroup.MarginLayoutParams leftLayoutMargins = (ViewGroup.MarginLayoutParams) tabDrawerLeftContainer
                .getLayoutParams(),
                rightLayoutMargins = (ViewGroup.MarginLayoutParams) tableDrawerRightContainer.getLayoutParams();
        leftLayoutMargins.topMargin = 0;
        rightLayoutMargins.topMargin = 0;
        tabDrawerLeftContainer.setLayoutParams(leftLayoutMargins);
        tableDrawerRightContainer.setLayoutParams(rightLayoutMargins);
    }

    private KiwixWebView getWebView(String url) {
        AttributeSet attrs = StyleUtils.getAttributes(this, R.xml.webview);
        KiwixWebView webView;
        if (isHideToolbar) {
            webView = new ToolbarScrollingKiwixWebView(KiwixMobileActivity.this, this, toolbarContainer,
                    pageBottomTabLayout, attrs);
            ((ToolbarScrollingKiwixWebView) webView).setOnToolbarVisibilityChangeListener(
                    new ToolbarScrollingKiwixWebView.OnToolbarVisibilityChangeListener() {
                        @Override
                        public void onToolbarDisplayed() {
                            shrinkDrawers();
                        }

                        @Override
                        public void onToolbarHidden() {
                            expandDrawers();
                        }
                    });
        } else {
            webView = new ToolbarStaticKiwixWebView(KiwixMobileActivity.this, this, toolbarContainer, attrs);
        }
        webView.loadUrl(url);
        webView.loadPrefs();

        return webView;
    }

    private KiwixWebView newTab() {
        String mainPage = Uri.parse(ZimContentProvider.CONTENT_URI + ZimContentProvider.getMainPage()).toString();
        return newTab(mainPage);
    }

    private KiwixWebView newTab(String url) {
        KiwixWebView webView = getWebView(url);
        mWebViews.add(webView);
        selectTab(mWebViews.size() - 1);
        tabDrawerAdapter.notifyDataSetChanged();
        setUpWebView();
        documentParser.initInterface(webView);
        return webView;
    }

    private void newTabInBackground(String url) {
        KiwixWebView webView = getWebView(url);
        mWebViews.add(webView);
        tabDrawerAdapter.notifyDataSetChanged();
        setUpWebView();
        documentParser.initInterface(webView);
    }

    private void restoreTab(int index) {
        mWebViews.add(index, tempForUndo);
        tabDrawerAdapter.notifyDataSetChanged();
        selectTab(index);
        setUpWebView();
    }

    private void closeTab(int index) {
        tempForUndo = mWebViews.get(index);
        int selectedPosition = tabDrawerAdapter.getSelectedPosition();
        int newSelectedPosition = selectedPosition;

        if (index <= selectedPosition)
            newSelectedPosition = selectedPosition - 1;
        if (index == 0)
            newSelectedPosition = 0;
        if (mWebViews.size() == 1)
            newTab();

        mWebViews.remove(index);
        showRestoreTabSnackbar(index);
        selectTab(newSelectedPosition);
        tabDrawerAdapter.notifyDataSetChanged();
    }

    private void showRestoreTabSnackbar(final int index) {
        Snackbar snackbar = Snackbar.make(snackbarLayout, getString(R.string.tab_closed), Snackbar.LENGTH_LONG)
                .setAction(getString(R.string.undo), v -> {
                    restoreTab(index);
                    drawerLayout.openDrawer(GravityCompat.START);
                });
        snackbar.setActionTextColor(Color.WHITE);
        snackbar.show();
    }

    private void selectTab(int position) {
        currentWebViewIndex = position;
        tabDrawerAdapter.setSelected(position);
        contentFrame.removeAllViews();

        KiwixWebView webView = mWebViews.get(position);
        contentFrame.addView(webView);
        tabDrawerAdapter.setSelected(currentWebViewIndex);

        if (drawerLayout.isDrawerOpen(GravityCompat.START)) {
            new Handler().postDelayed(() -> drawerLayout.closeDrawers(), 150);
        }
        loadPrefs();
        if (menu != null) {
            refreshBookmarkSymbol(menu);
        }
        updateTableOfContents();

        if (isHideToolbar) {
            ((ToolbarScrollingKiwixWebView) webView).ensureToolbarDisplayed();
        }
    }

    public KiwixWebView getCurrentWebView() {
        if (mWebViews.size() == 0)
            return newTab();
        if (currentWebViewIndex < mWebViews.size()) {
            return mWebViews.get(currentWebViewIndex);
        } else {
            return mWebViews.get(0);
        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        KiwixWebView webView = getCurrentWebView();
        switch (item.getItemId()) {

        case R.id.menu_home:
        case android.R.id.home:
            openMainPage();
            break;

        case R.id.menu_searchintext:
            compatCallback.setActive();
            compatCallback.setWebView(webView);
            startSupportActionMode(compatCallback);
            compatCallback.showSoftInput();
            break;

        case R.id.menu_bookmarks:
            toggleBookmark();
            break;

        case R.id.menu_bookmarks_list:
            goToBookmarks();
            break;

        case R.id.menu_randomarticle:
            openRandomArticle();
            break;

        case R.id.menu_help:
            showHelpPage();
            break;

        case R.id.menu_openfile:
            manageZimFiles(0);
            break;

        case R.id.menu_settings:
            selectSettings();
            break;

        case R.id.menu_read_aloud:
            if (TTSControls.getVisibility() == View.GONE) {
                if (isBackToTopEnabled) {
                    backToTopButton.setVisibility(View.INVISIBLE);
                }
            } else if (TTSControls.getVisibility() == View.VISIBLE) {
                if (isBackToTopEnabled) {
                    backToTopButton.setVisibility(View.VISIBLE);
                }
            }
            readAloud();
            break;

        case R.id.menu_fullscreen:
            if (isFullscreenOpened) {
                closeFullScreen();
            } else {
                openFullScreen();
            }
            break;

        default:
            break;
        }

        return super.onOptionsItemSelected(item);
    }

    private void goToBookmarks() {
        saveTabStates();
        Intent intentBookmarks = new Intent(getBaseContext(), BookmarksActivity.class);
        intentBookmarks.putExtra("bookmark_contents", bookmarks);
        startActivityForResult(intentBookmarks, BOOKMARK_CHOSEN_REQUEST);
    }

    private void openFullScreen() {

        toolbarContainer.setVisibility(View.GONE);
        pageBottomTabLayout.setVisibility(View.GONE);
        exitFullscreenButton.setVisibility(View.VISIBLE);
        int fullScreenFlag = WindowManager.LayoutParams.FLAG_FULLSCREEN;
        int classicScreenFlag = WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN;
        getWindow().addFlags(fullScreenFlag);
        getWindow().clearFlags(classicScreenFlag);
        SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
        SharedPreferences.Editor editor = settings.edit();
        editor.putBoolean(PREF_FULLSCREEN, true);
        editor.apply();
        expandDrawers();
        isFullscreenOpened = true;
        getCurrentWebView().requestLayout();
        if (isHideToolbar) {
            toolbarContainer.setTranslationY(0);
            this.getCurrentWebView().setTranslationY(0);
        }
    }

    private void closeFullScreen() {
        toolbarContainer.setVisibility(View.VISIBLE);
        if (settings.getBoolean(KiwixSettingsActivity.PREF_BOTTOM_TOOLBAR, false)) {
            pageBottomTabLayout.setVisibility(View.VISIBLE);
        }
        exitFullscreenButton.setVisibility(View.INVISIBLE);
        int fullScreenFlag = WindowManager.LayoutParams.FLAG_FULLSCREEN;
        int classicScreenFlag = WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN;
        getWindow().clearFlags(fullScreenFlag);
        getWindow().addFlags(classicScreenFlag);
        SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
        SharedPreferences.Editor editor = settings.edit();
        editor.putBoolean(PREF_FULLSCREEN, false);
        editor.apply();
        shrinkDrawers();
        isFullscreenOpened = false;
        getCurrentWebView().requestLayout();
        if (isHideToolbar) {
            toolbarContainer.setTranslationY(DimenUtils.getTranslucentStatusBarHeight(this));
            this.getCurrentWebView().setTranslationY(DimenUtils.getToolbarAndStatusBarHeight(this));
        }
    }

    public void showHelpPage() {
        getCurrentWebView().loadUrl("file:///android_asset/help.html");
    }

    public void sendContactEmail() {
        Intent intent = new Intent(Intent.ACTION_SEND);
        intent.setType("plain/text");
        intent.putExtra(Intent.EXTRA_EMAIL, new String[] { contactEmailAddress });
        intent.putExtra(Intent.EXTRA_SUBJECT,
                "Feedback in " + LanguageUtils.getCurrentLocale(this).getDisplayLanguage());
        startActivity(Intent.createChooser(intent, ""));
    }

    @Override
    public void openExternalUrl(Intent intent) {
        if (intent.resolveActivity(getPackageManager()) != null) {
            startActivity(intent);
        } else {
            String error = getString(R.string.no_reader_application_installed);
            Toast.makeText(this, error, Toast.LENGTH_LONG).show();
        }
    }

    public boolean openZimFile(File file, boolean clearHistory) {
        if (file.canRead() || Build.VERSION.SDK_INT < 19
                || (BuildConfig.IS_CUSTOM_APP && Build.VERSION.SDK_INT != 23)) {
            if (file.exists()) {
                if (ZimContentProvider.setZimFile(file.getAbsolutePath()) != null) {

                    if (clearHistory) {
                        requestClearHistoryAfterLoad = true;
                    }
                    if (menu != null) {
                        initAllMenuItems();
                    } else {
                        // Menu may not be initialized yet. In this case
                        // signal to menu create to show
                        requestInitAllMenuItems = true;
                    }

                    //Bookmarks
                    bookmarks = new ArrayList<>();
                    bookmarksDao = new BookmarksDao(KiwixDatabase.getInstance(this));
                    bookmarks = bookmarksDao.getBookmarks(ZimContentProvider.getId(), ZimContentProvider.getName());

                    openMainPage();
                    refreshBookmarks();
                    return true;
                } else {
                    Toast.makeText(this, getResources().getString(R.string.error_fileinvalid), Toast.LENGTH_LONG)
                            .show();
                    showHelpPage();
                }
            } else {
                Log.e(TAG_KIWIX, "ZIM file doesn't exist at " + file.getAbsolutePath());

                Toast.makeText(this, getResources().getString(R.string.error_filenotfound), Toast.LENGTH_LONG)
                        .show();
                showHelpPage();
            }
            return false;
        } else {
            this.file = file;
            ActivityCompat.requestPermissions(this, new String[] { Manifest.permission.READ_EXTERNAL_STORAGE },
                    KiwixMobileActivity.REQUEST_STORAGE_PERMISSION);
            if (BuildConfig.IS_CUSTOM_APP && Build.VERSION.SDK_INT == Build.VERSION_CODES.M) {
                Toast.makeText(this, getResources().getString(R.string.request_storage_custom), Toast.LENGTH_LONG)
                        .show();
            } else {
                Toast.makeText(this, getResources().getString(R.string.request_storage), Toast.LENGTH_LONG).show();
            }
            return false;
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        switch (requestCode) {
        case KiwixMobileActivity.REQUEST_STORAGE_PERMISSION: {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                finish();
                Intent newZimFile = new Intent(KiwixMobileActivity.this, KiwixMobileActivity.class);
                newZimFile.setData(Uri.fromFile(file));
                startActivity(newZimFile);
            } else {
                AlertDialog.Builder builder = new AlertDialog.Builder(this, dialogStyle());
                builder.setMessage(getResources().getString(R.string.reboot_message));
                AlertDialog dialog = builder.create();
                dialog.show();
                finish();
            }
        }
        }
    }

    // Workaround for popup bottom menu on older devices
    private void StyleMenuButtons(Menu m) {
        // Find each menu item and set its text colour
        for (int i = 0; i < m.size(); i++) {
            m.getItem(i).setTitle(createMenuItem(m.getItem(i).getTitle().toString()));
        }
    }

    // Create a correctly colored title for menu items
    private SpannableString createMenuItem(String title) {
        SpannableString s = new SpannableString(title);
        if (nightMode) {
            s.setSpan(new ForegroundColorSpan(Color.WHITE), 0, s.length(), 0);
        } else {
            s.setSpan(new ForegroundColorSpan(Color.BLACK), 0, s.length(), 0);
        }
        return s;
    }

    // Create a correctly colored title for menu items
    private SpannableString createMenuText(String title) {
        SpannableString s = new SpannableString(title);
        s.setSpan(new ForegroundColorSpan(Color.WHITE), 0, s.length(), 0);
        return s;
    }

    private void initAllMenuItems() {
        try {
            menu.findItem(R.id.menu_bookmarks).setVisible(true);
            menu.findItem(R.id.menu_fullscreen).setVisible(true);
            menu.findItem(R.id.menu_home).setVisible(true);
            menu.findItem(R.id.menu_randomarticle).setVisible(true);
            menu.findItem(R.id.menu_searchintext).setVisible(true);

            MenuItem searchItem = menu.findItem(R.id.menu_search);
            searchItem.setVisible(true);
            final String zimFile = ZimContentProvider.getZimFile();
            searchItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
                @Override
                public boolean onMenuItemClick(MenuItem item) {
                    Intent i = new Intent(KiwixMobileActivity.this, SearchActivity.class);
                    i.putExtra("zimFile", zimFile);
                    startActivityForResult(i, REQUEST_FILE_SEARCH);
                    overridePendingTransition(0, 0);
                    return true;
                }
            });

            toolbar.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent i = new Intent(KiwixMobileActivity.this, SearchActivity.class);
                    i.putExtra("zimFile", zimFile);
                    startActivityForResult(i, REQUEST_FILE_SEARCH);
                    overridePendingTransition(0, 0);
                }
            });
            toolbar.setNavigationOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (drawerLayout.isDrawerOpen(GravityCompat.END)) {
                        drawerLayout.closeDrawer(GravityCompat.END);
                    } else if (drawerLayout.isDrawerOpen(GravityCompat.START)) {
                        drawerLayout.closeDrawer(GravityCompat.START);
                    } else {
                        drawerLayout.openDrawer(GravityCompat.START);
                    }
                }
            });

            new Handler().post(new Runnable() {
                @Override
                public void run() {
                    ActionMenuItemView m = (ActionMenuItemView) findViewById(R.id.menu_bookmarks);
                    if (m == null) {
                        return;
                    }
                    findViewById(R.id.menu_bookmarks).setOnLongClickListener(view -> {
                        goToBookmarks();
                        return false;
                    });
                }
            });

            if (tts.isInitialized()) {
                menu.findItem(R.id.menu_read_aloud).setVisible(true);
                if (isSpeaking) {
                    menu.findItem(R.id.menu_read_aloud)
                            .setTitle(createMenuItem(getResources().getString(R.string.menu_read_aloud_stop)));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (event.getAction() == KeyEvent.ACTION_DOWN) {
            switch (keyCode) {
            case KeyEvent.KEYCODE_BACK:
                if (getCurrentWebView().canGoBack()) {
                    getCurrentWebView().goBack();
                } else {
                    finish();
                }
                if (compatCallback.mIsActive) {
                    compatCallback.finish();
                }
                return true;
            case KeyEvent.KEYCODE_MENU:
                openOptionsMenu();
                return true;
            }
        }
        return false;
    }

    public void toggleBookmark() {
        //Check maybe need refresh
        String article = getCurrentWebView().getUrl();
        boolean isBookmark = false;
        if (article != null && !bookmarks.contains(article)) {
            saveBookmark(article, getCurrentWebView().getTitle());
            isBookmark = true;
        } else if (article != null) {
            deleteBookmark(article);
            isBookmark = false;
        }
        popBookmarkSnackbar(isBookmark);
        supportInvalidateOptionsMenu();
    }

    private void popBookmarkSnackbar(boolean isBookmark) {
        if (isBookmark) {
            Snackbar bookmarkSnackbar = Snackbar
                    .make(snackbarLayout, getString(R.string.bookmark_added), Snackbar.LENGTH_LONG)
                    .setAction(getString(R.string.open), new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            goToBookmarks();
                        }
                    });
            bookmarkSnackbar.setActionTextColor(getResources().getColor(R.color.white));
            bookmarkSnackbar.show();
        } else {
            Snackbar bookmarkSnackbar = Snackbar.make(snackbarLayout, getString(R.string.bookmark_removed),
                    Snackbar.LENGTH_LONG);
            bookmarkSnackbar.show();
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        invalidateOptionsMenu();
        if (wasHideToolbar != isHideToolbar) {
            wasHideToolbar = isHideToolbar;

            List<KiwixWebView> newWebViews = new ArrayList<>();
            for (int i = 0; i < mWebViews.size(); i++) {
                KiwixWebView newView = getWebView(mWebViews.get(i).getUrl());
                newWebViews.add(i, newView);
            }
            mWebViews = newWebViews;
            selectTab(currentWebViewIndex);
        }
        if (refresh) {
            refresh = false;
            recreate();
        }
        if (menu != null) {
            refreshBookmarkSymbol(menu);
        }
        if (getResources().getConfiguration().orientation == ORIENTATION_LANDSCAPE) {
            if (menu != null) {
                menu.getItem(4).setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
            }
        } else {
            if (menu != null) {
                menu.getItem(4).setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
            }
        }

        if (settings.getBoolean(KiwixSettingsActivity.PREF_BOTTOM_TOOLBAR, false)) {
            pageBottomTabLayout.setVisibility(View.VISIBLE);
        } else {
            pageBottomTabLayout.setVisibility(View.GONE);
        }

        Intent intent = getIntent();
        if (intent.getAction() != null) {

            if (intent.getAction().equals(Intent.ACTION_PROCESS_TEXT)) {
                final String zimFile = ZimContentProvider.getZimFile();
                saveTabStates();
                Intent i = new Intent(KiwixMobileActivity.this, SearchActivity.class);
                i.putExtra("zimFile", zimFile);
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    i.putExtra(Intent.EXTRA_PROCESS_TEXT, intent.getStringExtra(Intent.EXTRA_PROCESS_TEXT));
                }
                intent.setAction("");
                startActivityForResult(i, REQUEST_FILE_SEARCH);
            } else if (intent.getAction().equals(KiwixSearchWidget.TEXT_CLICKED)) {
                intent.setAction("");
                goToSearch(false);
            } else if (intent.getAction().equals(KiwixSearchWidget.STAR_CLICKED)) {
                intent.setAction("");
                goToBookmarks();
            } else if (intent.getAction().equals(KiwixSearchWidget.MIC_CLICKED)) {
                intent.setAction("");
                goToSearch(true);
            }

        }
        updateWidgets(this);
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        boolean isWidgetSearch = intent.getBooleanExtra("isWidgetSearch", false);
        boolean isWidgetVoiceSearch = intent.getBooleanExtra("isWidgetVoice", false);
        boolean isWidgetStar = intent.getBooleanExtra("isWidgetStar", false);

        if (isWidgetStar && ZimContentProvider.getId() != null) {
            goToBookmarks();
        } else if (isWidgetSearch && ZimContentProvider.getId() != null) {
            goToSearch(false);
        } else if (isWidgetVoiceSearch && ZimContentProvider.getId() != null) {
            goToSearch(true);
        } else if (isWidgetStar || isWidgetSearch || isWidgetVoiceSearch) {
            manageZimFiles(0);
        }
    }

    private void refreshBookmarks() {
        if (bookmarks != null) {
            bookmarks.clear();
        }
        if (bookmarksDao != null) {
            bookmarks = bookmarksDao.getBookmarks(ZimContentProvider.getId(), ZimContentProvider.getName());
        }
    }

    // TODO: change saving bookbark by zim name not id
    private void saveBookmark(String articleUrl, String articleTitle) {
        bookmarksDao.saveBookmark(articleUrl, articleTitle, ZimContentProvider.getId(),
                ZimContentProvider.getName());
        refreshBookmarks();
    }

    private void deleteBookmark(String article) {
        bookmarksDao.deleteBookmark(article, ZimContentProvider.getId(), ZimContentProvider.getName());
        refreshBookmarks();
    }

    public boolean openArticleFromBookmarkTitle(String bookmarkTitle) {
        return openArticle(ZimContentProvider.getPageUrlFromTitle(bookmarkTitle));
    }

    private void contentsDrawerHint() {
        drawerLayout.postDelayed(() -> drawerLayout.openDrawer(GravityCompat.END), 500);

        AlertDialog.Builder builder = new AlertDialog.Builder(this, dialogStyle());
        builder.setMessage(getString(R.string.hint_contents_drawer_message))
                .setPositiveButton(getString(R.string.got_it), (dialog, id) -> {
                }).setTitle(getString(R.string.did_you_know)).setIcon(R.drawable.icon_question);
        AlertDialog alert = builder.create();
        alert.show();
    }

    private boolean openArticle(String articleUrl) {
        if (articleUrl != null) {
            getCurrentWebView().loadUrl(Uri.parse(ZimContentProvider.CONTENT_URI + articleUrl).toString());
        }
        return true;
    }

    public boolean openRandomArticle() {
        String articleUrl = ZimContentProvider.getRandomArticleUrl();
        Log.d(TAG_KIWIX, "openRandomArticle: " + articleUrl);
        return openArticle(articleUrl);
    }

    public boolean openMainPage() {
        String articleUrl = ZimContentProvider.getMainPage();
        return openArticle(articleUrl);
    }

    public void readAloud() {
        tts.readAloud(getCurrentWebView());
    }

    public static void updateWidgets(Context context) {
        Intent intent = new Intent(context.getApplicationContext(), KiwixSearchWidget.class);
        intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
        // Use an array and EXTRA_APPWIDGET_IDS instead of AppWidgetManager.EXTRA_APPWIDGET_ID,
        // since it seems the onUpdate() is only fired on that:
        AppWidgetManager widgetManager = AppWidgetManager.getInstance(context);
        int[] ids = widgetManager.getAppWidgetIds(new ComponentName(context, KiwixSearchWidget.class));

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            widgetManager.notifyAppWidgetViewDataChanged(ids, android.R.id.list);

            intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids);
            context.sendBroadcast(intent);
        }
    }

    private void setUpWebView() {

        getCurrentWebView().getSettings().setJavaScriptEnabled(true);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            WebView.setWebContentsDebuggingEnabled(true);
        }

        // webView.getSettings().setLoadsImagesAutomatically(false);
        // Does not make much sense to cache data from zim files.(Not clear whether
        // this actually has any effect)
        getCurrentWebView().getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);

        // Should basically resemble the behavior when setWebClient not done
        // (i.p. internal urls load in webview, external urls in browser)
        // as currently no custom setWebViewClient required it is commented
        // However, it must notify the bookmark system when a page is finished loading
        // so that it can refresh the menu.

        backToTopButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                KiwixMobileActivity.this.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        getCurrentWebView().pageUp(true);
                    }
                });
            }
        });
        tts.initWebView(getCurrentWebView());
    }

    private void setUpExitFullscreenButton() {

        exitFullscreenButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                closeFullScreen();
            }
        });
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        toggleActionItemsConfig();
    }

    void toggleActionItemsConfig() {
        if (menu != null) {
            MenuItem random = menu.findItem(R.id.menu_randomarticle);
            MenuItem home = menu.findItem(R.id.menu_home);
            if (getResources().getConfiguration().orientation == ORIENTATION_LANDSCAPE) {
                random.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
                home.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
            } else {
                random.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
                home.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
            }
        }
    }

    public void searchForTitle(String title) {
        String articleUrl;

        if (title.startsWith("A/")) {
            articleUrl = title;
        } else {
            articleUrl = ZimContentProvider.getPageUrlFromTitle(title);
        }
        openArticle(articleUrl);
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {

        Log.i(TAG_KIWIX, "Intent data: " + data);

        switch (requestCode) {
        case REQUEST_FILE_SELECT:
            if (resultCode == RESULT_OK) {
                // The URI of the selected file
                final Uri uri = data.getData();
                File file = null;
                if (uri != null) {
                    String path = uri.getPath();
                    if (path != null) {
                        file = new File(path);
                    }
                }
                if (file == null) {
                    return;
                }

                finish();
                Intent zimFile = new Intent(KiwixMobileActivity.this, KiwixMobileActivity.class);
                zimFile.setData(uri);
                startActivity(zimFile);
            }
            break;
        case REQUEST_FILE_SEARCH:
            if (resultCode == RESULT_OK) {
                String title = data.getStringExtra(TAG_FILE_SEARCHED).replace("<b>", "").replace("</b>", "");
                searchForTitle(title);
            }
            break;
        case REQUEST_PREFERENCES:
            if (resultCode == KiwixSettingsActivity.RESULT_RESTART) {
                finish();
                startActivity(new Intent(KiwixMobileActivity.this, KiwixMobileActivity.class));
            }
            if (resultCode == KiwixSettingsActivity.RESULT_HISTORY_CLEARED) {
                mWebViews.clear();
                newTab();
                tabDrawerAdapter.notifyDataSetChanged();
            }
            loadPrefs();
            break;

        case BOOKMARK_CHOSEN_REQUEST:
            if (resultCode == RESULT_OK) {
                boolean itemClicked = data.getBooleanExtra("bookmarkClicked", false);
                if (ZimContentProvider.getId() == null)
                    return;

                //Bookmarks
                bookmarksDao = new BookmarksDao(KiwixDatabase.getInstance(this));
                bookmarks = bookmarksDao.getBookmarks(ZimContentProvider.getId(), ZimContentProvider.getName());

                if (itemClicked) {
                    String bookmarkChosen;
                    if (data.getStringExtra("choseXURL") != null) {
                        bookmarkChosen = data.getStringExtra("choseXURL");
                        newTab();
                        getCurrentWebView().loadUrl(bookmarkChosen);
                    } else {
                        newTab();
                        bookmarkChosen = data.getStringExtra("choseXTitle");
                        openArticleFromBookmarkTitle(bookmarkChosen);
                    }
                }
                if (menu != null) {
                    refreshBookmarkSymbol(menu);
                }
            }
            break;
        default:
            break;
        }

        super.onActivityResult(requestCode, resultCode, data);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.menu_main, menu);
        this.menu = menu;
        StyleMenuButtons(menu);
        if (BuildConfig.IS_CUSTOM_APP) {
            menu.findItem(R.id.menu_help).setVisible(false);
        }

        if (requestInitAllMenuItems) {
            initAllMenuItems();
        }
        if (isFullscreenOpened) {
            openFullScreen();
        }
        return true;
    }

    // This method refreshes the menu for the bookmark system.
    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        super.onPrepareOptionsMenu(menu);
        toggleActionItemsConfig();
        refreshBookmarkSymbol(menu);
        refreshNavigationButtons();

        if (getCurrentWebView().getUrl() == null
                || getCurrentWebView().getUrl().equals("file:///android_asset/help.html")) {
            menu.findItem(R.id.menu_read_aloud).setVisible(false);
        } else {
            menu.findItem(R.id.menu_read_aloud).setVisible(true);
        }

        return true;
    }

    public void refreshBookmarkSymbol(Menu menu) { // Checks if current webview is in bookmarks array
        if (bookmarks == null || bookmarks.size() == 0) {
            bookmarksDao = new BookmarksDao(KiwixDatabase.getInstance(this));
            bookmarks = bookmarksDao.getBookmarks(ZimContentProvider.getId(), ZimContentProvider.getName());
        }
        if (menu.findItem(R.id.menu_bookmarks) != null && getCurrentWebView().getUrl() != null
                && ZimContentProvider.getId() != null
                && !getCurrentWebView().getUrl().equals("file:///android_asset/help.html")) {
            menu.findItem(R.id.menu_bookmarks).setEnabled(true)
                    .setIcon(bookmarks.contains(getCurrentWebView().getUrl()) ? R.drawable.action_bookmark_active
                            : R.drawable.action_bookmark)
                    .getIcon().setAlpha(255);
        } else {
            menu.findItem(R.id.menu_bookmarks).setEnabled(false).setIcon(R.drawable.action_bookmark).getIcon()
                    .setAlpha(130);
        }
    }

    public void refreshNavigationButtons() {
        toggleImageViewGrayFilter(tabBackButton, getCurrentWebView().canGoBack());
        toggleImageViewGrayFilter(tabForwardButton, getCurrentWebView().canGoForward());
        tabBackButtonContainer.setEnabled(getCurrentWebView().canGoBack());
        tabForwardButtonContainer.setEnabled(getCurrentWebView().canGoForward());
    }

    public void toggleImageViewGrayFilter(ImageView image, boolean state) {
        Drawable originalIcon = image.getDrawable();
        Drawable res = originalIcon.mutate();
        if (state) {
            res.clearColorFilter();
        } else {
            res.setColorFilter(Color.GRAY, PorterDuff.Mode.SRC_IN);
        }
        image.setImageDrawable(res);
    }

    public void loadPrefs() {

        SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
        nightMode = KiwixSettingsActivity.nightMode(sharedPreferences);
        isBackToTopEnabled = sharedPreferences.getBoolean(PREF_BACK_TO_TOP, false);
        isHideToolbar = sharedPreferences.getBoolean(PREF_HIDE_TOOLBAR, false);
        isFullscreenOpened = sharedPreferences.getBoolean(PREF_FULLSCREEN, false);
        boolean isZoomEnabled = sharedPreferences.getBoolean(PREF_ZOOM_ENABLED, false);
        isOpenNewTabInBackground = sharedPreferences.getBoolean(PREF_NEW_TAB_BACKGROUND, false);

        if (isZoomEnabled) {
            int zoomScale = (int) sharedPreferences.getFloat(PREF_ZOOM, 100.0f);
            getCurrentWebView().setInitialScale(zoomScale);
        } else {
            getCurrentWebView().setInitialScale(0);
        }

        if (!isBackToTopEnabled) {
            backToTopButton.setVisibility(View.INVISIBLE);
        }

        if (isFullscreenOpened) {
            openFullScreen();
        }

        // Night mode status
        Log.d(TAG_KIWIX, "nightMode value (" + nightMode + ")");
        if (nightMode) {
            getCurrentWebView().toggleNightMode();
        } else {
            getCurrentWebView().deactivateNightMode();
        }
    }

    public void manageZimFiles(int tab) {
        refreshBookmarks();
        final Intent target = new Intent(this, ZimManageActivity.class);
        target.setAction(Intent.ACTION_GET_CONTENT);
        // The MIME data type filter
        target.setType("//");
        target.putExtra(ZimManageActivity.TAB_EXTRA, tab);
        // Only return URIs that can be opened with ContentResolver
        target.addCategory(Intent.CATEGORY_OPENABLE);
        // Force use of our file selection component.
        // (Note may make sense to just define a custom intent instead)

        startActivityForResult(target, REQUEST_FILE_SELECT);
    }

    public void selectSettings() {
        final String zimFile = ZimContentProvider.getZimFile();
        Intent i = new Intent(this, KiwixSettingsActivity.class);
        i.putExtra("zim_file", zimFile);
        startActivityForResult(i, REQUEST_PREFERENCES);
    }

    public void saveTabStates() {
        SharedPreferences settings = getSharedPreferences(PREF_KIWIX_MOBILE, 0);
        SharedPreferences.Editor editor = settings.edit();

        JSONArray urls = new JSONArray();
        JSONArray positions = new JSONArray();
        for (KiwixWebView view : mWebViews) {
            if (view.getUrl() == null)
                continue;
            urls.put(view.getUrl());
            positions.put(view.getScrollY());
        }

        editor.putString(TAG_CURRENT_FILE, ZimContentProvider.getZimFile());
        editor.putString(TAG_CURRENT_ARTICLES, urls.toString());
        editor.putString(TAG_CURRENT_POSITIONS, positions.toString());
        editor.putInt(TAG_CURRENT_TAB, currentWebViewIndex);

        editor.apply();
    }

    public void restoreTabStates() {
        SharedPreferences settings = getSharedPreferences(PREF_KIWIX_MOBILE, 0);
        String zimFile = settings.getString(TAG_CURRENT_FILE, null);
        String zimArticles = settings.getString(TAG_CURRENT_ARTICLES, null);
        String zimPositions = settings.getString(TAG_CURRENT_POSITIONS, null);

        int currentTab = settings.getInt(TAG_CURRENT_TAB, 0);

        openZimFile(new File(zimFile), false);
        try {
            JSONArray urls = new JSONArray(zimArticles);
            JSONArray positions = new JSONArray(zimPositions);
            int i = 0;
            getCurrentWebView().loadUrl(urls.getString(i));
            getCurrentWebView().setScrollY(positions.getInt(i));
            i++;
            for (; i < urls.length(); i++) {
                newTab(urls.getString(i));
                getCurrentWebView().setScrollY(positions.getInt(i));
            }
            selectTab(currentTab);
        } catch (Exception e) {
            Log.d(TAG_KIWIX, " Kiwix sharedpreferences corrupted");
        }
    }

    private void manageExternalLaunchAndRestoringViewState() {

        if (getIntent().getData() != null) {
            String filePath = FileUtils.getLocalFilePathByUri(getApplicationContext(), getIntent().getData());

            if (filePath == null || !new File(filePath).exists()) {
                Toast.makeText(KiwixMobileActivity.this, getString(R.string.error_filenotfound), Toast.LENGTH_LONG)
                        .show();
                return;
            }

            Log.d(TAG_KIWIX, " Kiwix started from a filemanager. Intent filePath: " + filePath
                    + " -> open this zimfile and load menu_main page");
            openZimFile(new File(filePath), false);
        } else {
            SharedPreferences settings = getSharedPreferences(PREF_KIWIX_MOBILE, 0);
            String zimFile = settings.getString(TAG_CURRENT_FILE, null);
            if (zimFile != null && new File(zimFile).exists()) {
                Log.d(TAG_KIWIX,
                        " Kiwix normal start, zimFile loaded last time -> Open last used zimFile " + zimFile);
                restoreTabStates();
                // Alternative would be to restore webView state. But more effort to implement, and actually
                // fits better normal android behavior if after closing app ("back" button) state is not maintained.
            } else {

                if (BuildConfig.IS_CUSTOM_APP) {
                    Log.d(TAG_KIWIX, "Kiwix Custom App starting for the first time. Check Companion ZIM.");

                    String currentLocaleCode = Locale.getDefault().toString();
                    // Custom App recommends to start off a specific language
                    if (BuildConfig.ENFORCED_LANG.length() > 0
                            && !BuildConfig.ENFORCED_LANG.equals(currentLocaleCode)) {

                        // change the locale machinery
                        LanguageUtils.handleLocaleChange(this, BuildConfig.ENFORCED_LANG);

                        // save new locale into preferences for next startup
                        SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
                        SharedPreferences.Editor editor = sharedPreferences.edit();
                        editor.putString("pref_language_chooser", BuildConfig.ENFORCED_LANG);
                        editor.apply();

                        // restart activity for new locale to take effect
                        this.setResult(1236);
                        this.finish();
                        this.startActivity(new Intent(this, this.getClass()));
                    }

                    String filePath = "";
                    if (BuildConfig.HAS_EMBEDDED_ZIM) {
                        String appPath = getPackageResourcePath();
                        File libDir = new File(appPath.substring(0, appPath.lastIndexOf("/")) + "/lib/");
                        if (libDir.exists() && libDir.listFiles().length > 0) {
                            filePath = libDir.listFiles()[0].getPath() + "/" + BuildConfig.ZIM_FILE_NAME;
                        }
                        if (filePath.isEmpty() || !new File(filePath).exists()) {
                            filePath = String.format("/data/data/%s/lib/%s", BuildConfig.APPLICATION_ID,
                                    BuildConfig.ZIM_FILE_NAME);
                        }
                    } else {
                        String fileName = FileUtils.getExpansionAPKFileName(true);
                        filePath = FileUtils.generateSaveFileName(fileName);
                    }

                    if (!FileUtils.doesFileExist(filePath, BuildConfig.ZIM_FILE_SIZE, false)) {

                        AlertDialog.Builder zimFileMissingBuilder = new AlertDialog.Builder(this, dialogStyle());
                        zimFileMissingBuilder.setTitle(R.string.app_name);
                        zimFileMissingBuilder.setMessage(R.string.customapp_missing_content);
                        zimFileMissingBuilder.setIcon(R.mipmap.kiwix_icon);
                        final Activity activity = this;
                        zimFileMissingBuilder.setPositiveButton(getString(R.string.go_to_play_store),
                                new DialogInterface.OnClickListener() {
                                    public void onClick(DialogInterface dialog, int which) {
                                        String market_uri = "market://details?id=" + BuildConfig.APPLICATION_ID;
                                        Intent intent = new Intent(Intent.ACTION_VIEW);
                                        intent.setData(Uri.parse(market_uri));
                                        startActivity(intent);
                                        activity.finish();
                                    }
                                });
                        zimFileMissingBuilder.setCancelable(false);
                        AlertDialog zimFileMissingDialog = zimFileMissingBuilder.create();
                        zimFileMissingDialog.show();
                    } else {
                        openZimFile(new File(filePath), true);
                    }
                } else {
                    Log.d(TAG_KIWIX, " Kiwix normal start, no zimFile loaded last time  -> display help page");
                    showHelpPage();
                }
            }
        }
    }

    @Override
    public void onPause() {
        super.onPause();

        saveTabStates();
        refreshBookmarks();

        Log.d(TAG_KIWIX, "onPause Save currentzimfile to preferences:" + ZimContentProvider.getZimFile());
    }

    @Override
    public void webViewUrlLoading() {
        if (isFirstRun && !BuildConfig.DEBUG) {
            contentsDrawerHint();
            SharedPreferences.Editor editor = settings.edit();
            editor.putBoolean("isFirstRun", false); // It is no longer the first run
            isFirstRun = false;
            editor.apply();
        }
    }

    @Override
    public void webViewUrlFinishedLoading() {
        updateTableOfContents();
        tabDrawerAdapter.notifyDataSetChanged();

        if (menu != null)
            refreshBookmarkSymbol(menu);
    }

    @Override
    public void webViewFailedLoading(String url) {
        String error = String.format(getString(R.string.error_articleurlnotfound), url);
        Toast.makeText(this, error, Toast.LENGTH_SHORT).show();
    }

    @Override
    public void webViewProgressChanged(int progress) {
        progressBar.setProgress(progress);
        if (progress == 100) {
            Log.d(KiwixMobileActivity.TAG_KIWIX, "Loading article finished.");
            if (requestClearHistoryAfterLoad) {
                Log.d(KiwixMobileActivity.TAG_KIWIX,
                        "Loading article finished and requestClearHistoryAfterLoad -> clearHistory");
                getCurrentWebView().clearHistory();
                requestClearHistoryAfterLoad = false;
            }

            Log.d(KiwixMobileActivity.TAG_KIWIX, "Loaded URL: " + getCurrentWebView().getUrl());
        }
    }

    @Override
    public void webViewTitleUpdated(String title) {
        tabDrawerAdapter.notifyDataSetChanged();
    }

    @Override
    public void webViewPageChanged(int page, int maxPages) {
        if (isBackToTopEnabled) {
            if (getCurrentWebView().getScrollY() > 200) {
                if (backToTopButton.getVisibility() == View.INVISIBLE && TTSControls.getVisibility() == View.GONE) {
                    backToTopButton.setText(R.string.button_backtotop);
                    backToTopButton.setVisibility(View.VISIBLE);

                    backToTopButton.startAnimation(
                            AnimationUtils.loadAnimation(KiwixMobileActivity.this, android.R.anim.fade_in));
                    backToTopButton.setVisibility(View.INVISIBLE);
                    Animation fadeAnimation = AnimationUtils.loadAnimation(KiwixMobileActivity.this,
                            android.R.anim.fade_out);
                    fadeAnimation.setStartOffset(1200);
                    backToTopButton.startAnimation(fadeAnimation);
                }
            } else {
                if (backToTopButton.getVisibility() == View.VISIBLE) {
                    backToTopButton.setVisibility(View.INVISIBLE);

                    backToTopButton.clearAnimation();
                    backToTopButton.startAnimation(
                            AnimationUtils.loadAnimation(KiwixMobileActivity.this, android.R.anim.fade_out));
                } else {
                    backToTopButton.clearAnimation();
                }
            }
        }
    }

    @Override
    public void webViewLongClick(final String url) {
        boolean handleEvent = false;
        if (url.startsWith(ZimContentProvider.CONTENT_URI.toString())) {
            // This is my web site, so do not override; let my WebView load the page
            handleEvent = true;
        } else if (url.startsWith("file://")) {
            // To handle help page (loaded from resources)
            handleEvent = true;
        } else if (url.startsWith(ZimContentProvider.UI_URI.toString())) {
            handleEvent = true;
        }

        if (handleEvent) {
            AlertDialog.Builder builder = new AlertDialog.Builder(KiwixMobileActivity.this, dialogStyle());

            builder.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {
                    if (isOpenNewTabInBackground) {
                        newTabInBackground(url);
                        Snackbar snackbar = Snackbar
                                .make(snackbarLayout, getString(R.string.new_tab_snackbar), Snackbar.LENGTH_LONG)
                                .setAction(getString(R.string.open), v -> {
                                    if (mWebViews.size() > 1)
                                        selectTab(mWebViews.size() - 1);
                                });
                        snackbar.setActionTextColor(getResources().getColor(R.color.white));
                        snackbar.show();
                    } else {
                        newTab(url);
                    }
                }
            });
            builder.setNegativeButton(android.R.string.no, null);
            builder.setMessage(getString(R.string.open_in_new_tab));
            AlertDialog dialog = builder.create();
            dialog.show();
        }
    }

}