org.floens.chan.ui.activity.BoardActivity.java Source code

Java tutorial

Introduction

Here is the source code for org.floens.chan.ui.activity.BoardActivity.java

Source

/*
 * Clover - 4chan browser https://github.com/Floens/Clover/
 * Copyright (C) 2014  Floens
 *
 * 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 org.floens.chan.ui.activity;

import java.util.List;

import org.floens.chan.ChanApplication;
import org.floens.chan.R;
import org.floens.chan.chan.ChanUrls;
import org.floens.chan.core.model.Loadable;
import org.floens.chan.core.model.Pin;
import org.floens.chan.core.model.Post;
import org.floens.chan.service.WatchService;
import org.floens.chan.ui.fragment.ThreadFragment;
import org.floens.chan.utils.Utils;

import android.app.ActionBar;
import android.app.AlertDialog;
import android.app.FragmentTransaction;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Configuration;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.ActionBarDrawerToggle;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.widget.ArrayAdapter;
import android.widget.FrameLayout;

public class BoardActivity extends BaseActivity implements ActionBar.OnNavigationListener {
    private Loadable boardLoadable = new Loadable();
    private Loadable threadLoadable = new Loadable();
    private ThreadFragment boardFragment;
    private ThreadFragment threadFragment;

    private boolean actionBarSetToListNavigation = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        boardFragment = ThreadFragment.newInstance(this);
        threadFragment = ThreadFragment.newInstance(this);

        FragmentTransaction ft = getFragmentManager().beginTransaction();
        ft.replace(R.id.left_pane, boardFragment);
        ft.replace(R.id.right_pane, threadFragment);
        ft.commitAllowingStateLoss();

        final ActionBar actionBar = getActionBar();
        actionBar.setListNavigationCallbacks(
                new ArrayAdapter<String>(actionBar.getThemedContext(), R.layout.board_select_spinner,
                        android.R.id.text1, ChanApplication.getBoardManager().getSavedKeys()),
                this);

        updatePaneState();
        updateActionBarState();

        Intent startIntent = getIntent();
        Uri startUri = startIntent.getData();

        if (savedInstanceState != null) {
            threadLoadable.readFromBundle(this, "thread", savedInstanceState);
            startLoadingThread(threadLoadable);

            // Reset page etc.
            Loadable tmp = new Loadable();
            tmp.readFromBundle(this, "board", savedInstanceState);
            loadBoard(tmp.board);
        } else {
            if (startUri != null) {
                handleIntentURI(startUri);
            }

            if (boardLoadable.mode == Loadable.Mode.INVALID) {
                List<String> savedValues = ChanApplication.getBoardManager().getSavedValues();
                if (savedValues.size() > 0) {
                    loadBoard(savedValues.get(0));
                }
            }
        }
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);

        boardLoadable.writeToBundle(this, "board", outState);
        threadLoadable.writeToBundle(this, "thread", outState);
    }

    @Override
    protected void onStart() {
        super.onStart();

        WatchService.onActivityStart();
    }

    @Override
    protected void onStop() {
        super.onStop();

        WatchService.onActivityStop();
    }

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

        ChanApplication.getPinnedManager().updateAll();
    }

    @Override
    protected void initDrawer() {
        pinDrawerListener = new ActionBarDrawerToggle(this, pinDrawer, R.drawable.ic_drawer, R.string.drawer_open,
                R.string.drawer_close) {
        };

        super.initDrawer();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);

        return true;
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        pinDrawerListener.onConfigurationChanged(newConfig);
        updateActionBarState();

        updatePaneState();
    }

    private void updatePaneState() {
        DisplayMetrics metrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(metrics);
        int width = metrics.widthPixels;

        FrameLayout left = (FrameLayout) findViewById(R.id.left_pane);
        FrameLayout right = (FrameLayout) findViewById(R.id.right_pane);

        LayoutParams leftParams = left.getLayoutParams();
        LayoutParams rightParams = right.getLayoutParams();

        // Content view dp's:
        // Nexus 4 is 384 x 640 dp
        // Nexus 7 is 600 x 960 dp
        // Nexus 10 is 800 x 1280 dp

        if (width < Utils.dp(800)) {
            if (width < Utils.dp(400)) {
                leftParams.width = width - Utils.dp(30);
            } else {
                leftParams.width = width - Utils.dp(150);
            }
            rightParams.width = width;
        } else {
            leftParams.width = Utils.dp(300);
            rightParams.width = width - Utils.dp(300);
        }

        left.setLayoutParams(leftParams);
        right.setLayoutParams(rightParams);

        threadPane.requestLayout();
        left.requestLayout();
        right.requestLayout();
    }

    @Override
    public void openPin(Pin pin) {
        startLoadingThread(pin.loadable);

        pinDrawer.closeDrawer(pinDrawerView);
    }

    @Override
    public void onOPClicked(Post post) {
        startLoadingThread(new Loadable(post.board, post.no, post.subject));
    }

    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        pinDrawerListener.syncState();
    }

    @Override
    public void onBackPressed() {
        if (threadPane.isOpen()) {
            super.onBackPressed();
        } else {
            threadPane.openPane();
        }
    }

    @Override
    public void updatePin(Pin pin) {
        super.updatePin(pin);
        updateActionBarState();
    }

    private void updateActionBarState() {
        // Force the actionbar state after the ThreadPane layout,
        // otherwise the ThreadPane incorrectly reports that it's not slidable.
        threadPane.post(new Runnable() {
            @Override
            public void run() {
                updateActionBarStateCallback();
            }
        });
    }

    private void updateActionBarStateCallback() {
        final ActionBar actionBar = getActionBar();

        if (threadPane.isSlideable()) {
            if (threadPane.isOpen()) {
                int index = getBoardIndexNavigator(boardLoadable.board);

                if (index >= 0) {
                    //                    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
                    setActionBarListMode();
                    actionBar.setTitle("");
                } else {
                    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
                    String niceTitle = ChanApplication.getBoardManager().getBoardKey(boardLoadable.board);
                    if (niceTitle == null) {
                        actionBar.setTitle("/" + boardLoadable.board + "/");
                    } else {
                        actionBar.setTitle(niceTitle);
                    }
                }

                actionBar.setHomeButtonEnabled(true);
                pinDrawerListener.setDrawerIndicatorEnabled(true);

                if (boardLoadable.isBoardMode())
                    setShareUrl(ChanUrls.getBoardUrlDesktop(boardLoadable.board));
            } else {
                actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
                actionBar.setTitle(threadLoadable.title);
                pinDrawerListener.setDrawerIndicatorEnabled(false);

                if (threadLoadable.isThreadMode())
                    setShareUrl(ChanUrls.getThreadUrlDesktop(threadLoadable.board, threadLoadable.no));
            }

            actionBar.setDisplayHomeAsUpEnabled(true);
        } else {
            setActionBarListMode();
            //            actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
            pinDrawerListener.setDrawerIndicatorEnabled(true);
            actionBar.setTitle(threadLoadable.title);

            actionBar.setDisplayHomeAsUpEnabled(true);

            if (threadLoadable.isThreadMode())
                setShareUrl(ChanUrls.getThreadUrlDesktop(threadLoadable.board, threadLoadable.no));
        }

        actionBar.setDisplayShowTitleEnabled(true);

        invalidateOptionsMenu();
    }

    private void setActionBarListMode() {
        ActionBar actionBar = getActionBar();
        if (actionBar.getNavigationMode() != ActionBar.NAVIGATION_MODE_LIST)
            actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        boolean open = threadPane.isOpen();
        boolean slidable = threadPane.isSlideable();

        setMenuItemEnabled(menu.findItem(R.id.action_reload_board), slidable && open);
        setMenuItemEnabled(menu.findItem(R.id.action_reload_thread), slidable && !open);
        setMenuItemEnabled(menu.findItem(R.id.action_reload_tablet), !slidable);

        setMenuItemEnabled(menu.findItem(R.id.action_pin), !slidable || !open);

        setMenuItemEnabled(menu.findItem(R.id.action_reply), slidable);
        setMenuItemEnabled(menu.findItem(R.id.action_reply_tablet), !slidable);

        return super.onPrepareOptionsMenu(menu);
    }

    private void setMenuItemEnabled(MenuItem item, boolean enabled) {
        if (item != null) {
            item.setVisible(enabled);
            item.setEnabled(enabled);
        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (pinDrawerListener.onOptionsItemSelected(item)) {
            return true;
        }

        switch (item.getItemId()) {
        case R.id.action_reload_board:
        case R.id.action_reload_tablet_board:
            boardFragment.reload();
            return true;
        case R.id.action_reload_thread:
        case R.id.action_reload_tablet_thread:
            threadFragment.reload();
            return true;
        case R.id.action_reply:
            if (threadPane.isOpen()) {
                boardFragment.openReply();
            } else {
                threadFragment.openReply();
            }
            return true;
        case R.id.action_reply_board:
            boardFragment.openReply();

            return true;
        case R.id.action_reply_thread:
            threadFragment.openReply();

            return true;
        case R.id.action_pin:
            if (threadFragment.hasLoader()) {
                Pin pin = new Pin();
                pin.loadable = threadLoadable;

                addPin(pin);

                pinDrawer.openDrawer(pinDrawerView);
            }

            return true;
        case R.id.action_open_browser:
            if (threadPane.isOpen()) {
                showUrlOpenPicker(ChanUrls.getBoardUrlDesktop(boardLoadable.board));
            } else {
                if (threadFragment.hasLoader()) {
                    showUrlOpenPicker(ChanUrls.getThreadUrlDesktop(threadLoadable.board, threadLoadable.no));
                }
            }

            return true;
        case android.R.id.home:
            threadPane.openPane();

            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onPanelClosed(View view) {
        updateActionBarState();
    }

    @Override
    public void onPanelOpened(View view) {
        updateActionBarState();
    }

    /**
     * Sets the navigator to appropriately and calls startLoadingBoard
     *
     * @param board
     */
    private void loadBoard(String board) {
        boardLoadable = new Loadable(board);

        int index = getBoardIndexNavigator(boardLoadable.board);
        if (index >= 0) {
            ActionBar actionBar = getActionBar();
            setActionBarListMode();

            if (actionBar.getSelectedNavigationIndex() != index) {
                actionBar.setSelectedNavigationItem(index);
            } else {
                startLoadingBoard(boardLoadable);
            }
        } else {
            startLoadingBoard(boardLoadable);
        }
    }

    @Override
    public boolean onNavigationItemSelected(int position, long id) {
        if (!actionBarSetToListNavigation) {
            actionBarSetToListNavigation = true;
        } else {
            List<String> savedValues = ChanApplication.getBoardManager().getSavedValues();
            if (position >= 0 && position < savedValues.size()) {
                boardLoadable = new Loadable(savedValues.get(position));
                startLoadingBoard(boardLoadable);
            }
        }

        return true;
    }

    private void startLoadingBoard(Loadable loadable) {
        if (loadable.mode == Loadable.Mode.INVALID)
            return;

        boardLoadable = loadable;

        boardFragment.bindLoadable(loadable);
        boardFragment.requestData();

        updateActionBarState();
    }

    private void startLoadingThread(Loadable loadable) {
        if (loadable.mode == Loadable.Mode.INVALID)
            return;

        Pin pin = ChanApplication.getPinnedManager().findPinByLoadable(loadable);
        if (pin != null) {
            // Use the loadable from the pin.
            // This way we can store the listview position in the pin loadable,
            // and not in a separate loadable instance.
            loadable = pin.loadable;
        }

        threadLoadable = loadable;

        threadFragment.bindLoadable(loadable);
        threadFragment.requestData();

        if (TextUtils.isEmpty(loadable.title)) {
            loadable.title = "/" + loadable.board + "/" + loadable.no;
        }

        threadPane.closePane();

        updateActionBarState();
    }

    /**
     * Handle opening from an external url.
     *
     * @param startUri
     */
    private void handleIntentURI(Uri startUri) {
        List<String> parts = startUri.getPathSegments();

        if (parts.size() == 1) {
            // Board mode
            String rawBoard = parts.get(0);
            if (ChanApplication.getBoardManager().getBoardExists(rawBoard)) {
                // To clear the flag
                loadBoard(rawBoard);
                loadBoard(rawBoard);
            } else {
                handleIntentURIFallback(startUri.toString());
            }
        } else if (parts.size() == 3) {
            // Thread mode
            String rawBoard = parts.get(0);
            int no = -1;

            try {
                no = Integer.parseInt(parts.get(2));
            } catch (NumberFormatException e) {
            }

            if (no >= 0 && ChanApplication.getBoardManager().getBoardExists(rawBoard)) {
                startLoadingThread(new Loadable(rawBoard, no));
            } else {
                handleIntentURIFallback(startUri.toString());
                return;
            }
        } else {
            showUrlOpenPicker(startUri.toString());
        }
    }

    private void handleIntentURIFallback(final String url) {
        new AlertDialog.Builder(this).setTitle(R.string.open_unknown_title).setMessage(R.string.open_unknown)
                .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        finish();
                    }
                }).setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        showUrlOpenPicker(url);
                    }
                }).setCancelable(false).create().show();
    }

    private int getBoardIndexNavigator(String boardValue) {
        List<String> list = ChanApplication.getBoardManager().getSavedValues();
        for (int i = 0; i < list.size(); i++) {
            if (list.get(i).equals(boardValue)) {
                return i;
            }
        }

        return -1;
    }
}