Merge remote-tracking branch 'remotes/cemrich/refactoring-NewsDetailFragment'
# Conflicts: # News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsDetailFragment.java
This commit is contained in:
commit
64a73121f9
7 changed files with 398 additions and 375 deletions
|
@ -21,7 +21,6 @@
|
||||||
|
|
||||||
package de.luhmer.owncloudnewsreader;
|
package de.luhmer.owncloudnewsreader;
|
||||||
|
|
||||||
import android.content.ComponentName;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
|
@ -30,11 +29,7 @@ import android.content.pm.ResolveInfo;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.support.customtabs.CustomTabsCallback;
|
|
||||||
import android.support.customtabs.CustomTabsClient;
|
|
||||||
import android.support.customtabs.CustomTabsIntent;
|
import android.support.customtabs.CustomTabsIntent;
|
||||||
import android.support.customtabs.CustomTabsServiceConnection;
|
|
||||||
import android.support.customtabs.CustomTabsSession;
|
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
import android.support.v4.app.FragmentManager;
|
import android.support.v4.app.FragmentManager;
|
||||||
import android.support.v4.app.FragmentPagerAdapter;
|
import android.support.v4.app.FragmentPagerAdapter;
|
||||||
|
@ -59,7 +54,6 @@ import java.util.Set;
|
||||||
|
|
||||||
import butterknife.BindView;
|
import butterknife.BindView;
|
||||||
import butterknife.ButterKnife;
|
import butterknife.ButterKnife;
|
||||||
import de.luhmer.owncloudnewsreader.chrometabs.CustomTabActivityManager;
|
|
||||||
import de.luhmer.owncloudnewsreader.database.DatabaseConnectionOrm;
|
import de.luhmer.owncloudnewsreader.database.DatabaseConnectionOrm;
|
||||||
import de.luhmer.owncloudnewsreader.database.DatabaseConnectionOrm.SORT_DIRECTION;
|
import de.luhmer.owncloudnewsreader.database.DatabaseConnectionOrm.SORT_DIRECTION;
|
||||||
import de.luhmer.owncloudnewsreader.database.model.RssItem;
|
import de.luhmer.owncloudnewsreader.database.model.RssItem;
|
||||||
|
@ -239,18 +233,9 @@ public class NewsDetailActivity extends PodcastFragmentActivity {
|
||||||
{
|
{
|
||||||
NewsDetailFragment ndf = getNewsDetailFragmentAtPosition(currentPosition);//(NewsDetailFragment) getSupportFragmentManager().findFragmentByTag("android:switcher:" + R.id.pager + ":" + currentPosition);
|
NewsDetailFragment ndf = getNewsDetailFragmentAtPosition(currentPosition);//(NewsDetailFragment) getSupportFragmentManager().findFragmentByTag("android:switcher:" + R.id.pager + ":" + currentPosition);
|
||||||
|
|
||||||
if(ndf != null && ndf.mWebView != null)
|
if(ndf != null && ndf.canNavigateBack()) {
|
||||||
{
|
ndf.navigateBack();
|
||||||
if (ndf.urls.size() > 1) {
|
return true;
|
||||||
ndf.urls.remove(0);
|
|
||||||
ndf.mWebView.loadUrl(ndf.urls.get(0));
|
|
||||||
return true;
|
|
||||||
} else if(ndf.urls.size() == 1) {
|
|
||||||
ndf.urls.remove(0);
|
|
||||||
ndf.startLoadRssItemToWebViewTask();
|
|
||||||
Log.v(TAG, "Load rssitem to webview again");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,60 +22,46 @@
|
||||||
package de.luhmer.owncloudnewsreader;
|
package de.luhmer.owncloudnewsreader;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.content.Context;
|
|
||||||
import android.graphics.Bitmap;
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.AsyncTask;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.customtabs.CustomTabsIntent;
|
import android.support.customtabs.CustomTabsIntent;
|
||||||
import android.support.v4.app.DialogFragment;
|
import android.support.v4.app.DialogFragment;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
import android.support.v4.app.FragmentTransaction;
|
import android.support.v4.app.FragmentTransaction;
|
||||||
import android.support.v4.content.ContextCompat;
|
import android.support.v4.content.ContextCompat;
|
||||||
import android.text.format.DateUtils;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.ContextMenu;
|
import android.view.ContextMenu;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.webkit.ConsoleMessage;
|
import android.webkit.WebBackForwardList;
|
||||||
import android.webkit.WebChromeClient;
|
import android.webkit.WebHistoryItem;
|
||||||
import android.webkit.WebResourceRequest;
|
|
||||||
import android.webkit.WebSettings;
|
import android.webkit.WebSettings;
|
||||||
import android.webkit.WebView;
|
import android.webkit.WebView;
|
||||||
import android.webkit.WebViewClient;
|
import android.webkit.WebViewClient;
|
||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
|
|
||||||
import com.nostra13.universalimageloader.cache.disc.DiskCache;
|
|
||||||
import com.nostra13.universalimageloader.core.ImageLoader;
|
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringEscapeUtils;
|
|
||||||
import org.jsoup.Jsoup;
|
import org.jsoup.Jsoup;
|
||||||
import org.jsoup.nodes.Document;
|
import org.jsoup.nodes.Document;
|
||||||
import org.jsoup.select.Elements;
|
import org.jsoup.select.Elements;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
import butterknife.BindView;
|
import butterknife.BindView;
|
||||||
import butterknife.ButterKnife;
|
import butterknife.ButterKnife;
|
||||||
import de.luhmer.owncloudnewsreader.database.model.Feed;
|
import de.luhmer.owncloudnewsreader.adapter.ProgressBarWebChromeClient;
|
||||||
|
import de.luhmer.owncloudnewsreader.async_tasks.RssItemToHtmlTask;
|
||||||
import de.luhmer.owncloudnewsreader.database.model.RssItem;
|
import de.luhmer.owncloudnewsreader.database.model.RssItem;
|
||||||
import de.luhmer.owncloudnewsreader.helper.AsyncTaskHelper;
|
import de.luhmer.owncloudnewsreader.helper.AsyncTaskHelper;
|
||||||
import de.luhmer.owncloudnewsreader.helper.ColorHelper;
|
import de.luhmer.owncloudnewsreader.helper.ColorHelper;
|
||||||
import de.luhmer.owncloudnewsreader.helper.ImageHandler;
|
|
||||||
import de.luhmer.owncloudnewsreader.helper.ThemeChooser;
|
import de.luhmer.owncloudnewsreader.helper.ThemeChooser;
|
||||||
|
|
||||||
public class NewsDetailFragment extends Fragment {
|
public class NewsDetailFragment extends Fragment implements RssItemToHtmlTask.Listener {
|
||||||
public static final String ARG_SECTION_NUMBER = "ARG_SECTION_NUMBER";
|
|
||||||
|
public static final String ARG_SECTION_NUMBER = "ARG_SECTION_NUMBER";
|
||||||
|
private static final String RSS_ITEM_PAGE_URL = "about:blank";
|
||||||
|
|
||||||
public final String TAG = getClass().getCanonicalName();
|
public final String TAG = getClass().getCanonicalName();
|
||||||
|
|
||||||
|
@ -87,7 +73,6 @@ public class NewsDetailFragment extends Fragment {
|
||||||
|
|
||||||
|
|
||||||
private int section_number;
|
private int section_number;
|
||||||
public List<String> urls = new ArrayList<>();
|
|
||||||
protected String html;
|
protected String html;
|
||||||
|
|
||||||
|
|
||||||
|
@ -136,11 +121,32 @@ public class NewsDetailFragment extends Fragment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true when calls to NewsDetailFragment#navigateBack()
|
||||||
|
* can be processed right now
|
||||||
|
* @see NewsDetailFragment#navigateBack()
|
||||||
|
*/
|
||||||
|
public boolean canNavigateBack() {
|
||||||
|
return !isCurrentPageRssItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Navigates back to the last displayed page. Call NewsDetailFragment#canNavigateBack()
|
||||||
|
* to check if back navigation is possible right now. Use e.g. for back button handling.
|
||||||
|
* @see NewsDetailFragment#navigateBack()
|
||||||
|
*/
|
||||||
|
public void navigateBack() {
|
||||||
|
if (isLastPageRssItem()) {
|
||||||
|
mWebView.clearHistory();
|
||||||
|
startLoadRssItemToWebViewTask();
|
||||||
|
} else if (!isCurrentPageRssItem()){
|
||||||
|
mWebView.goBack();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
View rootView = inflater.inflate(R.layout.fragment_news_detail, container, false);
|
View rootView = inflater.inflate(R.layout.fragment_news_detail, container, false);
|
||||||
|
|
||||||
section_number = (Integer) getArguments().get(ARG_SECTION_NUMBER);
|
section_number = (Integer) getArguments().get(ARG_SECTION_NUMBER);
|
||||||
|
|
||||||
|
@ -151,50 +157,34 @@ public class NewsDetailFragment extends Fragment {
|
||||||
return rootView;
|
return rootView;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startLoadRssItemToWebViewTask() {
|
private void startLoadRssItemToWebViewTask() {
|
||||||
AsyncTaskHelper.StartAsyncTask(new LoadRssItemToWebViewAsyncTask());
|
mWebView.setVisibility(View.GONE);
|
||||||
|
mProgressBarLoading.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
|
NewsDetailActivity ndActivity = ((NewsDetailActivity)getActivity());
|
||||||
|
if(background_color != Integer.MIN_VALUE && ThemeChooser.isDarkTheme(ndActivity))
|
||||||
|
{
|
||||||
|
mWebView.setBackgroundColor(background_color);
|
||||||
|
ndActivity.mViewPager.setBackgroundColor(background_color);
|
||||||
|
}
|
||||||
|
|
||||||
|
init_webView();
|
||||||
|
|
||||||
|
RssItem rssItem = ndActivity.rssItems.get(section_number);
|
||||||
|
|
||||||
|
RssItemToHtmlTask task = new RssItemToHtmlTask(ndActivity, rssItem, this);
|
||||||
|
AsyncTaskHelper.StartAsyncTask(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class LoadRssItemToWebViewAsyncTask extends AsyncTask<Void, Void, String> {
|
@Override
|
||||||
|
public void onRssItemParsed(String htmlPage) {
|
||||||
|
mWebView.setVisibility(View.VISIBLE);
|
||||||
|
mProgressBarLoading.setVisibility(View.GONE);
|
||||||
|
|
||||||
@Override
|
setSoftwareRenderModeForWebView(htmlPage, mWebView);
|
||||||
protected void onPreExecute() {
|
|
||||||
NewsDetailActivity ndActivity = ((NewsDetailActivity)getActivity());
|
|
||||||
|
|
||||||
if(background_color != Integer.MIN_VALUE && ThemeChooser.isDarkTheme(ndActivity))
|
html = htmlPage;
|
||||||
{
|
mWebView.loadDataWithBaseURL("file:///android_asset/", htmlPage, "text/html", "UTF-8", RSS_ITEM_PAGE_URL);
|
||||||
mWebView.setBackgroundColor(background_color);
|
|
||||||
ndActivity.mViewPager.setBackgroundColor(background_color);
|
|
||||||
}
|
|
||||||
|
|
||||||
init_webView();
|
|
||||||
|
|
||||||
mWebView.setVisibility(View.GONE);
|
|
||||||
mProgressBarLoading.setVisibility(View.VISIBLE);
|
|
||||||
|
|
||||||
super.onPreExecute();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String doInBackground(Void... voids) {
|
|
||||||
NewsDetailActivity ndActivity = ((NewsDetailActivity)getActivity());
|
|
||||||
|
|
||||||
RssItem rssItem = ndActivity.rssItems.get(section_number);
|
|
||||||
|
|
||||||
return getHtmlPage(ndActivity, rssItem, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPostExecute(String htmlPage) {
|
|
||||||
mWebView.setVisibility(View.VISIBLE);
|
|
||||||
mProgressBarLoading.setVisibility(View.GONE);
|
|
||||||
|
|
||||||
SetSoftwareRenderModeForWebView(htmlPage, mWebView);
|
|
||||||
|
|
||||||
html = htmlPage;
|
|
||||||
mWebView.loadDataWithBaseURL("file:///android_asset/", htmlPage, "text/html", "UTF-8", "");
|
|
||||||
super.onPostExecute(htmlPage);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -202,17 +192,14 @@ public class NewsDetailFragment extends Fragment {
|
||||||
* @param htmlPage
|
* @param htmlPage
|
||||||
* @param webView
|
* @param webView
|
||||||
*/
|
*/
|
||||||
public static void SetSoftwareRenderModeForWebView(String htmlPage, WebView webView) {
|
private void setSoftwareRenderModeForWebView(String htmlPage, WebView webView) {
|
||||||
if (htmlPage.contains(".gif")) {
|
if (htmlPage.contains(".gif")) {
|
||||||
webView.setLayerType(WebView.LAYER_TYPE_SOFTWARE, null);
|
webView.setLayerType(WebView.LAYER_TYPE_SOFTWARE, null);
|
||||||
Log.v("NewsDetailFragment", "Using LAYER_TYPE_SOFTWARE");
|
Log.v("NewsDetailFragment", "Using LAYER_TYPE_SOFTWARE");
|
||||||
} else {
|
} else {
|
||||||
//webView.setLayerType(WebView.LAYER_TYPE_HARDWARE, null);
|
if (webView.getLayerType() == WebView.LAYER_TYPE_HARDWARE) {
|
||||||
//Log.v("NewsDetailFragment", "Using LAYER_TYPE_HARDWARE");
|
|
||||||
|
|
||||||
if(webView.getLayerType() == WebView.LAYER_TYPE_HARDWARE) {
|
|
||||||
Log.v("NewsDetailFragment", "Using LAYER_TYPE_HARDWARE");
|
Log.v("NewsDetailFragment", "Using LAYER_TYPE_HARDWARE");
|
||||||
} else if (webView.getLayerType() == WebView.LAYER_TYPE_SOFTWARE){
|
} else if (webView.getLayerType() == WebView.LAYER_TYPE_SOFTWARE) {
|
||||||
Log.v("NewsDetailFragment", "Using LAYER_TYPE_SOFTWARE");
|
Log.v("NewsDetailFragment", "Using LAYER_TYPE_SOFTWARE");
|
||||||
} else {
|
} else {
|
||||||
Log.v("NewsDetailFragment", "Using LAYER_TYPE_DEFAULT");
|
Log.v("NewsDetailFragment", "Using LAYER_TYPE_DEFAULT");
|
||||||
|
@ -240,35 +227,7 @@ public class NewsDetailFragment extends Fragment {
|
||||||
|
|
||||||
registerForContextMenu(mWebView);
|
registerForContextMenu(mWebView);
|
||||||
|
|
||||||
mWebView.setWebChromeClient(new WebChromeClient() {
|
mWebView.setWebChromeClient(new ProgressBarWebChromeClient(mProgressbarWebView));
|
||||||
@Override
|
|
||||||
public boolean onConsoleMessage(ConsoleMessage cm) {
|
|
||||||
Log.v(TAG, cm.message() + " at " + cm.sourceId() + ":" + cm.lineNumber());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onProgressChanged(WebView view, int progress) {
|
|
||||||
if (progress < 100 && mProgressbarWebView.getVisibility() == ProgressBar.GONE) {
|
|
||||||
mProgressbarWebView.setVisibility(ProgressBar.VISIBLE);
|
|
||||||
}
|
|
||||||
mProgressbarWebView.setProgress(progress);
|
|
||||||
if (progress == 100) {
|
|
||||||
mProgressbarWebView.setVisibility(ProgressBar.GONE);
|
|
||||||
|
|
||||||
//The following three lines are a workaround for websites which don't use a background color
|
|
||||||
int bgColor = ContextCompat.getColor(getContext(), R.color.slider_listview_text_color_dark_theme);
|
|
||||||
NewsDetailActivity ndActivity = ((NewsDetailActivity) getActivity());
|
|
||||||
mWebView.setBackgroundColor(bgColor);
|
|
||||||
ndActivity.mViewPager.setBackgroundColor(bgColor);
|
|
||||||
|
|
||||||
|
|
||||||
if (ThemeChooser.isDarkTheme(getActivity())) {
|
|
||||||
mWebView.setBackgroundColor(ContextCompat.getColor(getContext(), android.R.color.transparent));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
mWebView.setWebViewClient(new WebViewClient() {
|
mWebView.setWebViewClient(new WebViewClient() {
|
||||||
|
@ -286,19 +245,17 @@ public class NewsDetailFragment extends Fragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPageStarted(WebView view, String url, Bitmap favicon) {
|
public void onPageFinished(WebView view, String url) {
|
||||||
if (changedUrl) {
|
super.onPageFinished(view, url);
|
||||||
changedUrl = false;
|
|
||||||
|
|
||||||
if (!url.equals("file:///android_asset/") && (urls.isEmpty() || !urls.get(0).equals(url))) {
|
// the following lines are a workaround for websites which don't use a background color
|
||||||
urls.add(0, url);
|
NewsDetailActivity ndActivity = ((NewsDetailActivity) getActivity());
|
||||||
|
int backgroundColor = ColorHelper.getColorFromAttribute(getContext(),
|
||||||
Log.v(TAG, "Page finished (added): " + url);
|
R.attr.news_detail_background_color);
|
||||||
}
|
mWebView.setBackgroundColor(backgroundColor);
|
||||||
}
|
ndActivity.mViewPager.setBackgroundColor(backgroundColor);
|
||||||
|
|
||||||
super.onPageStarted(view, url, favicon);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
mWebView.setOnTouchListener(new View.OnTouchListener() {
|
mWebView.setOnTouchListener(new View.OnTouchListener() {
|
||||||
|
@ -314,265 +271,101 @@ public class NewsDetailFragment extends Fragment {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
|
||||||
|
if (!(view instanceof WebView))
|
||||||
|
return;
|
||||||
|
|
||||||
|
WebView.HitTestResult result = ((WebView) view).getHitTestResult();
|
||||||
|
if (result == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int type = result.getType();
|
||||||
|
Document htmlDoc = Jsoup.parse(html);
|
||||||
|
FragmentTransaction ft = getFragmentManager().beginTransaction();
|
||||||
|
String text;
|
||||||
|
DialogFragment newFragment;
|
||||||
|
|
||||||
|
|
||||||
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
|
switch (type) {
|
||||||
if (v instanceof WebView) {
|
case WebView.HitTestResult.IMAGE_TYPE:
|
||||||
WebView.HitTestResult result = ((WebView) v).getHitTestResult();
|
case WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE:
|
||||||
if (result != null) {
|
String imageUrl = result.getExtra();
|
||||||
int type = result.getType();
|
|
||||||
|
|
||||||
Document htmldoc = Jsoup.parse(html);
|
if (imageUrl.startsWith("http") || imageUrl.startsWith("file")) {
|
||||||
|
URL mImageUrl;
|
||||||
|
String imgtitle;
|
||||||
|
String imgaltval;
|
||||||
|
String imgsrcval;
|
||||||
|
|
||||||
FragmentTransaction ft = getFragmentManager().beginTransaction();
|
imgsrcval = imageUrl.substring(imageUrl.lastIndexOf('/') + 1, imageUrl.length());
|
||||||
|
Elements imgtag = htmlDoc.getElementsByAttributeValueContaining("src", imageUrl);
|
||||||
|
|
||||||
if (type == WebView.HitTestResult.IMAGE_TYPE || type == WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE) {
|
|
||||||
String imageUrl = result.getExtra();
|
|
||||||
if (imageUrl.startsWith("http") || imageUrl.startsWith("file")) {
|
|
||||||
|
|
||||||
URL mImageUrl;
|
|
||||||
String imgtitle;
|
|
||||||
String imgaltval;
|
|
||||||
String imgsrcval;
|
|
||||||
|
|
||||||
imgsrcval = imageUrl.substring(imageUrl.lastIndexOf('/') + 1, imageUrl.length());
|
|
||||||
Elements imgtag = htmldoc.getElementsByAttributeValueContaining("src", imageUrl);
|
|
||||||
|
|
||||||
try {
|
|
||||||
imgtitle = imgtag.first().attr("title");
|
|
||||||
} catch (NullPointerException e) {
|
|
||||||
imgtitle = "";
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
imgaltval = imgtag.first().attr("alt");
|
|
||||||
} catch (NullPointerException e) {
|
|
||||||
imgaltval = "";
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
mImageUrl = new URL(imageUrl);
|
|
||||||
} catch (MalformedURLException e) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
String title = imgsrcval;
|
|
||||||
int titleIcon = android.R.drawable.ic_menu_gallery;
|
|
||||||
String text = (imgtitle.isEmpty()) ? imgaltval : imgtitle;
|
|
||||||
|
|
||||||
// Create and show the dialog.
|
|
||||||
DialogFragment newFragment =
|
|
||||||
NewsDetailImageDialogFragment.newInstanceImage(title, titleIcon, text, mImageUrl);
|
|
||||||
newFragment.show(ft, "menu_fragment_dialog");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (type == WebView.HitTestResult.SRC_ANCHOR_TYPE) {
|
|
||||||
String url = result.getExtra();
|
|
||||||
URL mUrl;
|
|
||||||
String text;
|
|
||||||
try {
|
try {
|
||||||
Elements urltag = htmldoc.getElementsByAttributeValueContaining("href", url);
|
imgtitle = imgtag.first().attr("title");
|
||||||
text = urltag.text();
|
} catch (NullPointerException e) {
|
||||||
mUrl = new URL(url);
|
imgtitle = "";
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
imgaltval = imgtag.first().attr("alt");
|
||||||
|
} catch (NullPointerException e) {
|
||||||
|
imgaltval = "";
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
mImageUrl = new URL(imageUrl);
|
||||||
} catch (MalformedURLException e) {
|
} catch (MalformedURLException e) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String title = imgsrcval;
|
||||||
|
int titleIcon = android.R.drawable.ic_menu_gallery;
|
||||||
|
text = (imgtitle.isEmpty()) ? imgaltval : imgtitle;
|
||||||
|
|
||||||
// Create and show the dialog.
|
// Create and show the dialog.
|
||||||
DialogFragment newFragment =
|
newFragment = NewsDetailImageDialogFragment.newInstanceImage(title, titleIcon, text, mImageUrl);
|
||||||
NewsDetailImageDialogFragment.newInstanceUrl(text, mUrl.toString());
|
|
||||||
newFragment.show(ft, "menu_fragment_dialog");
|
newFragment.show(ft, "menu_fragment_dialog");
|
||||||
}
|
}
|
||||||
//else if (type == WebView.HitTestResult.EMAIL_TYPE) { }
|
break;
|
||||||
//else if (type == WebView.HitTestResult.GEO_TYPE) { }
|
|
||||||
//else if (type == WebView.HitTestResult.PHONE_TYPE) { }
|
case WebView.HitTestResult.SRC_ANCHOR_TYPE:
|
||||||
//else if (type == WebView.HitTestResult.EDIT_TEXT_TYPE) { }
|
String url = result.getExtra();
|
||||||
}
|
URL mUrl;
|
||||||
|
try {
|
||||||
|
Elements urltag = htmlDoc.getElementsByAttributeValueContaining("href", url);
|
||||||
|
text = urltag.text();
|
||||||
|
mUrl = new URL(url);
|
||||||
|
} catch (MalformedURLException e) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create and show the dialog.
|
||||||
|
newFragment = NewsDetailImageDialogFragment.newInstanceUrl(text, mUrl.toString());
|
||||||
|
newFragment.show(ft, "menu_fragment_dialog");
|
||||||
|
break;
|
||||||
|
case WebView.HitTestResult.EMAIL_TYPE:
|
||||||
|
case WebView.HitTestResult.GEO_TYPE:
|
||||||
|
case WebView.HitTestResult.PHONE_TYPE:
|
||||||
|
case WebView.HitTestResult.EDIT_TEXT_TYPE:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true when the last page on the webview's history stack is
|
||||||
@SuppressLint("SimpleDateFormat")
|
* the original rss item page
|
||||||
public static String getHtmlPage(Context context, RssItem rssItem, boolean showHeader)
|
*/
|
||||||
{
|
private boolean isLastPageRssItem() {
|
||||||
String feedTitle = "Undefined";
|
WebBackForwardList list = mWebView.copyBackForwardList();
|
||||||
String favIconUrl = null;
|
WebHistoryItem lastItem = list.getItemAtIndex(list.getCurrentIndex() - 1);
|
||||||
|
return lastItem != null && lastItem.getUrl().equals(RSS_ITEM_PAGE_URL);
|
||||||
Feed feed = rssItem.getFeed();
|
|
||||||
int[] colors = ColorHelper.getColorsFromAttributes(context,
|
|
||||||
R.attr.dividerLineColor,
|
|
||||||
R.attr.rssItemListBackground);
|
|
||||||
int feedColor = colors[0];
|
|
||||||
if(feed != null) {
|
|
||||||
feedTitle = StringEscapeUtils.escapeHtml4(feed.getFeedTitle());
|
|
||||||
favIconUrl = feed.getFaviconUrl();
|
|
||||||
if(feed.getAvgColour() != null)
|
|
||||||
feedColor = Integer.parseInt(feed.getAvgColour());
|
|
||||||
}
|
|
||||||
|
|
||||||
if(favIconUrl != null)
|
|
||||||
{
|
|
||||||
DiskCache diskCache = ImageLoader.getInstance().getDiskCache();
|
|
||||||
File file = diskCache.get(favIconUrl);
|
|
||||||
if(file != null)
|
|
||||||
favIconUrl = "file://" + file.getAbsolutePath();
|
|
||||||
} else {
|
|
||||||
favIconUrl = "file:///android_res/drawable/default_feed_icon_light.png";
|
|
||||||
}
|
|
||||||
|
|
||||||
String body_id;
|
|
||||||
if(ThemeChooser.isDarkTheme(context)) {
|
|
||||||
body_id = "darkTheme";
|
|
||||||
} else {
|
|
||||||
body_id = "lightTheme";
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean isRightToLeft = context.getResources().getBoolean(R.bool.is_right_to_left);
|
|
||||||
String rtlClass = isRightToLeft ? "rtl" : "";
|
|
||||||
String borderSide = isRightToLeft ? "right" : "left";
|
|
||||||
|
|
||||||
StringBuilder builder = new StringBuilder();
|
|
||||||
|
|
||||||
builder.append("<html><head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=0\" />");
|
|
||||||
builder.append("<link rel=\"stylesheet\" type=\"text/css\" href=\"web.css\" />");
|
|
||||||
builder.append("<style type=\"text/css\">");
|
|
||||||
builder.append(String.format(
|
|
||||||
"#top_section { border-%s: 4px solid %s; border-bottom: 1px solid %s; background: %s }",
|
|
||||||
borderSide,
|
|
||||||
ColorHelper.getCssColor(feedColor),
|
|
||||||
ColorHelper.getCssColor(colors[0]),
|
|
||||||
ColorHelper.getCssColor(colors[1]))
|
|
||||||
);
|
|
||||||
builder.append("</style>");
|
|
||||||
builder.append(String.format("</head><body id=\"%s\" class=\"%s\">", body_id, rtlClass));
|
|
||||||
|
|
||||||
if(showHeader) {
|
|
||||||
builder.append("<div id=\"top_section\">");
|
|
||||||
builder.append("<div id=\"header\">");
|
|
||||||
String title = StringEscapeUtils.escapeHtml4(rssItem.getTitle());
|
|
||||||
String linkToFeed = StringEscapeUtils.escapeHtml4(rssItem.getLink());
|
|
||||||
builder.append(String.format("<a href=\"%s\">%s</a>", linkToFeed, title));
|
|
||||||
builder.append("</div>");
|
|
||||||
|
|
||||||
String authorOfArticle = StringEscapeUtils.escapeHtml4(rssItem.getAuthor());
|
|
||||||
if (authorOfArticle != null)
|
|
||||||
if (!authorOfArticle.trim().equals(""))
|
|
||||||
feedTitle += " - " + authorOfArticle.trim();
|
|
||||||
|
|
||||||
builder.append("<div id=\"header_small_text\">");
|
|
||||||
|
|
||||||
builder.append("<div id=\"subscription\">");
|
|
||||||
builder.append(String.format("<img id=\"imgFavicon\" src=\"%s\" />", favIconUrl));
|
|
||||||
builder.append(feedTitle.trim());
|
|
||||||
builder.append("</div>");
|
|
||||||
|
|
||||||
Date date = rssItem.getPubDate();
|
|
||||||
if (date != null) {
|
|
||||||
String dateString = (String) DateUtils.getRelativeTimeSpanString(date.getTime());
|
|
||||||
builder.append("<div id=\"datetime\">");
|
|
||||||
builder.append(dateString);
|
|
||||||
builder.append("</div>");
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.append("</div>");
|
|
||||||
|
|
||||||
builder.append("</div>");
|
|
||||||
}
|
|
||||||
|
|
||||||
String description = rssItem.getBody();
|
|
||||||
description = getDescriptionWithCachedImages(description).trim();
|
|
||||||
//StopWatch stopWatch = new StopWatch();
|
|
||||||
// stopWatch.start();
|
|
||||||
description = removePreloadAttributeFromVideos(description);
|
|
||||||
//stopWatch.stop();
|
|
||||||
//Log.d("NewsDetailFragment", "Time needed for removing preload attribute: " + stopWatch.toString() + " - " + feedTitle);
|
|
||||||
|
|
||||||
builder.append("<div id=\"content\">");
|
|
||||||
builder.append(description);
|
|
||||||
builder.append("</div>");
|
|
||||||
|
|
||||||
builder.append("</body></html>");
|
|
||||||
|
|
||||||
String htmlData = builder.toString().replaceAll("\"//", "\"https://");
|
|
||||||
|
|
||||||
return htmlData;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private static Pattern PATTERN_PRELOAD_VIDEOS = Pattern.compile("(<video[^>]*)(preload=\".*?\")");
|
|
||||||
private static String removePreloadAttributeFromVideos(String text) {
|
|
||||||
Matcher m = PATTERN_PRELOAD_VIDEOS.matcher(text);
|
|
||||||
if(m.find()) {
|
|
||||||
StringBuffer sb = new StringBuffer();
|
|
||||||
do {
|
|
||||||
//$1 represents the 1st group
|
|
||||||
m.appendReplacement(sb, "$1" + "preload=\"none\"");
|
|
||||||
} while (m.find());
|
|
||||||
m.appendTail(sb);
|
|
||||||
text = sb.toString();
|
|
||||||
}
|
|
||||||
return text;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getDescriptionWithCachedImages(String text)
|
/**
|
||||||
{
|
* @return true when the current page on the webview's history stack is
|
||||||
List<String> links = ImageHandler.getImageLinksFromText(text);
|
* the original rss item page
|
||||||
DiskCache diskCache = ImageLoader.getInstance().getDiskCache();
|
*/
|
||||||
|
private boolean isCurrentPageRssItem() {
|
||||||
for(String link : links)
|
String currentPageUrl = mWebView.copyBackForwardList().getCurrentItem().getOriginalUrl();
|
||||||
{
|
return currentPageUrl.equals("data:text/html;charset=utf-8;base64,");
|
||||||
link = link.trim();
|
//return currentPageUrl.equals(RSS_ITEM_PAGE_URL);
|
||||||
try
|
|
||||||
{
|
|
||||||
File file = diskCache.get(link);
|
|
||||||
if(file != null)
|
|
||||||
text = text.replace(link, "file://" + file.getAbsolutePath());
|
|
||||||
}
|
|
||||||
catch(Exception ex)
|
|
||||||
{
|
|
||||||
ex.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static String getTextFromAssets(String fileName, Context context) {
|
|
||||||
InputStream input;
|
|
||||||
try {
|
|
||||||
input = context.getAssets().open(fileName);
|
|
||||||
int size = input.available();
|
|
||||||
byte[] buffer = new byte[size];
|
|
||||||
input.read(buffer);
|
|
||||||
input.close();
|
|
||||||
|
|
||||||
// byte buffer into a string
|
|
||||||
return new String(buffer);
|
|
||||||
} catch(Exception ex) {
|
|
||||||
ex.printStackTrace();
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String SearchString(String data, String startString, String endString)
|
|
||||||
{
|
|
||||||
int start = data.indexOf(startString) + startString.length();
|
|
||||||
int end = data.indexOf(endString, start);
|
|
||||||
if(start != (-1 + startString.length()) && end != -1)
|
|
||||||
data = data.substring(start, end).trim();
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String convertHexColorFrom3To6Characters(String color)
|
|
||||||
{
|
|
||||||
for(int i = 1; i < 6; i += 2)
|
|
||||||
color = color.substring(0, i) + color.charAt(i) + color.substring(i);
|
|
||||||
|
|
||||||
return color;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -195,9 +195,9 @@ public class NewsDetailImageDialogFragment extends DialogFragment {
|
||||||
|
|
||||||
View v = inflater.inflate(R.layout.fragment_dialog_image, container, false);
|
View v = inflater.inflate(R.layout.fragment_dialog_image, container, false);
|
||||||
|
|
||||||
TextView tvTitle = (TextView) v.findViewById(R.id.ic_menu_title);
|
TextView tvTitle = v.findViewById(R.id.ic_menu_title);
|
||||||
TextView tvText = (TextView) v.findViewById(R.id.ic_menu_item_text);
|
TextView tvText = v.findViewById(R.id.ic_menu_item_text);
|
||||||
ImageView imgTitle = (ImageView) v.findViewById(R.id.ic_menu_gallery);
|
ImageView imgTitle = v.findViewById(R.id.ic_menu_gallery);
|
||||||
|
|
||||||
tvTitle.setText(mDialogTitle);
|
tvTitle.setText(mDialogTitle);
|
||||||
tvText.setText(mDialogText);
|
tvText.setText(mDialogText);
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
package de.luhmer.owncloudnewsreader.adapter;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
import android.webkit.ConsoleMessage;
|
||||||
|
import android.webkit.WebChromeClient;
|
||||||
|
import android.webkit.WebView;
|
||||||
|
import android.widget.ProgressBar;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A very simple WebChromeClient which sets the status of a given
|
||||||
|
* ProgressBar instance while loading. The ProgressBar instance will
|
||||||
|
* only be visible during loading.
|
||||||
|
*/
|
||||||
|
public class ProgressBarWebChromeClient extends WebChromeClient {
|
||||||
|
|
||||||
|
public final String TAG = getClass().getCanonicalName();
|
||||||
|
|
||||||
|
private ProgressBar mProgressBar;
|
||||||
|
|
||||||
|
public ProgressBarWebChromeClient(ProgressBar progressBar) {
|
||||||
|
mProgressBar = progressBar;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onConsoleMessage(ConsoleMessage cm) {
|
||||||
|
Log.v(TAG, cm.message() + " at " + cm.sourceId() + ":" + cm.lineNumber());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onProgressChanged(WebView view, int progress) {
|
||||||
|
mProgressBar.setProgress(progress);
|
||||||
|
|
||||||
|
if (progress < 100 && mProgressBar.getVisibility() == ProgressBar.GONE) {
|
||||||
|
mProgressBar.setVisibility(ProgressBar.VISIBLE);
|
||||||
|
} else if (progress == 100) {
|
||||||
|
mProgressBar.setVisibility(ProgressBar.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,9 +26,9 @@ import org.greenrobot.eventbus.Subscribe;
|
||||||
|
|
||||||
import butterknife.BindView;
|
import butterknife.BindView;
|
||||||
import butterknife.ButterKnife;
|
import butterknife.ButterKnife;
|
||||||
import de.luhmer.owncloudnewsreader.NewsDetailFragment;
|
|
||||||
import de.luhmer.owncloudnewsreader.R;
|
import de.luhmer.owncloudnewsreader.R;
|
||||||
import de.luhmer.owncloudnewsreader.SettingsActivity;
|
import de.luhmer.owncloudnewsreader.SettingsActivity;
|
||||||
|
import de.luhmer.owncloudnewsreader.async_tasks.RssItemToHtmlTask;
|
||||||
import de.luhmer.owncloudnewsreader.database.model.RssItem;
|
import de.luhmer.owncloudnewsreader.database.model.RssItem;
|
||||||
import de.luhmer.owncloudnewsreader.helper.ColorHelper;
|
import de.luhmer.owncloudnewsreader.helper.ColorHelper;
|
||||||
import de.luhmer.owncloudnewsreader.helper.FavIconHandler;
|
import de.luhmer.owncloudnewsreader.helper.FavIconHandler;
|
||||||
|
@ -243,7 +243,7 @@ public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickL
|
||||||
favIconHandler.loadFavIconForFeed(favIconUrl, imgViewFavIcon);
|
favIconHandler.loadFavIconForFeed(favIconUrl, imgViewFavIcon);
|
||||||
|
|
||||||
if(webView_body != null) {
|
if(webView_body != null) {
|
||||||
String htmlPage = NewsDetailFragment.getHtmlPage(itemView.getContext(),rssItem,false);
|
String htmlPage = RssItemToHtmlTask.getHtmlPage(itemView.getContext(), rssItem, false);
|
||||||
webView_body.loadDataWithBaseURL("file:///android_asset/", htmlPage, "text/html", "UTF-8", "");
|
webView_body.loadDataWithBaseURL("file:///android_asset/", htmlPage, "text/html", "UTF-8", "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,199 @@
|
||||||
|
package de.luhmer.owncloudnewsreader.async_tasks;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
import android.text.format.DateUtils;
|
||||||
|
|
||||||
|
import com.nostra13.universalimageloader.cache.disc.DiskCache;
|
||||||
|
import com.nostra13.universalimageloader.core.ImageLoader;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringEscapeUtils;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import de.luhmer.owncloudnewsreader.R;
|
||||||
|
import de.luhmer.owncloudnewsreader.database.model.Feed;
|
||||||
|
import de.luhmer.owncloudnewsreader.database.model.RssItem;
|
||||||
|
import de.luhmer.owncloudnewsreader.helper.ColorHelper;
|
||||||
|
import de.luhmer.owncloudnewsreader.helper.ImageHandler;
|
||||||
|
import de.luhmer.owncloudnewsreader.helper.ThemeChooser;
|
||||||
|
|
||||||
|
|
||||||
|
public class RssItemToHtmlTask extends AsyncTask<Void, Void, String> {
|
||||||
|
|
||||||
|
public interface Listener {
|
||||||
|
/**
|
||||||
|
* The RSS item has successfully been parsed.
|
||||||
|
* @param htmlPage RSS item as HTML string
|
||||||
|
*/
|
||||||
|
void onRssItemParsed(String htmlPage);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private Context mContext;
|
||||||
|
private RssItem mRssItem;
|
||||||
|
private Listener mListener;
|
||||||
|
|
||||||
|
|
||||||
|
public RssItemToHtmlTask(Context context, RssItem rssItem, Listener listener) {
|
||||||
|
this.mContext = context;
|
||||||
|
this.mRssItem = rssItem;
|
||||||
|
this.mListener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String doInBackground(Void... params) {
|
||||||
|
return getHtmlPage(mContext, mRssItem, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(String htmlPage) {
|
||||||
|
mListener.onRssItemParsed(htmlPage);
|
||||||
|
super.onPostExecute(htmlPage);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param context
|
||||||
|
* @param rssItem item to parse
|
||||||
|
* @param showHeader true if a header with item title, feed title, etc. should be included
|
||||||
|
* @return given RSS item as full HTML page
|
||||||
|
*/
|
||||||
|
public static String getHtmlPage(Context context, RssItem rssItem, boolean showHeader) {
|
||||||
|
String feedTitle = "Undefined";
|
||||||
|
String favIconUrl = null;
|
||||||
|
|
||||||
|
Feed feed = rssItem.getFeed();
|
||||||
|
int[] colors = ColorHelper.getColorsFromAttributes(context,
|
||||||
|
R.attr.dividerLineColor,
|
||||||
|
R.attr.rssItemListBackground);
|
||||||
|
|
||||||
|
int feedColor = colors[0];
|
||||||
|
if (feed != null) {
|
||||||
|
feedTitle = StringEscapeUtils.escapeHtml4(feed.getFeedTitle());
|
||||||
|
favIconUrl = feed.getFaviconUrl();
|
||||||
|
if(feed.getAvgColour() != null) {
|
||||||
|
feedColor = Integer.parseInt(feed.getAvgColour());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (favIconUrl != null) {
|
||||||
|
DiskCache diskCache = ImageLoader.getInstance().getDiskCache();
|
||||||
|
File file = diskCache.get(favIconUrl);
|
||||||
|
if(file != null) {
|
||||||
|
favIconUrl = "file://" + file.getAbsolutePath();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
favIconUrl = "file:///android_res/drawable/default_feed_icon_light.png";
|
||||||
|
}
|
||||||
|
|
||||||
|
String body_id;
|
||||||
|
if (ThemeChooser.isDarkTheme(context)) {
|
||||||
|
body_id = "darkTheme";
|
||||||
|
} else {
|
||||||
|
body_id = "lightTheme";
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isRightToLeft = context.getResources().getBoolean(R.bool.is_right_to_left);
|
||||||
|
String rtlClass = isRightToLeft ? "rtl" : "";
|
||||||
|
String borderSide = isRightToLeft ? "right" : "left";
|
||||||
|
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
|
||||||
|
builder.append("<html><head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=0\" />");
|
||||||
|
builder.append("<link rel=\"stylesheet\" type=\"text/css\" href=\"web.css\" />");
|
||||||
|
builder.append("<style type=\"text/css\">");
|
||||||
|
builder.append(String.format(
|
||||||
|
"#top_section { border-%s: 4px solid %s; border-bottom: 1px solid %s; background: %s }",
|
||||||
|
borderSide,
|
||||||
|
ColorHelper.getCssColor(feedColor),
|
||||||
|
ColorHelper.getCssColor(colors[0]),
|
||||||
|
ColorHelper.getCssColor(colors[1]))
|
||||||
|
);
|
||||||
|
builder.append("</style>");
|
||||||
|
builder.append(String.format("</head><body id=\"%s\" class=\"%s\">", body_id, rtlClass));
|
||||||
|
|
||||||
|
if (showHeader) {
|
||||||
|
builder.append("<div id=\"top_section\">");
|
||||||
|
builder.append("<div id=\"header\">");
|
||||||
|
String title = StringEscapeUtils.escapeHtml4(rssItem.getTitle());
|
||||||
|
String linkToFeed = StringEscapeUtils.escapeHtml4(rssItem.getLink());
|
||||||
|
builder.append(String.format("<a href=\"%s\">%s</a>", linkToFeed, title));
|
||||||
|
builder.append("</div>");
|
||||||
|
|
||||||
|
String authorOfArticle = StringEscapeUtils.escapeHtml4(rssItem.getAuthor());
|
||||||
|
if (authorOfArticle != null)
|
||||||
|
if (!authorOfArticle.trim().equals(""))
|
||||||
|
feedTitle += " - " + authorOfArticle.trim();
|
||||||
|
|
||||||
|
builder.append("<div id=\"header_small_text\">");
|
||||||
|
|
||||||
|
builder.append("<div id=\"subscription\">");
|
||||||
|
builder.append(String.format("<img id=\"imgFavicon\" src=\"%s\" />", favIconUrl));
|
||||||
|
builder.append(feedTitle.trim());
|
||||||
|
builder.append("</div>");
|
||||||
|
|
||||||
|
Date date = rssItem.getPubDate();
|
||||||
|
if (date != null) {
|
||||||
|
String dateString = (String) DateUtils.getRelativeTimeSpanString(date.getTime());
|
||||||
|
builder.append("<div id=\"datetime\">");
|
||||||
|
builder.append(dateString);
|
||||||
|
builder.append("</div>");
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.append("</div>");
|
||||||
|
|
||||||
|
builder.append("</div>");
|
||||||
|
}
|
||||||
|
|
||||||
|
String description = rssItem.getBody();
|
||||||
|
|
||||||
|
description = getDescriptionWithCachedImages(description).trim();
|
||||||
|
description = removePreloadAttributeFromVideos(description);
|
||||||
|
|
||||||
|
builder.append("<div id=\"content\">");
|
||||||
|
builder.append(description);
|
||||||
|
builder.append("</div>");
|
||||||
|
|
||||||
|
builder.append("</body></html>");
|
||||||
|
|
||||||
|
return builder.toString().replaceAll("\"//", "\"https://");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getDescriptionWithCachedImages(String text) {
|
||||||
|
List<String> links = ImageHandler.getImageLinksFromText(text);
|
||||||
|
DiskCache diskCache = ImageLoader.getInstance().getDiskCache();
|
||||||
|
|
||||||
|
for(String link : links) {
|
||||||
|
link = link.trim();
|
||||||
|
try {
|
||||||
|
File file = diskCache.get(link);
|
||||||
|
if(file != null)
|
||||||
|
text = text.replace(link, "file://" + file.getAbsolutePath());
|
||||||
|
} catch(Exception ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Pattern PATTERN_PRELOAD_VIDEOS = Pattern.compile("(<video[^>]*)(preload=\".*?\")");
|
||||||
|
private static String removePreloadAttributeFromVideos(String text) {
|
||||||
|
Matcher m = PATTERN_PRELOAD_VIDEOS.matcher(text);
|
||||||
|
if(m.find()) {
|
||||||
|
StringBuffer sb = new StringBuffer();
|
||||||
|
do {
|
||||||
|
//$1 represents the 1st group
|
||||||
|
m.appendReplacement(sb, "$1" + "preload=\"none\"");
|
||||||
|
} while (m.find());
|
||||||
|
m.appendTail(sb);
|
||||||
|
text = sb.toString();
|
||||||
|
}
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,6 +22,7 @@
|
||||||
package de.luhmer.owncloudnewsreader.helper;
|
package de.luhmer.owncloudnewsreader.helper;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.os.Environment;
|
||||||
|
|
||||||
import com.nostra13.universalimageloader.utils.StorageUtils;
|
import com.nostra13.universalimageloader.utils.StorageUtils;
|
||||||
|
|
||||||
|
@ -87,4 +88,9 @@ public class FileUtils {
|
||||||
{
|
{
|
||||||
return getPath(context) + "/podcasts";
|
return getPath(context) + "/podcasts";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isExternalStorageWritable() {
|
||||||
|
String state = Environment.getExternalStorageState();
|
||||||
|
return Environment.MEDIA_MOUNTED.equals(state);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue