com.nttec.everychan.ui.MainActivity.java Source code

Java tutorial

Introduction

Here is the source code for com.nttec.everychan.ui.MainActivity.java

Source

/*
 * Everychan Android (Meta Imageboard Client)
 * Copyright (C) 2014-2016  miku-nyan <https://github.com/miku-nyan>
 *     
 * 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
 * (at your option) 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, see <http://www.gnu.org/licenses/>.
 */

package com.nttec.everychan.ui;

import java.io.Serializable;

import com.nttec.everychan.R;
import com.nttec.everychan.api.models.UrlPageModel;
import com.nttec.everychan.common.Async;
import com.nttec.everychan.common.Logger;
import com.nttec.everychan.common.MainApplication;
import com.nttec.everychan.http.client.ExtendedTrustManager;
import com.nttec.everychan.lib.appcompat_v7_actionbartoogle.wrappers.ActionBarDrawerToogleCompat;
import com.nttec.everychan.lib.appcompat_v7_actionbartoogle.wrappers.ActionBarDrawerToogleV4;
import com.nttec.everychan.lib.appcompat_v7_actionbartoogle.wrappers.ActionBarDrawerToogleV7;
import com.nttec.everychan.lib.dslv.DragSortController;
import com.nttec.everychan.lib.dslv.DragSortListView;
import com.nttec.everychan.lib.dslv.DragSortListView.DropListener;
import com.nttec.everychan.ui.posting.PostFormActivity;
import com.nttec.everychan.ui.posting.PostingService;
import com.nttec.everychan.ui.presentation.BoardFragment;
import com.nttec.everychan.ui.presentation.FlowTextHelper;
import com.nttec.everychan.ui.settings.PreferencesActivity;
import com.nttec.everychan.ui.settings.ApplicationSettings.StaticSettingsContainer;
import com.nttec.everychan.ui.tabs.LocalHandler;
import com.nttec.everychan.ui.tabs.TabModel;
import com.nttec.everychan.ui.tabs.TabsAdapter;
import com.nttec.everychan.ui.tabs.TabsState;
import com.nttec.everychan.ui.tabs.TabsTrackerService;
import com.nttec.everychan.ui.tabs.UrlHandler;
import com.nttec.everychan.ui.theme.GenericThemeEntry;
import com.nttec.everychan.ui.theme.ThemeUtils;
import com.nttec.everychan.ui.tabs.TabsAdapter.TabSelectListener;
import android.annotation.SuppressLint;
import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.graphics.Point;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.widget.DrawerLayout;
import android.util.TypedValue;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.URLUtil;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.Toast;

public class MainActivity extends FragmentActivity {
    private static final String TAG = "MainActivity";

    @SuppressLint("InlinedApi")
    private static final int DRAWER_GRAVITY = Gravity.START;

    private NotificationManager notificationManager;
    private BroadcastReceiver broadcastReceiver;
    private IntentFilter intentFilter;

    public TabsAdapter tabsAdapter = null;
    public StaticSettingsContainer settings;
    private GenericThemeEntry theme;
    private int autohideRulesHash;
    private float rootViewWeight = 0;
    private boolean tabsPanelRight;
    private boolean openSpoilers;
    private boolean highlightSubscriptions;
    private boolean swipeToHideThread;
    private boolean isHorizontalOrientation;
    private boolean isPaused = false;
    private boolean isDestroyed = false;

    private DrawerLayout drawerLayout;
    private ActionBarDrawerToogleCompat drawerToggle;

    private HiddenTabsSection hiddenTabsSection = null;

    private void initDrawer() {
        drawerLayout = (DrawerLayout) findViewById(R.id.drawer);
        if (drawerLayout == null || Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB)
            return;

        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
            int drawerResId = ThemeUtils.getThemeResId(getTheme(), R.attr.iconDrawer);
            drawerToggle = new ActionBarDrawerToogleV4(this, drawerLayout, drawerResId, R.string.drawer_open,
                    R.string.drawer_close) {
                @SuppressWarnings("deprecation")
                @Override
                public void onDrawerClosed(View drawerView) {
                    super.onDrawerClosed(drawerView);
                    if (tabsAdapter != null)
                        tabsAdapter.setDraggingItem(-1);
                }

                @SuppressWarnings("deprecation")
                @Override
                public void onDrawerSlide(View drawerView, float slideOffset) {
                    super.onDrawerSlide(drawerView, slideOffset);
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
                        CompatibilityImpl.showActionBar(MainActivity.this);
                }
            };
        } else {
            drawerToggle = new ActionBarDrawerToogleV7(this, drawerLayout, R.string.drawer_open,
                    R.string.drawer_close) {
                @Override
                public void onDrawerClosed(View drawerView) {
                    super.onDrawerClosed(drawerView);
                    if (tabsAdapter != null)
                        tabsAdapter.setDraggingItem(-1);
                }

                @Override
                public void onDrawerSlide(View drawerView, float slideOffset) {
                    super.onDrawerSlide(drawerView, slideOffset);
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
                        CompatibilityImpl.showActionBar(MainActivity.this);
                }
            };
        }
        drawerLayout.setDrawerListener(drawerToggle);

        drawerLayout.setDrawerShadow(R.drawable.drawer_shadow, DRAWER_GRAVITY);
        CompatibilityImpl.activeActionBar(this);
    }

    private void openDrawer() {
        if (drawerLayout != null)
            drawerLayout.openDrawer(DRAWER_GRAVITY);
    }

    private void closeDrawer() {
        if (drawerLayout != null)
            drawerLayout.closeDrawers();
    }

    public void setDrawerLock(int lockMode) {
        if (drawerLayout != null)
            drawerLayout.setDrawerLockMode(lockMode, DRAWER_GRAVITY);
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        if (drawerToggle != null) {
            drawerToggle.onConfigurationChanged(newConfig);
        }
        if (!isPaused)
            handleOrientationChange(newConfig);
    }

    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        if (drawerToggle != null) {
            drawerToggle.syncState();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        if (!MainApplication.getInstance().settings.showSidePanel() && Build.VERSION.SDK_INT < 11) {
            menu.add(Menu.NONE, R.id.menu_open_close_drawer, Menu.FIRST, R.string.menu_open_drawer)
                    .setIcon(R.drawable.ic_menu_windows);
        }
        if (tabsAdapter != null && tabsAdapter.getSelectedItem() >= 0) {
            TabModel tab = tabsAdapter.getItem(tabsAdapter.getSelectedItem());
            if (canFavorite(tab)) {
                menu.add(Menu.NONE, R.id.menu_favorites, 201, R.string.menu_add_favorites)
                        .setIcon(R.drawable.ic_menu_add_bookmark);
            }
            if (tab.webUrl != null) {
                menu.add(Menu.NONE, R.id.menu_open_browser, 202, R.string.menu_open_browser)
                        .setIcon(R.drawable.ic_menu_browser);
            }
        }
        menu.add(Menu.NONE, R.id.menu_settings, 203, R.string.menu_preferences)
                .setIcon(android.R.drawable.ic_menu_preferences);
        Menu subMenu = menu.addSubMenu(Menu.NONE, R.id.menu_sub_settings, 203, R.string.menu_preferences)
                .setIcon(android.R.drawable.ic_menu_preferences);
        subMenu.add(Menu.NONE, R.id.menu_sub_settings_suspend, 1, R.string.menu_sub_preferences_suspend);
        subMenu.add(Menu.NONE, R.id.menu_sub_settings_autoupdate, 2, R.string.menu_sub_preferences_autoupdate)
                .setCheckable(true);
        subMenu.add(Menu.NONE, R.id.menu_sub_settings_maskpictures, 3, R.string.menu_sub_preferences_maskpictures)
                .setCheckable(true);
        subMenu.add(Menu.NONE, R.id.menu_sub_settings_all, 4, R.string.menu_sub_preferences_all);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        MenuItem drawerMenuItem = menu.findItem(R.id.menu_open_close_drawer);
        if (drawerMenuItem != null) {
            drawerMenuItem.setTitle(drawerLayout.isDrawerOpen(DRAWER_GRAVITY) ? R.string.menu_close_drawer
                    : R.string.menu_open_drawer);
        }
        MenuItem favoritesMenuItem = menu.findItem(R.id.menu_favorites);
        if (favoritesMenuItem != null && tabsAdapter != null && tabsAdapter.getSelectedItem() >= 0) {
            TabModel tab = tabsAdapter.getItem(tabsAdapter.getSelectedItem());
            favoritesMenuItem
                    .setTitle(isFavorite(tab) ? R.string.menu_remove_favorites : R.string.menu_add_favorites);
        }
        MenuItem preferencesMenuItem = menu.findItem(R.id.menu_settings);
        MenuItem preferencesSubMenuItem = menu.findItem(R.id.menu_sub_settings);
        try {
            if (MainApplication.getInstance().settings.preferencesSubmenu()) {
                preferencesSubMenuItem.setVisible(true);
                preferencesMenuItem.setVisible(false);
                Menu subMenu = preferencesSubMenuItem.getSubMenu();
                subMenu.findItem(R.id.menu_sub_settings_suspend)
                        .setVisible(MainApplication.getInstance().settings.isAutoupdateEnabled());
                subMenu.findItem(R.id.menu_sub_settings_autoupdate)
                        .setChecked(MainApplication.getInstance().settings.isAutoupdateEnabled());
                subMenu.findItem(R.id.menu_sub_settings_maskpictures)
                        .setChecked(MainApplication.getInstance().settings.maskPictures());
            } else {
                preferencesMenuItem.setVisible(true);
                preferencesSubMenuItem.setVisible(false);
            }
        } catch (Exception e) {
            Logger.e(TAG, e);
        }
        return super.onPrepareOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (drawerToggle != null && drawerToggle.onOptionsItemSelected(item)) {
            return true;
        }
        int id = item.getItemId();
        switch (id) {
        case R.id.menu_open_browser:
            if (tabsAdapter != null && tabsAdapter.getSelectedItem() >= 0
                    && tabsAdapter.getItem(tabsAdapter.getSelectedItem()).webUrl != null) {
                UrlHandler.launchExternalBrowser(this, tabsAdapter.getItem(tabsAdapter.getSelectedItem()).webUrl);
            }
            return true;
        case R.id.menu_favorites:
            if (tabsAdapter != null && tabsAdapter.getSelectedItem() >= 0
                    && tabsAdapter.getItem(tabsAdapter.getSelectedItem()).webUrl != null) {
                handleFavorite(tabsAdapter.getItem(tabsAdapter.getSelectedItem()));
            }
            return true;
        case R.id.menu_settings:
        case R.id.menu_sub_settings_all:
            Intent preferencesIntent = new Intent(this, PreferencesActivity.class);
            this.startActivity(preferencesIntent);
            return true;
        case R.id.menu_sub_settings_suspend:
            Toast.makeText(this, R.string.notification_suspend, Toast.LENGTH_LONG).show();
            if (TabsTrackerService.isRunning())
                stopService(new Intent(MainActivity.this, TabsTrackerService.class));
            finish();
            return true;
        case R.id.menu_sub_settings_autoupdate:
            MainApplication.getInstance().settings
                    .setAutoupdateEnabled(!MainApplication.getInstance().settings.isAutoupdateEnabled());
            if (TabsTrackerService.isRunning())
                stopService(new Intent(this, TabsTrackerService.class));
            if (MainApplication.getInstance().settings.isAutoupdateEnabled())
                startService(new Intent(this, TabsTrackerService.class));
            return true;
        case R.id.menu_sub_settings_maskpictures:
            MainApplication.getInstance().settings
                    .setMaskPictures(!MainApplication.getInstance().settings.maskPictures());
            MainApplication.getInstance().settings.updateStaticSettings(settings);
            reloadCurrentBoardFragment();
            return true;
        case R.id.menu_open_close_drawer:
            if (drawerLayout.isDrawerOpen(DRAWER_GRAVITY)) {
                closeDrawer();
            } else {
                openDrawer();
            }
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
        super.onCreateContextMenu(menu, v, menuInfo);
        if (v.getId() == R.id.sidebar_tabs_list) {
            AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
            TabModel model = tabsAdapter.getItem(info.position);
            if (tabsAdapter.getCount() > 1) {
                menu.add(Menu.NONE, R.id.context_menu_move, 1, R.string.context_menu_move);
            }
            if (model.webUrl != null) {
                menu.add(Menu.NONE, R.id.context_menu_copy_url, 2, R.string.context_menu_copy_url);
                menu.add(Menu.NONE, R.id.context_menu_share_link, 3, R.string.context_menu_share_link);
            }
            if (canFavorite(model)) {
                menu.add(Menu.NONE, R.id.context_menu_favorites, 4,
                        isFavorite(model) ? R.string.context_menu_remove_favorites
                                : R.string.context_menu_add_favorites);
            }
            if (model.type == TabModel.TYPE_NORMAL && model.pageModel != null
                    && model.pageModel.type == UrlPageModel.TYPE_THREADPAGE) {
                boolean backgroundAutoupdateEnabled = MainApplication.getInstance().settings.isAutoupdateEnabled()
                        && MainApplication.getInstance().settings.isAutoupdateBackground();
                menu.add(Menu.NONE, R.id.context_menu_autoupdate_background, 5,
                        backgroundAutoupdateEnabled ? R.string.context_menu_autoupdate_background
                                : R.string.context_menu_autoupdate_background_off)
                        .setCheckable(true).setChecked(model.autoupdateBackground);
            }
            if (model.autoupdateBackground && TabsTrackerService.getCurrentUpdatingTabId() == -1) {
                menu.add(Menu.NONE, R.id.context_menu_autoupdate_now, 6, R.string.context_menu_autoupdate_now);
            }
        }
    }

    @Override
    public boolean onContextItemSelected(MenuItem item) {
        AdapterView.AdapterContextMenuInfo menuInfo = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
        switch (item.getItemId()) {
        case R.id.context_menu_move:
            tabsAdapter.setDraggingItem(menuInfo.position);
            return true;
        case R.id.context_menu_copy_url:
            String url = tabsAdapter.getItem(menuInfo.position).webUrl;
            if (url != null) {
                Clipboard.copyText(this, url);
                Toast.makeText(this, getString(R.string.notification_url_copied, url), Toast.LENGTH_LONG).show();
            }
            return true;
        case R.id.context_menu_share_link:
            url = tabsAdapter.getItem(menuInfo.position).webUrl;
            if (url != null) {
                Intent shareIntent = new Intent(Intent.ACTION_SEND);
                shareIntent.setType("text/plain");
                shareIntent.putExtra(Intent.EXTRA_SUBJECT, url);
                shareIntent.putExtra(Intent.EXTRA_TEXT, url);
                startActivity(Intent.createChooser(shareIntent, getString(R.string.share_via)));
            }
            return true;
        case R.id.context_menu_favorites:
            handleFavorite(tabsAdapter.getItem(menuInfo.position));
            return true;
        case R.id.context_menu_autoupdate_background:
            tabsAdapter.getItem(menuInfo.position).autoupdateBackground = !tabsAdapter
                    .getItem(menuInfo.position).autoupdateBackground;
            tabsAdapter.notifyDataSetChanged();
            return true;
        case R.id.context_menu_autoupdate_now:
            startService(new Intent(this, TabsTrackerService.class)
                    .putExtra(TabsTrackerService.EXTRA_UPDATE_IMMEDIATELY, true));
            return true;
        }
        return false;
    }

    private void updateTabPanelTabletWeight() {
        if (MainApplication.getInstance().settings.isRealTablet()
                && !MainApplication.getInstance().settings.showSidePanel()) {
            DrawerLayout.LayoutParams sidebarLayoutParams = (DrawerLayout.LayoutParams) findViewById(R.id.sidebar)
                    .getLayoutParams();
            Point displaySize = AppearanceUtils.getDisplaySize(getWindowManager().getDefaultDisplay());
            sidebarLayoutParams.width = (int) (displaySize.x
                    * MainApplication.getInstance().settings.getTabPanelTabletWeight());
            findViewById(R.id.sidebar).setLayoutParams(sidebarLayoutParams);
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        Logger.d(TAG, "main activity creating");
        settings = MainApplication.getInstance().settings.getStaticSettings();
        autohideRulesHash = MainApplication.getInstance().settings.getAutohideRulesJson().hashCode();
        rootViewWeight = MainApplication.getInstance().settings.getRootViewWeight();
        tabsPanelRight = MainApplication.getInstance().settings.isTabsPanelOnRight();
        openSpoilers = MainApplication.getInstance().settings.openSpoilers();
        highlightSubscriptions = MainApplication.getInstance().settings.highlightSubscriptions();
        swipeToHideThread = MainApplication.getInstance().settings.swipeToHideThread();
        isHorizontalOrientation = getResources()
                .getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
        (theme = MainApplication.getInstance().settings.getTheme()).setTo(this);
        super.onCreate(savedInstanceState);
        if (MainApplication.getInstance().settings.showSidePanel()) {
            setContentView(tabsPanelRight ? R.layout.main_activity_tablet_right : R.layout.main_activity_tablet);
            LinearLayout.LayoutParams sidebarLayoutParams = (LinearLayout.LayoutParams) findViewById(R.id.sidebar)
                    .getLayoutParams();
            Point displaySize = AppearanceUtils.getDisplaySize(getWindowManager().getDefaultDisplay());
            int rootWidth = (int) (displaySize.x * rootViewWeight);
            sidebarLayoutParams.width = displaySize.x - rootWidth;
            findViewById(R.id.sidebar).setLayoutParams(sidebarLayoutParams);
        } else {
            setContentView(R.layout.main_activity_drawer);
            updateTabPanelTabletWeight();
        }
        initDrawer();

        View[] sidebarButtons = new View[] { findViewById(R.id.sidebar_btn_newtab),
                findViewById(R.id.sidebar_btn_history), findViewById(R.id.sidebar_btn_favorites) };
        hiddenTabsSection = new HiddenTabsSection(sidebarButtons);

        DragSortListView list = (DragSortListView) findViewById(R.id.sidebar_tabs_list);
        TabsState state = MainApplication.getInstance().tabsState;
        tabsAdapter = initTabsListView(list, state);
        handleUriIntent(getIntent());
        notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        broadcastReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                String action = intent.getAction();
                if (action == null) {
                    Logger.e(TAG, "received broadcast with NULL action");
                    return;
                }
                if (action.equals(PostingService.BROADCAST_ACTION_STATUS)) {
                    int progress = intent.getIntExtra(PostingService.EXTRA_BROADCAST_PROGRESS_STATUS, -1);
                    switch (progress) {
                    case PostingService.BROADCAST_STATUS_SUCCESS:
                        UrlHandler.open(intent.getStringExtra(PostingService.EXTRA_TARGET_URL), MainActivity.this);
                        notificationManager.cancel(PostingService.POSTING_NOTIFICATION_ID);
                        break;
                    case PostingService.BROADCAST_STATUS_ERROR:
                        Intent toPostForm = new Intent(MainActivity.this, PostFormActivity.class);
                        toPostForm.putExtra(PostingService.EXTRA_PAGE_HASH,
                                intent.getStringExtra(PostingService.EXTRA_PAGE_HASH));
                        toPostForm.putExtra(PostingService.EXTRA_SEND_POST_MODEL,
                                intent.getSerializableExtra(PostingService.EXTRA_SEND_POST_MODEL));
                        toPostForm.putExtra(PostingService.EXTRA_BOARD_MODEL,
                                intent.getSerializableExtra(PostingService.EXTRA_BOARD_MODEL));
                        toPostForm.putExtra(PostingService.EXTRA_RETURN_FROM_SERVICE, true);
                        toPostForm.putExtra(PostingService.EXTRA_RETURN_REASON,
                                intent.getIntExtra(PostingService.EXTRA_RETURN_REASON, 0));
                        String error = intent.getStringExtra(PostingService.EXTRA_RETURN_REASON_ERROR);
                        Serializable interactiveException = intent
                                .getSerializableExtra(PostingService.EXTRA_RETURN_REASON_INTERACTIVE_EXCEPTION);
                        if (error != null) {
                            toPostForm.putExtra(PostingService.EXTRA_RETURN_REASON_ERROR, error);
                        }
                        if (interactiveException != null) {
                            toPostForm.putExtra(PostingService.EXTRA_RETURN_REASON_INTERACTIVE_EXCEPTION,
                                    interactiveException);
                        }
                        startActivity(toPostForm);
                        notificationManager.cancel(PostingService.POSTING_NOTIFICATION_ID);
                        break;
                    }
                } else if (action.equals(TabsTrackerService.BROADCAST_ACTION_NOTIFY)) {
                    tabsAdapter.notifyDataSetChanged(false);
                    TabsTrackerService.clearUnread();
                }
            }
        };
        intentFilter = new IntentFilter();
        intentFilter.addAction(PostingService.BROADCAST_ACTION_STATUS);
        intentFilter.addAction(TabsTrackerService.BROADCAST_ACTION_NOTIFY);

        if (!TabsTrackerService.isRunning() && MainApplication.getInstance().settings.isAutoupdateEnabled())
            startService(new Intent(this, TabsTrackerService.class));

        if (MainApplication.getInstance().settings.isSFWRelease())
            NewsReader.checkNews(this);
    }

    @Override
    protected void onStart() {
        super.onStart();
        registerReceiver(broadcastReceiver, intentFilter);
        tabsAdapter.notifyDataSetChanged(false);
        ExtendedTrustManager.bindActivity(this);
    }

    @Override
    protected void onStop() {
        super.onStop();
        unregisterReceiver(broadcastReceiver);
        ExtendedTrustManager.unbindActivity();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        MainApplication.getInstance().tabsSwitcher.currentId = null;
        MainApplication.getInstance().tabsSwitcher.currentFragment = null;
        isDestroyed = true;
        Logger.d(TAG, "main activity destroyed");
    }

    public boolean isPaused() {
        return isPaused;
    }

    @Override
    protected void onPause() {
        super.onPause();
        isPaused = true;
    }

    @Override
    protected void onResume() {
        super.onResume();
        isPaused = false;
        TabsTrackerService.clearUnread();

        StaticSettingsContainer newSettings = MainApplication.getInstance().settings.getStaticSettings();

        boolean shouldClearCache = false;
        boolean shouldReloadBoardFragment = false;
        boolean shouldRestartActivity = false;

        if (!MainApplication.getInstance().settings.getTheme().equals(theme)
                || MainApplication.getInstance().settings.getRootViewWeight() != rootViewWeight) {
            shouldClearCache = true;
            shouldRestartActivity = true;
        }

        if (MainApplication.getInstance().settings.isTabsPanelOnRight() != tabsPanelRight) {
            shouldRestartActivity = true;
        }

        if (settings.isDisplayDate != newSettings.isDisplayDate
                || (settings.isDisplayDate && (settings.isLocalTime != newSettings.isLocalTime))
                || MainApplication.getInstance().settings.getAutohideRulesJson().hashCode() != autohideRulesHash
                || MainApplication.getInstance().settings.openSpoilers() != openSpoilers
                || MainApplication.getInstance().settings.highlightSubscriptions() != highlightSubscriptions
                || MainApplication.getInstance().settings.subscriptionsClear()) {
            shouldClearCache = true;
            shouldReloadBoardFragment = true;
        }

        MainApplication.getInstance().settings.setSubscriptionsClear(false);

        if (settings.repliesOnlyQuantity != newSettings.repliesOnlyQuantity
                || settings.showHiddenItems != newSettings.showHiddenItems
                || settings.maskPictures != newSettings.maskPictures
                || MainApplication.getInstance().settings.swipeToHideThread() != swipeToHideThread) {
            shouldReloadBoardFragment = true;
        }

        if (shouldClearCache)
            clearCache();
        if (shouldRestartActivity) {
            restartActivity();
            return;
        }

        MainApplication.getInstance().settings.updateStaticSettings(settings);
        autohideRulesHash = MainApplication.getInstance().settings.getAutohideRulesJson().hashCode();
        openSpoilers = MainApplication.getInstance().settings.openSpoilers();
        highlightSubscriptions = MainApplication.getInstance().settings.highlightSubscriptions();
        swipeToHideThread = MainApplication.getInstance().settings.swipeToHideThread();
        updateTabPanelTabletWeight();

        if (shouldReloadBoardFragment)
            reloadCurrentBoardFragment();
        handleOrientationChange(getResources().getConfiguration(), shouldReloadBoardFragment);
    }

    private void clearCache() {
        MainApplication.getInstance().pagesCache.clearLru();
    }

    private void reloadCurrentBoardFragment() {
        Fragment currentFragment = MainApplication.getInstance().tabsSwitcher.currentFragment;
        if (currentFragment instanceof BoardFragment) {
            Long id = MainApplication.getInstance().tabsSwitcher.currentId;
            if (id != null) {
                TabModel tab = MainApplication.getInstance().tabsState.findTabById(id);
                MainApplication.getInstance().tabsSwitcher.switchTo(tab, getSupportFragmentManager(), true);
            }
        }
    }

    private void restartActivity() {
        MainApplication.getInstance().tabsSwitcher.currentId = null;
        MainApplication.getInstance().tabsSwitcher.currentFragment = null;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            // https://code.google.com/p/android/issues/detail?id=93731
            Async.runAsync(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(10);
                    } catch (Exception e) {
                    }
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            CompatibilityImpl.recreateActivity(MainActivity.this);
                        }
                    });
                }
            });
        } else {
            final Intent i = new Intent(this.getIntent());
            this.finish();
            Async.runAsync(new Runnable() {
                @Override
                public void run() {
                    //?  ?? ? activity; onDestroy() ? -> onCreate() 
                    while (!isDestroyed)
                        Thread.yield();
                    Async.runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            MainActivity.this.startActivity(i);
                        }
                    });
                }
            });
        }
    }

    private void handleOrientationChange(Configuration configuration) {
        handleOrientationChange(configuration, false);
    }

    private void handleOrientationChange(Configuration configuration, boolean doNotReloadBoardFragment) {
        boolean newOrientation = configuration.orientation == Configuration.ORIENTATION_LANDSCAPE;
        if (newOrientation != isHorizontalOrientation) {
            if (rootViewWeight != 1.0f) {
                clearCache();
                restartActivity();
            } else {
                if (!doNotReloadBoardFragment && FlowTextHelper.IS_AVAILABLE) {
                    reloadCurrentBoardFragment();
                }
                isHorizontalOrientation = newOrientation;
            }
        }
    }

    class HiddenTabsSection implements View.OnClickListener {
        private View btnNewTab;
        private View btnHistory;
        private View btnFavorites;

        public HiddenTabsSection(View[] views) {
            for (View view : views) {
                view.setOnClickListener(this);
                switch (view.getId()) {
                case R.id.sidebar_btn_newtab:
                    btnNewTab = view;
                    break;
                case R.id.sidebar_btn_favorites:
                    btnFavorites = view;
                    break;
                case R.id.sidebar_btn_history:
                    btnHistory = view;
                    break;
                }
            }
        }

        public void updateViewSelection(int selectedPosition) {
            setSelectedBackground(btnNewTab, selectedPosition == TabModel.POSITION_NEWTAB);
            setSelectedBackground(btnHistory, selectedPosition == TabModel.POSITION_HISTORY);
            setSelectedBackground(btnFavorites, selectedPosition == TabModel.POSITION_FAVORITES);
        }

        @Override
        public void onClick(View v) {
            tabsAdapter.setDraggingItem(-1);
            int position = TabModel.POSITION_NEWTAB;
            switch (v.getId()) {
            case R.id.sidebar_btn_newtab:
                position = TabModel.POSITION_NEWTAB;
                break;
            case R.id.sidebar_btn_favorites:
                position = TabModel.POSITION_FAVORITES;
                break;
            case R.id.sidebar_btn_history:
                position = TabModel.POSITION_HISTORY;
                break;
            }
            tabsAdapter.setDraggingItem(-1);
            boolean needSerialize = tabsAdapter.getSelectedItem() != position;
            tabsAdapter.setSelectedItem(position, needSerialize);
            closeDrawer();
        }

        private void setSelectedBackground(View view, boolean selected) {
            TypedValue typedValue;
            if (selected) {
                typedValue = ThemeUtils.resolveAttribute(getTheme(), R.attr.sidebarSelectedItem, true);
            } else {
                typedValue = new TypedValue();
                TypedArray typedArray = obtainStyledAttributes(R.style.SelectableItem,
                        new int[] { android.R.attr.background });
                typedArray.getValue(0, typedValue);
                typedArray.recycle();
            }
            if (typedValue.type >= TypedValue.TYPE_FIRST_COLOR_INT
                    && typedValue.type <= TypedValue.TYPE_LAST_COLOR_INT) {
                view.setBackgroundColor(typedValue.data);
            } else {
                view.setBackgroundResource(typedValue.resourceId);
            }
        }

    }

    @SuppressLint("ClickableViewAccessibility")
    private TabsAdapter initTabsListView(final DragSortListView list, final TabsState tabsState) {
        final TabsAdapter adapter = new TabsAdapter(this, tabsState, new TabSelectListener() {
            private final int selectionOffset = (int) (getResources().getDimension(R.dimen.tab_height) * 0.35f);

            @Override
            public void onTabSelected(int position) {
                hiddenTabsSection.updateViewSelection(position);
                if (position >= 0) {
                    list.setItemChecked(position, true);
                    boolean visible = false;
                    int absChildCount = list.getChildCount();
                    for (int i = 0; i < absChildCount; ++i) {
                        if (position == list.getPositionForView(list.getChildAt(i))) {
                            visible = true;
                            break;
                        }
                    }
                    if (!visible) {
                        if (position == 0)
                            list.setSelection(0);
                        else
                            list.setSelectionFromTop(position, selectionOffset);
                    }
                    MainApplication.getInstance().tabsSwitcher.switchTo(tabsState.tabsArray.get(position),
                            getSupportFragmentManager());
                } else {
                    list.clearChoices();
                    MainApplication.getInstance().tabsSwitcher.switchTo(position, getSupportFragmentManager());
                }
            }
        });

        DragSortController controller = new DragSortController(list, R.id.tab_drag_handle,
                DragSortController.ON_DRAG, 0) {
            @Override
            public View onCreateFloatView(int position) {
                return adapter.getView(position, null, list);
            }

            @Override
            public void onDragFloatView(View floatView, Point floatPoint, Point touchPoint) {
            }

            @Override
            public void onDestroyFloatView(View floatView) {
            }
        };

        list.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                boolean needCloseDrawer = adapter.getDraggingItem() == -1 || position != adapter.getSelectedItem();
                adapter.setDraggingItem(-1);
                boolean needSerialize = adapter.getSelectedItem() != position;
                adapter.setSelectedItem(position, needSerialize);
                if (needCloseDrawer)
                    closeDrawer();
            }
        });

        list.setDropListener(new DropListener() {
            @Override
            public void drop(int from, int to) {
                if (from != to) {
                    adapter.setDraggingItem(-1);
                    int newSelected = to;
                    if (from != adapter.getSelectedItem()) {
                        newSelected = adapter.getSelectedItem();
                        if (from < adapter.getSelectedItem() && to >= adapter.getSelectedItem())
                            --newSelected;
                        else if (from > adapter.getSelectedItem() && to <= adapter.getSelectedItem())
                            ++newSelected;
                    }
                    TabModel model = tabsState.tabsArray.remove(from);
                    tabsState.tabsArray.add(to, model);
                    adapter.setSelectedItem(newSelected); //serialization enabled
                }
            }
        });

        list.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
        list.setAdapter(adapter);
        list.setDragEnabled(true);
        list.setFloatViewManager(controller);
        list.setOnTouchListener(controller);
        registerForContextMenu(list);
        adapter.setSelectedItem(tabsState.position, false);
        return adapter;
    }

    private boolean hasChild(View view, View child) {
        if (view == child)
            return true;
        if (view instanceof ViewGroup) {
            ViewGroup group = (ViewGroup) view;
            for (int i = 0; i < group.getChildCount(); ++i) {
                if (hasChild(group.getChildAt(i), child))
                    return true;
            }
        }
        return false;
    }

    private boolean focusActionBar() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB)
            return false;
        if (drawerLayout == null || drawerLayout.isDrawerOpen(DRAWER_GRAVITY))
            return false;
        try {
            int resId = getResources().getIdentifier("action_bar_container", "id", "android");
            View actionBar = getWindow().getDecorView().findViewById(resId);
            if (hasChild(actionBar, getCurrentFocus()))
                return false;
            actionBar.requestFocus();
            return true;
        } catch (Exception e) {
            Logger.e(TAG, e);
            return false;
        }
    }

    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        if (settings.scrollVolumeButtons) {
            switch (keyCode) {
            case KeyEvent.KEYCODE_VOLUME_UP:
            case KeyEvent.KEYCODE_VOLUME_DOWN:
                return true;
            }
        }
        return super.onKeyUp(keyCode, event);
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        switch (keyCode) {
        case KeyEvent.KEYCODE_VOLUME_UP:
        case KeyEvent.KEYCODE_VOLUME_DOWN:
            if (settings.scrollVolumeButtons) {
                try {
                    Fragment currentFragment = MainApplication.getInstance().tabsSwitcher.currentFragment;
                    if (currentFragment instanceof BoardFragment) {
                        BoardFragment boardFragment = (BoardFragment) currentFragment;
                        if (keyCode == KeyEvent.KEYCODE_VOLUME_UP)
                            boardFragment.scrollUp();
                        else
                            boardFragment.scrollDown();
                        return true;
                    }
                } catch (Exception e) {
                    Logger.e(TAG, e);
                }
            }
            break;
        case KeyEvent.KEYCODE_BACK:
            if (onBack())
                return true;
            break;
        case KeyEvent.KEYCODE_DPAD_LEFT:
            if (focusActionBar())
                return true;
            break;
        }
        return super.onKeyDown(keyCode, event);
    }

    private boolean onBack() {
        if (tabsAdapter != null && tabsAdapter.getDraggingItem() != -1) {
            tabsAdapter.setDraggingItem(-1);
            return true;
        }
        if (drawerLayout != null && drawerLayout.isDrawerOpen(DRAWER_GRAVITY)) {
            closeDrawer();
            return true;
        }
        if (tabsAdapter != null && tabsAdapter.back()) {
            return true;
        }
        return false;
    }

    private boolean canFavorite(TabModel tab) {
        if (tab.type == TabModel.TYPE_LOCAL || tab.pageModel == null)
            return false;
        switch (tab.pageModel.type) {
        case UrlPageModel.TYPE_INDEXPAGE:
        case UrlPageModel.TYPE_BOARDPAGE:
        case UrlPageModel.TYPE_THREADPAGE:
            return true;
        }
        return false;
    }

    private boolean isFavorite(TabModel tab) {
        if (tab.type == TabModel.TYPE_LOCAL || tab.pageModel == null)
            return false;
        Database database = MainApplication.getInstance().database;
        switch (tab.pageModel.type) {
        case UrlPageModel.TYPE_INDEXPAGE:
            return database.isFavorite(tab.pageModel.chanName, null, null, null);
        case UrlPageModel.TYPE_BOARDPAGE:
            return database.isFavorite(tab.pageModel.chanName, tab.pageModel.boardName,
                    Integer.toString(tab.pageModel.boardPage), null);
        case UrlPageModel.TYPE_THREADPAGE:
            return database.isFavorite(tab.pageModel.chanName, tab.pageModel.boardName, null,
                    tab.pageModel.threadNumber);
        }
        return false;
    }

    private void handleFavorite(TabModel tab) {
        if (tab.type == TabModel.TYPE_LOCAL || tab.pageModel == null)
            return;
        Database database = MainApplication.getInstance().database;
        switch (tab.pageModel.type) {
        case UrlPageModel.TYPE_INDEXPAGE:
            if (database.isFavorite(tab.pageModel.chanName, null, null, null)) {
                database.removeFavorite(tab.pageModel.chanName, null, null, null);
            } else {
                database.addFavorite(tab.pageModel.chanName, null, null, null, tab.title, tab.webUrl);
            }
            break;
        case UrlPageModel.TYPE_BOARDPAGE:
            if (database.isFavorite(tab.pageModel.chanName, tab.pageModel.boardName,
                    Integer.toString(tab.pageModel.boardPage), null)) {
                database.removeFavorite(tab.pageModel.chanName, tab.pageModel.boardName,
                        Integer.toString(tab.pageModel.boardPage), null);
            } else {
                database.addFavorite(tab.pageModel.chanName, tab.pageModel.boardName,
                        Integer.toString(tab.pageModel.boardPage), null, tab.title, tab.webUrl);
            }
            break;
        case UrlPageModel.TYPE_THREADPAGE:
            if (database.isFavorite(tab.pageModel.chanName, tab.pageModel.boardName, null,
                    tab.pageModel.threadNumber)) {
                database.removeFavorite(tab.pageModel.chanName, tab.pageModel.boardName, null,
                        tab.pageModel.threadNumber);
            } else {
                database.addFavorite(tab.pageModel.chanName, tab.pageModel.boardName, null,
                        tab.pageModel.threadNumber, tab.title, tab.webUrl);
            }
            break;
        }
        if (MainApplication.getInstance().tabsSwitcher.currentId != null
                && MainApplication.getInstance().tabsSwitcher.currentId
                        .equals(Long.valueOf(TabModel.POSITION_FAVORITES))
                && MainApplication.getInstance().tabsSwitcher.currentFragment instanceof FavoritesFragment) {
            ((FavoritesFragment) MainApplication.getInstance().tabsSwitcher.currentFragment).update();
        }
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        handleUriIntent(intent);
    }

    private void handleUriIntent(Intent intent) {
        TabsTrackerService.clearUnread();
        if (intent != null) {
            if (intent.getBooleanExtra(TabsTrackerService.EXTRA_CLEAR_SUBSCRIPTIONS, false))
                TabsTrackerService.clearSubscriptions();
            if (MainApplication.getInstance().settings.useFakeBrowser())
                FakeBrowser.dismiss();
            if (intent.getData() != null && URLUtil.isFileUrl(intent.getDataString())) {
                LocalHandler.open(intent.getData().getPath(), this);
                return;
            }
            String url = intent.getDataString();
            if (url != null && url.length() != 0) {
                UrlHandler.open(url, this, MainApplication.getInstance().settings.useFakeBrowser());
            }
            intent.setData(null);
        }
    }
}