com.github.pockethub.android.ui.commit.CommitFileViewActivity.java Source code

Java tutorial

Introduction

Here is the source code for com.github.pockethub.android.ui.commit.CommitFileViewActivity.java

Source

/*
 * Copyright (c) 2015 PocketHub
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.github.pockethub.android.ui.commit;

import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.Loader;
import android.support.v7.app.ActionBar;
import android.text.TextUtils;
import android.util.Base64;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.webkit.WebView;
import android.widget.ProgressBar;

import com.meisolsson.githubsdk.core.ServiceGenerator;
import com.meisolsson.githubsdk.model.GitHubFile;
import com.meisolsson.githubsdk.model.Repository;
import com.github.pockethub.android.Intents.Builder;
import com.github.pockethub.android.R;
import com.github.pockethub.android.core.commit.CommitUtils;
import com.github.pockethub.android.ui.BaseActivity;
import com.github.pockethub.android.ui.MarkdownLoader;
import com.github.pockethub.android.util.AvatarLoader;
import com.github.pockethub.android.util.HttpImageGetter;
import com.github.pockethub.android.util.InfoUtils;
import com.github.pockethub.android.util.MarkdownUtils;
import com.github.pockethub.android.util.PreferenceUtils;
import com.github.pockethub.android.util.ShareUtils;
import com.github.pockethub.android.util.SourceEditor;
import com.github.pockethub.android.util.ToastUtils;
import com.meisolsson.githubsdk.model.git.GitBlob;
import com.meisolsson.githubsdk.service.git.GitService;
import com.google.inject.Inject;

import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;

import static com.github.pockethub.android.Intents.EXTRA_BASE;
import static com.github.pockethub.android.Intents.EXTRA_HEAD;
import static com.github.pockethub.android.Intents.EXTRA_PATH;
import static com.github.pockethub.android.Intents.EXTRA_REPOSITORY;
import static com.github.pockethub.android.util.PreferenceUtils.RENDER_MARKDOWN;
import static com.github.pockethub.android.util.PreferenceUtils.WRAP;

/**
 * Activity to display the contents of a file in a commit
 */
public class CommitFileViewActivity extends BaseActivity implements LoaderCallbacks<CharSequence> {

    private static final String TAG = "CommitFileViewActivity";

    private static final String ARG_TEXT = "text";

    private static final String ARG_REPO = "repo";

    /**
     * Create intent to show file in commit
     *
     * @param repository
     * @param commit
     * @param file
     * @return intent
     */
    public static Intent createIntent(Repository repository, String commit, GitHubFile file) {
        Builder builder = new Builder("commit.file.VIEW");
        builder.repo(repository);
        builder.add(EXTRA_HEAD, commit);
        builder.add(EXTRA_PATH, file.filename());
        builder.add(EXTRA_BASE, file.sha());
        return builder.toIntent();
    }

    private Repository repo;

    private String commit;

    private String sha;

    private String path;

    private String file;

    private boolean isMarkdownFile;

    private String renderedMarkdown;

    private GitBlob blob;

    private ProgressBar loadingBar;

    private WebView codeView;

    private SourceEditor editor;

    private MenuItem markdownItem;

    @Inject
    private AvatarLoader avatars;

    @Inject
    private HttpImageGetter imageGetter;

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

        setContentView(R.layout.activity_commit_file_view);

        setSupportActionBar((android.support.v7.widget.Toolbar) findViewById(R.id.toolbar));

        repo = getIntent().getParcelableExtra(EXTRA_REPOSITORY);
        commit = getStringExtra(EXTRA_HEAD);
        sha = getStringExtra(EXTRA_BASE);
        path = getStringExtra(EXTRA_PATH);

        loadingBar = (ProgressBar) findViewById(R.id.pb_loading);
        codeView = (WebView) findViewById(R.id.wv_code);

        file = CommitUtils.getName(path);
        isMarkdownFile = MarkdownUtils.isMarkdown(file);

        editor = new SourceEditor(codeView);
        editor.setWrap(PreferenceUtils.getCodePreferences(this).getBoolean(WRAP, false));

        ActionBar actionBar = getSupportActionBar();
        int lastSlash = path.lastIndexOf('/');
        if (lastSlash != -1) {
            actionBar.setTitle(path.substring(lastSlash + 1));
        } else {
            actionBar.setTitle(path);
        }
        actionBar.setSubtitle(getString(R.string.commit_prefix) + CommitUtils.abbreviate(commit));
        avatars.bind(actionBar, repo.owner());

        loadContent();
    }

    @Override
    public boolean onCreateOptionsMenu(final Menu optionsMenu) {
        getMenuInflater().inflate(R.menu.activity_file_view, optionsMenu);

        MenuItem wrapItem = optionsMenu.findItem(R.id.m_wrap);
        if (PreferenceUtils.getCodePreferences(this).getBoolean(WRAP, false)) {
            wrapItem.setTitle(R.string.disable_wrapping);
        } else {
            wrapItem.setTitle(R.string.enable_wrapping);
        }

        markdownItem = optionsMenu.findItem(R.id.m_render_markdown);
        if (isMarkdownFile) {
            markdownItem.setEnabled(blob != null);
            markdownItem.setVisible(true);
            if (PreferenceUtils.getCodePreferences(this).getBoolean(RENDER_MARKDOWN, true)) {
                markdownItem.setTitle(R.string.show_raw_markdown);
            } else {
                markdownItem.setTitle(R.string.render_markdown);
            }
        }

        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.m_wrap:
            if (editor.getWrap()) {
                item.setTitle(R.string.enable_wrapping);
            } else {
                item.setTitle(R.string.disable_wrapping);
            }
            editor.toggleWrap();
            PreferenceUtils
                    .save(PreferenceUtils.getCodePreferences(this).edit().putBoolean(WRAP, editor.getWrap()));
            return true;

        case R.id.m_share:
            shareFile();
            return true;

        case R.id.m_render_markdown:
            if (editor.isMarkdown()) {
                item.setTitle(R.string.render_markdown);
                editor.toggleMarkdown();
                editor.setSource(file, blob);
            } else {
                item.setTitle(R.string.show_raw_markdown);
                editor.toggleMarkdown();
                if (renderedMarkdown != null) {
                    editor.setSource(file, renderedMarkdown, false);
                } else {
                    loadMarkdown();
                }
            }
            PreferenceUtils.save(PreferenceUtils.getCodePreferences(this).edit().putBoolean(RENDER_MARKDOWN,
                    editor.isMarkdown()));
            return true;

        default:
            return super.onOptionsItemSelected(item);
        }
    }

    @Override
    public Loader<CharSequence> onCreateLoader(int loader, Bundle args) {
        final String raw = args.getString(ARG_TEXT);
        final Repository repo = args.getParcelable(ARG_REPO);
        return new MarkdownLoader(this, repo, raw, imageGetter, false);
    }

    @Override
    public void onLoadFinished(Loader<CharSequence> loader, CharSequence rendered) {
        if (rendered == null) {
            ToastUtils.show(this, R.string.error_rendering_markdown);
        }

        loadingBar.setVisibility(View.GONE);
        codeView.setVisibility(View.VISIBLE);

        if (!TextUtils.isEmpty(rendered)) {
            renderedMarkdown = rendered.toString();
            if (markdownItem != null) {
                markdownItem.setEnabled(true);
            }
            editor.setMarkdown(true).setSource(file, renderedMarkdown, false);
        }
    }

    @Override
    public void onLoaderReset(Loader<CharSequence> loader) {
    }

    private void shareFile() {
        String id = InfoUtils.createRepoId(repo);
        startActivity(ShareUtils.create(path + " at " + CommitUtils.abbreviate(commit) + " on " + id,
                "https://github.com/" + id + "/blob/" + commit + '/' + path));
    }

    private void loadMarkdown() {
        loadingBar.setVisibility(View.VISIBLE);
        codeView.setVisibility(View.GONE);

        String markdown = new String(Base64.decode(blob.content(), Base64.DEFAULT));
        Bundle args = new Bundle();
        args.putCharSequence(ARG_TEXT, markdown);
        args.putParcelable(ARG_REPO, repo);
        getSupportLoaderManager().restartLoader(0, args, this);
    }

    private void loadContent() {
        ServiceGenerator.createService(this, GitService.class).getGitBlob(repo.owner().login(), repo.name(), sha)
                .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
                .compose(this.bindToLifecycle()).subscribe(response -> {
                    GitBlob gitBlob = response.body();
                    loadingBar.setVisibility(View.GONE);
                    codeView.setVisibility(View.VISIBLE);

                    editor.setSource(path, gitBlob);
                    blob = gitBlob;

                    if (markdownItem != null) {
                        markdownItem.setEnabled(true);
                    }

                    if (isMarkdownFile
                            && PreferenceUtils.getCodePreferences(this).getBoolean(RENDER_MARKDOWN, true)) {
                        loadMarkdown();
                    } else {
                        loadingBar.setVisibility(View.GONE);
                        codeView.setVisibility(View.VISIBLE);
                        editor.setSource(path, gitBlob);
                    }
                }, error -> {
                    Log.e(TAG, "Loading commit file contents failed", error);

                    loadingBar.setVisibility(View.GONE);
                    codeView.setVisibility(View.VISIBLE);
                    ToastUtils.show(this, error, R.string.error_file_load);
                });
    }

}