package me.ccrama.redditslide.Fragments; import android.animation.ValueAnimator; import android.app.Activity; import android.content.Intent; import android.graphics.Bitmap; import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; import android.support.v4.app.Fragment; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.ViewTreeObserver; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ProgressBar; import com.afollestad.materialdialogs.AlertDialogWrapper; import com.google.gson.Gson; import com.google.gson.JsonObject; import com.nostra13.universalimageloader.core.DisplayImageOptions; import com.nostra13.universalimageloader.core.assist.FailReason; import com.nostra13.universalimageloader.core.assist.ImageScaleType; import com.nostra13.universalimageloader.core.imageaware.ImageViewAware; import com.nostra13.universalimageloader.core.listener.ImageLoadingListener; import com.nostra13.universalimageloader.core.listener.ImageLoadingProgressListener; import com.sothree.slidinguppanel.SlidingUpPanelLayout; import net.dean.jraw.models.Comment; import java.io.File; import java.io.IOException; import java.net.URL; import java.net.URLConnection; import me.ccrama.redditslide.Activities.MediaView; import me.ccrama.redditslide.Activities.ShadowboxComments; import me.ccrama.redditslide.Activities.Website; import me.ccrama.redditslide.Adapters.CommentUrlObject; import me.ccrama.redditslide.ContentType; import me.ccrama.redditslide.OpenRedditLink; import me.ccrama.redditslide.R; import me.ccrama.redditslide.Reddit; import me.ccrama.redditslide.SecretConstants; import me.ccrama.redditslide.SettingValues; import me.ccrama.redditslide.SubmissionViews.PopulateShadowboxInfo; import me.ccrama.redditslide.Views.ImageSource; import me.ccrama.redditslide.Views.MediaVideoView; import me.ccrama.redditslide.Views.SubsamplingScaleImageView; import me.ccrama.redditslide.util.GifUtils; import me.ccrama.redditslide.util.HttpUtil; import me.ccrama.redditslide.util.LogUtil; import me.ccrama.redditslide.util.NetworkUtil; import okhttp3.OkHttpClient; /** * Created by ccrama on 6/2/2015. */ public class MediaFragmentComment extends Fragment { public String contentUrl; public String sub; public String actuallyLoaded; public int i; private ViewGroup rootView; private MediaVideoView videoView; private boolean imageShown; private float previous; private boolean hidden; private int stopPosition; public boolean isGif; private GifUtils.AsyncLoadGif gif; private CommentUrlObject s; private OkHttpClient client; private Gson gson; private String mashapeKey; @Override public void onDestroy() { super.onDestroy(); LogUtil.v("Destroying"); ((SubsamplingScaleImageView) rootView.findViewById(R.id.submission_image)).recycle(); } @Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); if (isVisibleToUser && videoView != null) { videoView.seekTo(0); videoView.start(); } } @Override public void onResume() { super.onResume(); if (videoView != null) { videoView.seekTo(stopPosition); videoView.start(); } } @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); if (videoView != null) { stopPosition = videoView.getCurrentPosition(); videoView.pause(); ((SlidingUpPanelLayout) rootView.findViewById(R.id.sliding_layout)).setPanelState( SlidingUpPanelLayout.PanelState.COLLAPSED); outState.putInt("position", stopPosition); } } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { rootView = (ViewGroup) inflater.inflate(R.layout.submission_mediacard, container, false); if (savedInstanceState != null && savedInstanceState.containsKey("position")) { stopPosition = savedInstanceState.getInt("position"); } final SlidingUpPanelLayout slideLayout = ((SlidingUpPanelLayout) rootView.findViewById(R.id.sliding_layout)); PopulateShadowboxInfo.doActionbar(s.comment, rootView, getActivity(), true); (rootView.findViewById(R.id.thumbimage2)).setVisibility(View.GONE); ContentType.Type type = ContentType.getContentType(contentUrl); if (!ContentType.fullImage(type)) { addClickFunctions((rootView.findViewById(R.id.submission_image)), slideLayout, rootView, type, getActivity(), s); } else { (rootView.findViewById(R.id.thumbimage2)).setVisibility(View.GONE); addClickFunctions((rootView.findViewById(R.id.submission_image)), slideLayout, rootView, type, getActivity(), s); } doLoad(contentUrl); final View.OnClickListener openClick = new View.OnClickListener() { @Override public void onClick(View v) { ((SlidingUpPanelLayout) rootView.findViewById(R.id.sliding_layout)).setPanelState( SlidingUpPanelLayout.PanelState.EXPANDED); } }; rootView.findViewById(R.id.base).setOnClickListener(openClick); final View title = rootView.findViewById(R.id.title); title.getViewTreeObserver() .addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { ((SlidingUpPanelLayout) rootView.findViewById( R.id.sliding_layout)).setPanelHeight(title.getMeasuredHeight()); title.getViewTreeObserver().removeOnGlobalLayoutListener(this); } }); ((SlidingUpPanelLayout) rootView.findViewById(R.id.sliding_layout)).addPanelSlideListener( new SlidingUpPanelLayout.PanelSlideListener() { @Override public void onPanelSlide(View panel, float slideOffset) { } @Override public void onPanelStateChanged(View panel, SlidingUpPanelLayout.PanelState previousState, SlidingUpPanelLayout.PanelState newState) { if (newState == SlidingUpPanelLayout.PanelState.EXPANDED) { final Comment c = s.comment.getComment(); rootView.findViewById(R.id.base) .setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String url = "https://reddit.com" + "/r/" + c.getSubredditName() + "/comments/" + c.getDataNode() .get("link_id") .asText() .substring(3, c.getDataNode() .get("link_id") .asText() .length()) + "/nothing/" + c.getId() + "?context=3"; new OpenRedditLink(getActivity(), url); } }); } else { rootView.findViewById(R.id.base).setOnClickListener(openClick); } } }); return rootView; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Bundle bundle = this.getArguments(); i = bundle.getInt("page"); s = ((ShadowboxComments) getActivity()).comments.get(i); sub = s.comment.getComment().getSubredditName(); contentUrl = bundle.getString("contentUrl"); client = Reddit.client; gson = new Gson(); mashapeKey = SecretConstants.getImgurApiKey(getContext()); } public void doLoad(final String contentUrl) { switch (ContentType.getContentType(contentUrl)) { case DEVIANTART: doLoadDeviantArt(contentUrl); break; case IMAGE: doLoadImage(contentUrl); break; case IMGUR: doLoadImgur(contentUrl); break; case XKCD: doLoadXKCD(contentUrl); break; case VID_ME: case STREAMABLE: case GIF: doLoadGif(contentUrl); break; } } public void doLoadXKCD(String url) { if (!url.endsWith("/")) { url = url + "/"; } if (NetworkUtil.isConnected(getContext())) { final String apiUrl = url + "info.0.json"; LogUtil.v(apiUrl); final String finalUrl = url; new AsyncTask<Void, Void, JsonObject>() { @Override protected JsonObject doInBackground(Void... params) { return HttpUtil.getJsonObject(client, gson, apiUrl); } @Override protected void onPostExecute(final JsonObject result) { if (result != null && !result.isJsonNull() && result.has("error")) { LogUtil.v("Error loading content"); } else { try { if (result != null && !result.isJsonNull() && result.has("img")) { doLoadImage(result.get("img").getAsString()); rootView.findViewById(R.id.submission_image) .setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { try { new AlertDialogWrapper.Builder( getContext()).setTitle( result.get("safe_title").getAsString()) .setMessage( result.get("alt").getAsString()) .show(); } catch (Exception ignored) { } return true; } }); } else { Intent i = new Intent(getContext(), Website.class); i.putExtra(Website.EXTRA_URL, finalUrl); getContext().startActivity(i); } } catch (Exception e2) { e2.printStackTrace(); Intent i = new Intent(getContext(), Website.class); i.putExtra(Website.EXTRA_URL, finalUrl); getContext().startActivity(i); } } } }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } } private static void addClickFunctions(final View base, final SlidingUpPanelLayout slidingPanel, final View clickingArea, final ContentType.Type type, final Activity contextActivity, final CommentUrlObject submission) { base.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (slidingPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED) { slidingPanel.setPanelState(SlidingUpPanelLayout.PanelState.COLLAPSED); } else { switch (type) { case IMAGE: if (SettingValues.image) { Intent myIntent = new Intent(contextActivity, MediaView.class); String url; url = submission.getUrl(); myIntent.putExtra(MediaView.EXTRA_DISPLAY_URL, submission.getUrl()); myIntent.putExtra(MediaView.EXTRA_URL, url); myIntent.putExtra(MediaView.SUBREDDIT, submission.getSubredditName()); myIntent.putExtra(MediaView.EXTRA_SHARE_URL, submission.getUrl()); contextActivity.startActivity(myIntent); } else { Reddit.defaultShare(submission.getUrl(), contextActivity); } break; } } } }); } public void doLoadGif(final String dat) { isGif = true; videoView = (MediaVideoView) rootView.findViewById(R.id.gif); videoView.clearFocus(); videoView.setZOrderOnTop(true); rootView.findViewById(R.id.gifarea).setVisibility(View.VISIBLE); rootView.findViewById(R.id.submission_image).setVisibility(View.GONE); final ProgressBar loader = (ProgressBar) rootView.findViewById(R.id.gifprogress); rootView.findViewById(R.id.progress).setVisibility(View.GONE); gif = new GifUtils.AsyncLoadGif(getActivity(), (MediaVideoView) rootView.findViewById(R.id.gif), loader, rootView.findViewById(R.id.placeholder), false, false, true, sub); gif.execute(dat); } public void doLoadDeviantArt(String url) { final String apiUrl = "http://backend.deviantart.com/oembed?url=" + url; LogUtil.v(apiUrl); new AsyncTask<Void, Void, JsonObject>() { @Override protected JsonObject doInBackground(Void... params) { return HttpUtil.getJsonObject(client, gson, apiUrl); } @Override protected void onPostExecute(JsonObject result) { LogUtil.v("doLoad onPostExecute() called with: " + "result = [" + result + "]"); if (result != null && !result.isJsonNull() && (result.has("fullsize_url") || result.has("url"))) { String url; if (result.has("fullsize_url")) { url = result.get("fullsize_url").getAsString(); } else { url = result.get("url").getAsString(); } doLoadImage(url); } else { Intent i = new Intent(getActivity(), Website.class); i.putExtra(Website.EXTRA_URL, contentUrl); getActivity().startActivity(i); } } }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } public void doLoadImgur(String url) { if (url.endsWith("/")) { url = url.substring(0, url.length() - 1); } final String finalUrl = url; String hash = url.substring(url.lastIndexOf("/"), url.length()); if (NetworkUtil.isConnected(getActivity())) { if (hash.startsWith("/")) hash = hash.substring(1, hash.length()); final String apiUrl = "https://imgur-apiv3.p.mashape.com/3/image/" + hash + ".json"; LogUtil.v(apiUrl); new AsyncTask<Void, Void, JsonObject>() { @Override protected JsonObject doInBackground(Void... params) { return HttpUtil.getImgurMashapeJsonObject(client, gson, apiUrl, mashapeKey); } @Override protected void onPostExecute(JsonObject result) { if (result != null && !result.isJsonNull() && result.has("error")) { LogUtil.v("Error loading content"); (getActivity()).finish(); } else { try { if (result != null && !result.isJsonNull() && result.has("image")) { String type = result.get("image") .getAsJsonObject() .get("image") .getAsJsonObject() .get("type") .getAsString(); String urls = result.get("image") .getAsJsonObject() .get("links") .getAsJsonObject() .get("original") .getAsString(); if (type.contains("gif")) { doLoadGif(urls); } else if (!imageShown) { //only load if there is no image doLoadImage(urls); } } else if (result != null && result.has("data")) { String type = result.get("data") .getAsJsonObject() .get("type") .getAsString(); String urls = result.get("data") .getAsJsonObject() .get("link") .getAsString(); String mp4 = ""; if (result.get("data").getAsJsonObject().has("mp4")) { mp4 = result.get("data") .getAsJsonObject() .get("mp4") .getAsString(); } if (type.contains("gif")) { doLoadGif(((mp4 == null || mp4.isEmpty()) ? urls : mp4)); } else if (!imageShown) { //only load if there is no image doLoadImage(urls); } } else { if (!imageShown) doLoadImage(finalUrl); } } catch (Exception e) { LogUtil.e(e, "Error loading Imgur image finalUrl = [" + finalUrl + "], apiUrl = [" + apiUrl + "]"); //todo open it? } } } }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } } public void doLoadImage(String contentUrl) { if (contentUrl != null && contentUrl.contains("bildgur.de")) { contentUrl = contentUrl.replace("b.bildgur.de", "i.imgur.com"); } if (contentUrl != null && ContentType.isImgurLink(contentUrl)) { contentUrl = contentUrl + ".png"; } rootView.findViewById(R.id.gifprogress).setVisibility(View.GONE); if (contentUrl != null && contentUrl.contains("m.imgur.com")) { contentUrl = contentUrl.replace("m.imgur.com", "i.imgur.com"); } if ((contentUrl != null && !contentUrl.startsWith("https://i.redditmedia.com") && !contentUrl.startsWith("https://i.reddituploads.com") && !contentUrl.contains( "imgur.com"))) { //we can assume redditmedia and imgur links are to direct images and not websites rootView.findViewById(R.id.progress).setVisibility(View.VISIBLE); ((ProgressBar) rootView.findViewById(R.id.progress)).setIndeterminate(true); final String finalUrl2 = contentUrl; new AsyncTask<Void, Void, Void>() { @Override protected Void doInBackground(Void... params) { try { URL obj = new URL(finalUrl2); URLConnection conn = obj.openConnection(); final String type = conn.getHeaderField("Content-Type"); if (getActivity() != null) { getActivity().runOnUiThread(new Runnable() { @Override public void run() { if (!imageShown && type != null && !type.isEmpty() && type.startsWith("image/")) { //is image if (type.contains("gif")) { doLoadGif(finalUrl2.replace(".jpg", ".gif") .replace(".png", ".gif")); } else if (!imageShown) { displayImage(finalUrl2); } actuallyLoaded = finalUrl2; } else if (!imageShown) { Intent i = new Intent(getActivity(), Website.class); i.putExtra(Website.EXTRA_URL, finalUrl2); getActivity().startActivity(i); } } }); } } catch (IOException e) { LogUtil.e(e, "Error loading image finalUrl2 = [" + finalUrl2 + "]"); } return null; } @Override protected void onPostExecute(Void aVoid) { rootView.findViewById(R.id.progress).setVisibility(View.GONE); } }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } else { displayImage(contentUrl); } actuallyLoaded = contentUrl; } public void displayImage(final String url) { if (!imageShown) { actuallyLoaded = url; final SubsamplingScaleImageView i = (SubsamplingScaleImageView) rootView.findViewById(R.id.submission_image); i.setMinimumDpi(70); i.setMinimumTileDpi(240); final ProgressBar bar = (ProgressBar) rootView.findViewById(R.id.progress); bar.setIndeterminate(false); bar.setProgress(0); final Handler handler = new Handler(); final Runnable progressBarDelayRunner = new Runnable() { public void run() { bar.setVisibility(View.VISIBLE); } }; handler.postDelayed(progressBarDelayRunner, 500); ImageView fakeImage = new ImageView(getActivity()); fakeImage.setLayoutParams(new LinearLayout.LayoutParams(i.getWidth(), i.getHeight())); fakeImage.setScaleType(ImageView.ScaleType.CENTER_CROP); File f = ((Reddit) getActivity().getApplicationContext()).getImageLoader() .getDiscCache() .get(url); if (f != null && f.exists()) { imageShown = true; try { i.setImage(ImageSource.uri(f.getAbsolutePath())); } catch (Exception e) { //todo i.setImage(ImageSource.bitmap(loadedImage)); } (rootView.findViewById(R.id.progress)).setVisibility(View.GONE); handler.removeCallbacks(progressBarDelayRunner); previous = i.scale; final float base = i.scale; i.setOnZoomChangedListener(new SubsamplingScaleImageView.OnZoomChangedListener() { @Override public void onZoomLevelChanged(float zoom) { if (zoom > previous && !hidden && zoom > base) { hidden = true; final View base = rootView.findViewById(R.id.base); ValueAnimator va = ValueAnimator.ofFloat(1.0f, 0.2f); int mDuration = 250; //in millis va.setDuration(mDuration); va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { public void onAnimationUpdate(ValueAnimator animation) { Float value = (Float) animation.getAnimatedValue(); base.setAlpha(value); } }); va.start(); //hide } else if (zoom <= previous && hidden) { hidden = false; final View base = rootView.findViewById(R.id.base); ValueAnimator va = ValueAnimator.ofFloat(0.2f, 1.0f); int mDuration = 250; //in millis va.setDuration(mDuration); va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { public void onAnimationUpdate(ValueAnimator animation) { Float value = (Float) animation.getAnimatedValue(); base.setAlpha(value); } }); va.start(); //unhide } previous = zoom; } }); } else { ((Reddit) getActivity().getApplicationContext()).getImageLoader() .displayImage(url, new ImageViewAware(fakeImage), new DisplayImageOptions.Builder().resetViewBeforeLoading(true) .cacheOnDisk(true) .imageScaleType(ImageScaleType.NONE) .cacheInMemory(false) .build(), new ImageLoadingListener() { private View mView; @Override public void onLoadingStarted(String imageUri, View view) { imageShown = true; mView = view; } @Override public void onLoadingFailed(String imageUri, View view, FailReason failReason) { Log.v(LogUtil.getTag(), "LOADING FAILED"); } @Override public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) { imageShown = true; File f = null; if (getActivity() != null) { f = ((Reddit) getActivity().getApplicationContext()) .getImageLoader() .getDiscCache() .get(url); } if (f != null && f.exists()) { i.setImage(ImageSource.uri(f.getAbsolutePath())); } else { i.setImage(ImageSource.bitmap(loadedImage)); } (rootView.findViewById(R.id.progress)).setVisibility( View.GONE); handler.removeCallbacks(progressBarDelayRunner); previous = i.scale; final float base = i.scale; i.setOnZoomChangedListener( new SubsamplingScaleImageView.OnZoomChangedListener() { @Override public void onZoomLevelChanged(float zoom) { if (zoom > previous && !hidden && zoom > base) { hidden = true; final View base = rootView.findViewById( R.id.base); ValueAnimator va = ValueAnimator.ofFloat(1.0f, 0.2f); int mDuration = 250; //in millis va.setDuration(mDuration); va.addUpdateListener( new ValueAnimator.AnimatorUpdateListener() { public void onAnimationUpdate( ValueAnimator animation) { Float value = (Float) animation .getAnimatedValue(); base.setAlpha(value); } }); va.start(); //hide } else if (zoom <= previous && hidden) { hidden = false; final View base = rootView.findViewById( R.id.base); ValueAnimator va = ValueAnimator.ofFloat(0.2f, 1.0f); int mDuration = 250; //in millis va.setDuration(mDuration); va.addUpdateListener( new ValueAnimator.AnimatorUpdateListener() { public void onAnimationUpdate( ValueAnimator animation) { Float value = (Float) animation .getAnimatedValue(); base.setAlpha(value); } }); va.start(); //unhide } previous = zoom; } }); } @Override public void onLoadingCancelled(String imageUri, View view) { Log.v(LogUtil.getTag(), "LOADING CANCELLED"); } }, new ImageLoadingProgressListener() { @Override public void onProgressUpdate(String imageUri, View view, int current, int total) { ((ProgressBar) rootView.findViewById( R.id.progress)).setProgress( Math.round(100.0f * current / total)); } }); } } } }