/* * Copyright (c) 2011, 2012 Roberto Tyley * * This file is part of 'Agit' - an Android Git client. * * Agit 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. * * Agit 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.madgag.agit; import static android.os.Build.VERSION_CODES.HONEYCOMB; import static android.text.Html.fromHtml; import static com.madgag.agit.GitIntents.GITDIR; import static com.madgag.agit.GitIntents.PATH; import static com.madgag.agit.GitIntents.UNTIL_REVS; import static com.madgag.agit.GitIntents.gitDirFrom; import static com.madgag.android.HtmlStyleUtil.boldCode; import static com.madgag.android.IntentUtil.isIntentAvailable; import static org.apache.commons.io.FileUtils.copyInputStreamToFile; import android.content.Intent; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.support.v4.app.LoaderManager; import android.support.v4.content.Loader; import android.text.Spanned; import android.text.TextUtils; import android.util.Log; import android.webkit.WebSettings; import android.webkit.WebView; import android.widget.Toast; import java.io.File; import java.io.IOException; import java.net.URLConnection; import org.eclipse.jgit.diff.RawText; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectLoader; import org.eclipse.jgit.lib.ObjectStream; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevWalk; import org.eclipse.jgit.storage.file.FileRepositoryBuilder; import org.eclipse.jgit.treewalk.TreeWalk; import org.eclipse.jgit.util.RawParseUtils; public class BlobViewFragment extends com.madgag.agit.WebViewFragment implements LoaderManager .LoaderCallbacks<BlobView> { private static final String TAG = "BlobViewFragment"; public static BlobViewFragment newInstance(File gitdir, String revision, String path) { BlobViewFragment f = new BlobViewFragment(); Bundle args = new Bundle(); args.putString(GITDIR, gitdir.getAbsolutePath()); args.putString(UNTIL_REVS, revision); args.putString(PATH, path); f.setArguments(args); return f; } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); getLoaderManager().initLoader(0, null, this); } @Override public Loader<BlobView> onCreateLoader(int id, Bundle b) { return new AsyncLoader<BlobView>(getActivity()) { public BlobView loadInBackground() { Bundle args = getArguments(); try { Repository repo = FileRepositoryBuilder.create(gitDirFrom(args)); ObjectId revision = repo.resolve(args.getString(UNTIL_REVS)); RevWalk revWalk = new RevWalk(repo); RevCommit commit = revWalk.parseCommit(revision); TreeWalk treeWalk = TreeWalk.forPath(repo, args.getString(PATH), commit.getTree()); ObjectId blobId = treeWalk.getObjectId(0); ObjectLoader objectLoader = revWalk.getObjectReader().open(blobId, Constants.OBJ_BLOB); ObjectStream binaryTestStream = objectLoader.openStream(); boolean blobIsBinary = RawText.isBinary(binaryTestStream); binaryTestStream.close(); Log.d(TAG, "blobIsBinary="+blobIsBinary); return blobIsBinary?new BinaryBlobView(objectLoader, treeWalk.getNameString()):new TextBlobView(objectLoader); } catch (IOException e) { throw new RuntimeException(e); } } }; } @Override public void onLoadFinished(Loader<BlobView> stringLoader, BlobView r) { r.displayBlob(); } @Override public void onLoaderReset(Loader<BlobView> stringLoader) { } private class TextBlobView implements BlobView { private static final String TAG = "BlobViewFragment"; private final String blobHTML; TextBlobView(ObjectLoader objectLoader) throws IOException { byte[] cachedBytes = objectLoader.getCachedBytes(); Log.d(TAG, "Got " + cachedBytes.length + " of data"); String decode = RawParseUtils.decode(cachedBytes); blobHTML = dressFileContentForWebView(decode); } private String dressFileContentForWebView(String decode) { GoogleCodePrettify googleCodePrettify = new GoogleCodePrettify(); String boom = TextUtils.htmlEncode(decode).replace("\n", "<br>"); String contentString = ""; contentString += "<html><head>"; for (String css : googleCodePrettify.getCssFiles()) { contentString += "<link href='file:///android_asset/" + css + "' rel='stylesheet' type='text/css'/>"; } for (String js : googleCodePrettify.getJsFiles()) { contentString += "<script src='file:///android_asset/" + js + "' type='text/javascript'></script> "; } // contentString += handler.getFileScriptFiles(); contentString += "</head><body onload='prettyPrint()'><pre class='prettyprint'>"; //String sourceString = new String(array); contentString += boom; contentString += "</pre></body></html>"; return contentString; } public void displayBlob() { WebView webView = getWebView(); WebSettings settings = webView.getSettings(); settings.setUseWideViewPort(true); settings.setJavaScriptEnabled(true); // settings.setLoadWithOverviewMode(true); settings.setBuiltInZoomControls(true); if (Build.VERSION.SDK_INT >= HONEYCOMB) { // see also http://stackoverflow.com/q/5125851/438886 settings.setDisplayZoomControls(false); } webView.loadDataWithBaseURL("file:///android_asset", blobHTML, "text/html", "UTF-8", null); } } private class BinaryBlobView implements BlobView { private final File tempFile; private final String mimeType; private final String nameString; BinaryBlobView(ObjectLoader objectLoader, String nameString) throws IOException { this.nameString = nameString; ObjectStream stream = objectLoader.openStream(); tempFile= new File(getActivity().getExternalCacheDir(), nameString); copyInputStreamToFile(stream, tempFile); mimeType=URLConnection.getFileNameMap().getContentTypeFor(nameString); Log.d(TAG, "mimeType="+mimeType+" tempFile="+tempFile); } public void displayBlob() { Uri data = Uri.parse("file://" + tempFile.getAbsolutePath()); Intent intent = new Intent(android.content.Intent.ACTION_VIEW); intent.setDataAndType(data, mimeType); if (isIntentAvailable(getActivity(), intent)) { startActivity(intent); } else { Spanned messageHtml = fromHtml(getString(R.string.no_viewer_available_for_file, boldCode(nameString))); Toast.makeText(getActivity(), messageHtml, Toast.LENGTH_LONG).show(); } getActivity().finish(); } } } interface BlobView { void displayBlob(); }