first working implementation of incognito mode

This commit is contained in:
David Luhmer 2019-09-26 21:55:06 +02:00
parent 09550b2532
commit 227b149ff4
7 changed files with 162 additions and 35 deletions

View file

@ -53,16 +53,13 @@ body#darkTheme a:visited {
} }
*/ */
body, blockquote, img, iframe, video, div, table, tbody, tr, td, pre, code, blockquote, p, em, b { body, blockquote, img, iframe, video, div, table, tbody, tr, td, pre, code, blockquote, p, em, b, span {
width: auto !important; width: auto !important;
height: auto !important; height: auto !important;
max-width: 100% !important; max-width: 100% !important;
} }
span { span {
width: auto !important;
height: auto !important;
max-width: 100% !important;
display: block; display: block;
} }

View file

@ -26,7 +26,9 @@ import android.content.SharedPreferences;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo; import android.content.pm.ResolveInfo;
import android.net.Uri; import android.net.Uri;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.PersistableBundle;
import android.text.Html; import android.text.Html;
import android.util.Log; import android.util.Log;
import android.util.SparseArray; import android.util.SparseArray;
@ -34,8 +36,11 @@ import android.view.KeyEvent;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.webkit.WebView;
import android.widget.ImageButton;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.Toolbar; import androidx.appcompat.widget.Toolbar;
import androidx.browser.customtabs.CustomTabsIntent; import androidx.browser.customtabs.CustomTabsIntent;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
@ -58,6 +63,7 @@ import butterknife.ButterKnife;
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;
import de.luhmer.owncloudnewsreader.helper.ThemeUtils;
import de.luhmer.owncloudnewsreader.model.PodcastItem; import de.luhmer.owncloudnewsreader.model.PodcastItem;
import de.luhmer.owncloudnewsreader.model.TTSItem; import de.luhmer.owncloudnewsreader.model.TTSItem;
import de.luhmer.owncloudnewsreader.widget.WidgetProvider; import de.luhmer.owncloudnewsreader.widget.WidgetProvider;
@ -65,6 +71,7 @@ import de.luhmer.owncloudnewsreader.widget.WidgetProvider;
public class NewsDetailActivity extends PodcastFragmentActivity { public class NewsDetailActivity extends PodcastFragmentActivity {
private static final String TAG = NewsDetailActivity.class.getCanonicalName(); private static final String TAG = NewsDetailActivity.class.getCanonicalName();
public static final String INCOGNITO_MODE_ENABLED = "INCOGNITO_MODE_ENABLED";
/** /**
* The {@link PagerAdapter} that will provide * The {@link PagerAdapter} that will provide
* fragments for each of the sections. We use a * fragments for each of the sections. We use a
@ -76,6 +83,7 @@ public class NewsDetailActivity extends PodcastFragmentActivity {
private SectionsPagerAdapter mSectionsPagerAdapter; private SectionsPagerAdapter mSectionsPagerAdapter;
protected @BindView(R.id.toolbar) Toolbar toolbar; protected @BindView(R.id.toolbar) Toolbar toolbar;
protected @BindView(R.id.progressIndicator) ProgressBar progressIndicator; protected @BindView(R.id.progressIndicator) ProgressBar progressIndicator;
protected @BindView(R.id.btn_disable_incognito) ImageButton mBtnDisableIncognito;
/** /**
* The {@link ViewPager} that will host the section contents. * The {@link ViewPager} that will host the section contents.
@ -101,7 +109,14 @@ public class NewsDetailActivity extends PodcastFragmentActivity {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.activity_news_detail); setContentView(R.layout.activity_news_detail);
ButterKnife.bind(this); /*
// For Debugging the WebView using Chrome Remote Debugging
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
WebView.setWebContentsDebuggingEnabled(true);
}
*/
ButterKnife.bind(this);
if (toolbar != null) { if (toolbar != null) {
setSupportActionBar(toolbar); setSupportActionBar(toolbar);
@ -170,7 +185,21 @@ public class NewsDetailActivity extends PodcastFragmentActivity {
} }
mViewPager.addOnPageChangeListener(onPageChangeListener); mViewPager.addOnPageChangeListener(onPageChangeListener);
}
mBtnDisableIncognito.setOnClickListener(v -> {
// toggle incognito mode
setIncognitoEnabled(!isIncognitoEnabled());
for(int i = currentPosition-1; i <= currentPosition+1; i++) {
Log.d(TAG, "change incognito for idx: " + i);
WeakReference<NewsDetailFragment> ndf = mSectionsPagerAdapter.items.get(i);
if(ndf != null) {
ndf.get().syncIncognitoState();
ndf.get().startLoadRssItemToWebViewTask();
}
}
});
}
@Override @Override
protected void onDestroy() { protected void onDestroy() {
@ -337,7 +366,7 @@ public class NewsDetailActivity extends PodcastFragmentActivity {
menuItem_Read = menu.findItem(R.id.action_read); menuItem_Read = menu.findItem(R.id.action_read);
menuItem_PlayPodcast = menu.findItem(R.id.action_playPodcast); menuItem_PlayPodcast = menu.findItem(R.id.action_playPodcast);
Set<String> selections = mPrefs.getStringSet("sp_news_detail_actionbar_icons", new HashSet<String>()); Set<String> selections = mPrefs.getStringSet("sp_news_detail_actionbar_icons", new HashSet<>());
String[] selected = selections.toArray(new String[] {}); String[] selected = selections.toArray(new String[] {});
for(String selection : selected) { for(String selection : selected) {
switch(selection) { switch(selection) {
@ -358,6 +387,8 @@ public class NewsDetailActivity extends PodcastFragmentActivity {
updateActionBarIcons(); updateActionBarIcons();
initIncognitoMode();
return true; return true;
} }
@ -510,6 +541,21 @@ public class NewsDetailActivity extends PodcastFragmentActivity {
super.finish(); super.finish();
} }
public boolean isIncognitoEnabled() {
return mPrefs.getBoolean(INCOGNITO_MODE_ENABLED, false);
}
public void setIncognitoEnabled(boolean enabled) {
mPrefs.edit().putBoolean(INCOGNITO_MODE_ENABLED, enabled).commit();
initIncognitoMode();
}
public void initIncognitoMode() {
int color = getResources().getColor(isIncognitoEnabled() ? R.color.material_grey_900 : R.color.colorPrimary);
ThemeUtils.colorizeToolbar(toolbar, color);
ThemeUtils.changeStatusBarColor(this, color);
}
/** /**
* A {@link FragmentPagerAdapter} that returns a fragment corresponding to * A {@link FragmentPagerAdapter} that returns a fragment corresponding to
* one of the sections/tabs/pages. * one of the sections/tabs/pages.

View file

@ -42,6 +42,7 @@ import android.webkit.WebSettings;
import android.webkit.WebView; import android.webkit.WebView;
import android.webkit.WebViewClient; import android.webkit.WebViewClient;
import android.widget.Button; import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import android.widget.TextView; import android.widget.TextView;
@ -85,8 +86,6 @@ public class NewsDetailFragment extends Fragment implements RssItemToHtmlTask.Li
protected @BindView(R.id.progressBarLoading) ProgressBar mProgressBarLoading; protected @BindView(R.id.progressBarLoading) ProgressBar mProgressBarLoading;
protected @BindView(R.id.progressbar_webview) ProgressBar mProgressbarWebView; protected @BindView(R.id.progressbar_webview) ProgressBar mProgressbarWebView;
protected @BindView(R.id.tv_offline_version) TextView mTvOfflineVersion; protected @BindView(R.id.tv_offline_version) TextView mTvOfflineVersion;
protected @BindView(R.id.btn_disable_incognito) Button mBtnDisableIncognito;
protected @Inject SharedPreferences mPrefs; protected @Inject SharedPreferences mPrefs;
@ -183,19 +182,24 @@ public class NewsDetailFragment extends Fragment implements RssItemToHtmlTask.Li
} else { } else {
mWebView.restoreState(savedInstanceState); mWebView.restoreState(savedInstanceState);
mProgressBarLoading.setVisibility(View.GONE); mProgressBarLoading.setVisibility(View.GONE);
// Make sure to sync the incognitio on retained views
syncIncognitoState();
} }
setUpGestureDetector(); setUpGestureDetector();
mBtnDisableIncognito.setOnClickListener(v -> {
mWebView.getSettings().setBlockNetworkLoads(false);
mWebView.getSettings().setBlockNetworkImage(false);
mWebView.reload();
});
return rootView; return rootView;
} }
void syncIncognitoState() {
NewsDetailActivity ndActivity = ((NewsDetailActivity)getActivity());
boolean isIncognito = ndActivity.isIncognitoEnabled();
mWebView.getSettings().setBlockNetworkLoads(isIncognito);
mWebView.getSettings().setBlockNetworkImage(isIncognito);
}
@Override @Override
public void onSaveInstanceState(Bundle outState) { public void onSaveInstanceState(Bundle outState) {
mWebView.saveState(outState); mWebView.saveState(outState);
@ -233,7 +237,7 @@ public class NewsDetailFragment extends Fragment implements RssItemToHtmlTask.Li
}); });
} }
private void startLoadRssItemToWebViewTask() { void startLoadRssItemToWebViewTask() {
Log.d(TAG, "startLoadRssItemToWebViewTask() called"); Log.d(TAG, "startLoadRssItemToWebViewTask() called");
mWebView.setVisibility(View.GONE); mWebView.setVisibility(View.GONE);
mProgressBarLoading.setVisibility(View.VISIBLE); mProgressBarLoading.setVisibility(View.VISIBLE);
@ -304,11 +308,7 @@ public class NewsDetailFragment extends Fragment implements RssItemToHtmlTask.Li
webSettings.setAppCacheEnabled(true); webSettings.setAppCacheEnabled(true);
webSettings.setMediaPlaybackRequiresUserGesture(true); webSettings.setMediaPlaybackRequiresUserGesture(true);
//if(true) { syncIncognitoState();
//webSettings.setLoadsImagesAutomatically(false);
webSettings.setBlockNetworkImage(true);
webSettings.setBlockNetworkLoads(true);
//}
registerForContextMenu(mWebView); registerForContextMenu(mWebView);
@ -411,7 +411,7 @@ public class NewsDetailFragment extends Fragment implements RssItemToHtmlTask.Li
String imgaltval; String imgaltval;
String imgsrcval; String imgsrcval;
imgsrcval = imageUrl.substring(imageUrl.lastIndexOf('/') + 1, imageUrl.length()); imgsrcval = imageUrl.substring(imageUrl.lastIndexOf('/') + 1);
Elements imgtag = htmlDoc.getElementsByAttributeValueContaining("src", imageUrl); Elements imgtag = htmlDoc.getElementsByAttributeValueContaining("src", imageUrl);
try { try {

View file

@ -24,6 +24,7 @@ import de.luhmer.owncloudnewsreader.database.model.RssItem;
import de.luhmer.owncloudnewsreader.helper.ImageHandler; import de.luhmer.owncloudnewsreader.helper.ImageHandler;
import de.luhmer.owncloudnewsreader.helper.ThemeChooser; import de.luhmer.owncloudnewsreader.helper.ThemeChooser;
import static de.luhmer.owncloudnewsreader.NewsDetailActivity.INCOGNITO_MODE_ENABLED;
import static de.luhmer.owncloudnewsreader.helper.ThemeChooser.THEME; import static de.luhmer.owncloudnewsreader.helper.ThemeChooser.THEME;
@ -84,6 +85,8 @@ public class RssItemToHtmlTask extends AsyncTask<Void, Void, String> {
* @return given RSS item as full HTML page * @return given RSS item as full HTML page
*/ */
public static String getHtmlPage(RssItem rssItem, boolean showHeader, SharedPreferences mPrefs, boolean isRightToLeft) { public static String getHtmlPage(RssItem rssItem, boolean showHeader, SharedPreferences mPrefs, boolean isRightToLeft) {
boolean incognitoMode = mPrefs.getBoolean(INCOGNITO_MODE_ENABLED, false);
String favIconUrl = null; String favIconUrl = null;
Feed feed = rssItem.getFeed(); Feed feed = rssItem.getFeed();
@ -122,7 +125,14 @@ public class RssItemToHtmlTask extends AsyncTask<Void, Void, String> {
} }
String description = rssItem.getBody(); String description = rssItem.getBody();
description = getDescriptionWithCachedImages(description).trim(); if(!incognitoMode) {
// If incognito mode is disabled, try getting images from cache
description = getDescriptionWithCachedImages(description).trim();
} else {
// When incognito is on, we need to provide some error handling
//description = description.replaceAll("<img", "<img onerror=\"this.style='width: 40px !important; height: 40px !important'\" ");
description = description.replaceAll("<img", "<img width=\"40px\" height=\"40px\" ");
}
description = replacePatternInText(PATTERN_PRELOAD_VIDEOS_REMOVE, description, "$1 $3"); // remove whatever preload is there description = replacePatternInText(PATTERN_PRELOAD_VIDEOS_REMOVE, description, "$1 $3"); // remove whatever preload is there
description = replacePatternInText(PATTERN_PRELOAD_VIDEOS_INSERT, description, "$1 preload=\"metadata\" $3"); // add preload attribute description = replacePatternInText(PATTERN_PRELOAD_VIDEOS_INSERT, description, "$1 preload=\"metadata\" $3"); // add preload attribute
description = replacePatternInText(PATTERN_AUTOPLAY_VIDEOS_1, description, "$1 $3"); description = replacePatternInText(PATTERN_AUTOPLAY_VIDEOS_1, description, "$1 $3");

View file

@ -1,14 +1,43 @@
/**
* Android ownCloud News
*
* @author David Luhmer
* @copyright 2019 David Luhmer david-dev@live.de
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library 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 AFFERO GENERAL PUBLIC LICENSE for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*/
package de.luhmer.owncloudnewsreader.helper; package de.luhmer.owncloudnewsreader.helper;
import android.app.Activity;
import android.graphics.Color;
import android.graphics.PorterDuff; import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.Build;
import android.util.Log; import android.util.Log;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.SearchView; import android.widget.SearchView;
import android.widget.TextView; import android.widget.TextView;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import androidx.annotation.ColorInt; import androidx.annotation.ColorInt;
import androidx.appcompat.widget.ActionMenuView;
import androidx.appcompat.widget.Toolbar;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import de.luhmer.owncloudnewsreader.R; import de.luhmer.owncloudnewsreader.R;
@ -67,4 +96,42 @@ public class ThemeUtils {
} }
} }
/**
* Use this method to colorize the toolbar to the desired target color
* @param toolbarView toolbar view being colored
* @param toolbarBackgroundColor the target background color
*/
public static void colorizeToolbar(Toolbar toolbarView, @ColorInt int toolbarBackgroundColor) {
toolbarView.setBackgroundColor(toolbarBackgroundColor);
for(int i = 0; i < toolbarView.getChildCount(); i++) {
final View v = toolbarView.getChildAt(i);
v.setBackgroundColor(toolbarBackgroundColor);
if(v instanceof ActionMenuView) {
for(int j = 0; j < ((ActionMenuView)v).getChildCount(); j++) {
v.setBackgroundColor(toolbarBackgroundColor);
}
}
}
}
/**
* Use this method to colorize the status bar to the desired target color
* @param activity
* @param statusBarColor
*/
public static void changeStatusBarColor(Activity activity, @ColorInt int statusBarColor) {
Window window = activity.getWindow();
// clear FLAG_TRANSLUCENT_STATUS flag:
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
// add FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS flag to the window
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
window.setStatusBarColor(statusBarColor);
}
}
} }

View file

@ -1,8 +1,8 @@
<androidx.coordinatorlayout.widget.CoordinatorLayout <androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_width="match_parent"> android:layout_width="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<!-- SlidingUpPanelLayout doesn't work with layout_behavior, use marginTop --> <!-- SlidingUpPanelLayout doesn't work with layout_behavior, use marginTop -->
<de.luhmer.owncloudnewsreader.view.PodcastSlidingUpPanelLayout <de.luhmer.owncloudnewsreader.view.PodcastSlidingUpPanelLayout
@ -48,6 +48,21 @@
</de.luhmer.owncloudnewsreader.view.PodcastSlidingUpPanelLayout> </de.luhmer.owncloudnewsreader.view.PodcastSlidingUpPanelLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center"
android:layout_marginBottom="16dp">
<ImageButton
android:id="@+id/btn_disable_incognito"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="@drawable/incognito"/>
</LinearLayout>
<include <include
android:id="@+id/toolbar_layout" android:id="@+id/toolbar_layout"
layout="@layout/toolbar_layout" /> layout="@layout/toolbar_layout" />

View file

@ -1,10 +1,10 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
tools:context=".NewsDetailFragment" > tools:context=".NewsDetailFragment" >
<WebView <WebView
android:id="@+id/webview" android:id="@+id/webview"
android:layout_width="match_parent" android:layout_width="match_parent"
@ -42,12 +42,4 @@
android:background="@color/material_red_600" android:background="@color/material_red_600"
android:visibility="gone" /> android:visibility="gone" />
<Button
android:id="@+id/btn_disable_incognito"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Disable Incognito"
android:layout_alignParentBottom="true" />
</RelativeLayout> </RelativeLayout>