package org.fox.ttrss; import android.annotation.SuppressLint; import android.app.Dialog; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.preference.PreferenceManager; import android.support.v4.app.ActivityCompat; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewCompat; import android.support.v4.view.ViewPager; import android.support.v7.app.ActionBar; import android.support.v7.widget.Toolbar; import android.util.Log; import android.view.ContextMenu; import android.view.GestureDetector; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; import android.widget.ProgressBar; import android.widget.TextView; import com.ToxicBakery.viewpager.transforms.DepthPageTransformer; import com.nostra13.universalimageloader.core.DisplayImageOptions; import com.nostra13.universalimageloader.core.ImageLoader; import com.nostra13.universalimageloader.core.assist.FailReason; import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer; import com.nostra13.universalimageloader.core.listener.ImageLoadingListener; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; import java.util.ArrayList; import java.util.List; import it.sephiroth.android.library.imagezoom.ImageViewTouch; import me.relex.circleindicator.CircleIndicator; public class ArticleImagesPagerActivity extends CommonActivity implements GestureDetector.OnDoubleTapListener { private final String TAG = this.getClass().getSimpleName(); private ArrayList m_urls; private ArrayList m_checkedUrls; private String m_title; private ArticleImagesPagerAdapter m_adapter; private String m_content; private GestureDetector m_detector; private ProgressBar m_progress; private ViewPager m_pager; @Override public boolean onSingleTapConfirmed(MotionEvent motionEvent) { ActionBar bar = getSupportActionBar(); if (bar.isShowing()) { bar.hide(); } else { bar.show(); } return false; } @Override public boolean onDoubleTap(MotionEvent motionEvent) { return false; } @Override public boolean onDoubleTapEvent(MotionEvent motionEvent) { return false; } private class ArticleImagesPagerAdapter extends PagerAdapter { private List m_urls; public ArticleImagesPagerAdapter(List urls) { super(); m_urls = urls; } public ArticleImagesPagerAdapter() { super(); } @Override public int getCount() { return m_urls.size(); } @Override public boolean isViewFromObject(View view, Object o) { return view == o; } @Override public Object instantiateItem(ViewGroup container, int position) { String url = m_urls.get(position); Log.d(TAG, "called for URL: " + url); LayoutInflater inflater = (LayoutInflater) container.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); View view = inflater.inflate(R.layout.article_images_image, null); m_detector = new GestureDetector(ArticleImagesPagerActivity.this, new GestureDetector.SimpleOnGestureListener()); m_detector.setOnDoubleTapListener(ArticleImagesPagerActivity.this); ImageViewTouch imgView = (ImageViewTouch) view.findViewById(R.id.flavor_image); imgView.setFitToScreen(true); //imgView.setFitToWidth(true); imgView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View view, MotionEvent event) { return m_detector.onTouchEvent(event); } }); if (position == 0) { ViewCompat.setTransitionName(imgView, "TRANSITION:ARTICLE_IMAGES_PAGER"); } registerForContextMenu(imgView); DisplayImageOptions options = new DisplayImageOptions.Builder() .cacheInMemory(true) .resetViewBeforeLoading(true) .cacheOnDisk(true) .displayer(new FadeInBitmapDisplayer(200)) .build(); final ProgressBar progressBar = (ProgressBar) view.findViewById(R.id.flavor_image_progress); final View errorMessage = view.findViewById(R.id.flavor_image_error); ImageLoader.getInstance().displayImage(url, imgView, options, new ImageLoadingListener() { @Override public void onLoadingStarted(String s, View view) { } @Override public void onLoadingFailed(String s, View view, FailReason failReason) { progressBar.setVisibility(View.GONE); errorMessage.setVisibility(View.VISIBLE); } @Override public void onLoadingComplete(String s, View view, Bitmap bitmap) { if (bitmap != null) { view.setTag(s); } progressBar.setVisibility(View.GONE); } @Override public void onLoadingCancelled(String s, View view) { } }); ((ViewPager) container).addView(view, 0); if (position == 0) { ActivityCompat.startPostponedEnterTransition(ArticleImagesPagerActivity.this); } return view; } @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView((FrameLayout)object); } } private class ImageCheckTask extends AsyncTask, String, Integer> { @Override protected Integer doInBackground(List... urls) { int position = 0; for (String url : urls[0]) { if (!isCancelled()) { position++; //Log.d(TAG, "checking: " + url); DisplayImageOptions options = new DisplayImageOptions.Builder() .cacheInMemory(true) .cacheOnDisk(true) .build(); Bitmap bmp = ImageLoader.getInstance().loadImageSync(url, options); if (bmp != null && bmp.getWidth() > 128 && bmp.getHeight() > 128) { publishProgress(url, String.valueOf(position)); } else { publishProgress(null, String.valueOf(position)); } } } return -1; } @Override protected void onProgressUpdate(String... checkedUrl) { if (!isFinishing() && m_adapter != null) { if (checkedUrl[0] != null) { m_checkedUrls.add(checkedUrl[0]); m_adapter.notifyDataSetChanged(); } Log.d(TAG, "progr=" + checkedUrl[1]); m_progress.setProgress(Integer.valueOf(checkedUrl[1])); } else { cancel(true); } } @Override protected void onPostExecute(Integer result) { m_progress.setVisibility(View.GONE); CircleIndicator indicator = (CircleIndicator) findViewById(R.id.article_images_indicator); if (indicator != null) { indicator.setViewPager(m_pager); indicator.setVisibility(View.VISIBLE); } } } @Override public void onCreate(Bundle savedInstanceState) { ActivityCompat.postponeEnterTransition(this); // we use that before parent onCreate so let's init locally m_prefs = PreferenceManager .getDefaultSharedPreferences(getApplicationContext()); setTheme(R.style.DarkTheme); super.onCreate(savedInstanceState); setContentView(R.layout.article_images_pager); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); m_progress = (ProgressBar) findViewById(R.id.article_images_progress); getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().hide(); if (savedInstanceState == null) { m_title = getIntent().getStringExtra("title"); //m_urls = getIntent().getStringArrayListExtra("urls"); m_content = getIntent().getStringExtra("content"); String imgSrcFirst = getIntent().getStringExtra("firstSrc"); m_urls = new ArrayList(); Document doc = Jsoup.parse(m_content); Elements imgs = doc.select("img"); boolean firstFound = false; for (Element img : imgs) { String imgSrc = img.attr("src"); if (imgSrcFirst.equals(imgSrc)) firstFound = true; if (firstFound) { if (imgSrc.indexOf("//") == 0) imgSrc = "http:" + imgSrc; m_urls.add(imgSrc); } } } else { m_urls = savedInstanceState.getStringArrayList("urls"); m_title = savedInstanceState.getString("title"); m_content = savedInstanceState.getString("content"); } if (m_urls.size() > 1) { m_progress.setProgress(0); m_progress.setMax(m_urls.size()); m_checkedUrls = new ArrayList(); ArrayList tmp = new ArrayList(m_urls); m_checkedUrls.add(tmp.get(0)); tmp.remove(0); ImageCheckTask ict = new ImageCheckTask(); ict.execute(tmp); } else { m_checkedUrls = new ArrayList(m_urls); m_progress.setVisibility(View.GONE); } setTitle(m_title); m_adapter = new ArticleImagesPagerAdapter(m_checkedUrls); m_pager = (ViewPager) findViewById(R.id.article_images_pager); m_pager.setAdapter(m_adapter); m_pager.setPageTransformer(true, new DepthPageTransformer()); } @SuppressLint("NewApi") @Override public void onResume() { super.onResume(); } @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { getMenuInflater().inflate(R.menu.context_article_content_img, menu); super.onCreateContextMenu(menu, v, menuInfo); } @Override public void onSaveInstanceState(Bundle out) { super.onSaveInstanceState(out); out.putStringArrayList("urls", m_urls); out.putString("title", m_title); out.putString("content", m_content); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.context_article_content_img, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { return onContextItemSelected(item); // this is really bad :() } @Override public boolean onContextItemSelected(android.view.MenuItem item) { ViewPager pager = (ViewPager) findViewById(R.id.article_images_pager); String url = null; if (pager != null) { int currentItem = pager.getCurrentItem(); url = m_urls.get(currentItem); } switch (item.getItemId()) { case android.R.id.home: onBackPressed(); return true; case R.id.article_img_open: if (url != null) { try { Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); startActivity(intent); } catch (Exception e) { e.printStackTrace(); toast(R.string.error_other_error); } } return true; case R.id.article_img_copy: if (url != null) { copyToClipboard(url); } return true; case R.id.article_img_share: if (url != null) { Intent intent = new Intent(Intent.ACTION_SEND); intent.setType("image/png"); intent.putExtra(Intent.EXTRA_SUBJECT, url); intent.putExtra(Intent.EXTRA_TEXT, url); startActivity(Intent.createChooser(intent, url)); } return true; // TODO: this needs access to article text, I'm afraid case R.id.article_img_view_caption: if (url != null) { // Android doesn't give us an easy way to access title tags; // we'll use Jsoup on the body text to grab the title text // from the first image tag with this url. This will show // the wrong text if an image is used multiple times. Document doc = Jsoup.parse(m_content); Elements es = doc.getElementsByAttributeValue("src", url); if (es.size() > 0) { if (es.get(0).hasAttr("title")) { Dialog dia = new Dialog(this); if (es.get(0).hasAttr("alt")) { dia.setTitle(es.get(0).attr("alt")); } else { dia.setTitle(es.get(0).attr("title")); } TextView titleText = new TextView(this); if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) { titleText.setPaddingRelative(24, 24, 24, 24); } else { titleText.setPadding(24, 24, 24, 24); } titleText.setTextSize(16); titleText.setText(es.get(0).attr("title")); dia.setContentView(titleText); dia.show(); } else { toast(R.string.no_caption_to_display); } } else { toast(R.string.no_caption_to_display); } } return true; default: Log.d(TAG, "onContextItemSelected, unhandled id=" + item.getItemId()); return super.onContextItemSelected(item); } } }