diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/activities/BaseMainActivity.java b/app/src/main/java/fr/gouv/etalab/mastodon/activities/BaseMainActivity.java index 500408b90..8806e3a19 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/activities/BaseMainActivity.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/activities/BaseMainActivity.java @@ -496,87 +496,88 @@ public abstract class BaseMainActivity extends BaseActivity } //Display filter for notification when long pressing the tab final LinearLayout tabStrip = (LinearLayout) tabLayout.getChildAt(0); - tabStrip.getChildAt(1).setOnLongClickListener(new View.OnLongClickListener() { - @Override - public boolean onLongClick(View v) { - //Only shown if the tab has focus - if( tabLayoutNotificationsFragment != null && tabLayoutNotificationsFragment.getUserVisibleHint()){ - PopupMenu popup = new PopupMenu(BaseMainActivity.this, tabStrip.getChildAt(1)); - popup.getMenuInflater() - .inflate(R.menu.option_filter_notifications, popup.getMenu()); - Menu menu = popup.getMenu(); - final MenuItem itemFavourite = menu.findItem(R.id.action_favorite); - final MenuItem itemFollow = menu.findItem(R.id.action_follow); - final MenuItem itemMention = menu.findItem(R.id.action_mention); - final MenuItem itemBoost = menu.findItem(R.id.action_boost); - notif_follow = sharedpreferences.getBoolean(Helper.SET_NOTIF_FOLLOW_FILTER, true); - notif_add = sharedpreferences.getBoolean(Helper.SET_NOTIF_ADD_FILTER, true); - notif_mention = sharedpreferences.getBoolean(Helper.SET_NOTIF_MENTION_FILTER, true); - notif_share = sharedpreferences.getBoolean(Helper.SET_NOTIF_SHARE_FILTER, true); - itemFavourite.setChecked(notif_add); - itemFollow.setChecked(notif_follow); - itemMention.setChecked(notif_mention); - itemBoost.setChecked(notif_share); - popup.setOnDismissListener(new PopupMenu.OnDismissListener() { - @Override - public void onDismiss(PopupMenu menu) { - if( tabLayoutNotificationsFragment != null) - tabLayoutNotificationsFragment.refreshAll(); - } - }); - popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { - public boolean onMenuItemClick(MenuItem item) { - item.setShowAsAction(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW); - item.setActionView(new View(getApplicationContext())); - item.setOnActionExpandListener(new MenuItem.OnActionExpandListener() { - @Override - public boolean onMenuItemActionExpand(MenuItem item) { - return false; - } - - @Override - public boolean onMenuItemActionCollapse(MenuItem item) { - return false; - } - }); - switch (item.getItemId()) { - case R.id.action_favorite: - SharedPreferences.Editor editor = sharedpreferences.edit(); - notif_add = !notif_add; - editor.putBoolean(Helper.SET_NOTIF_ADD_FILTER, notif_add); - itemFavourite.setChecked(notif_add); - editor.apply(); - break; - case R.id.action_follow: - editor = sharedpreferences.edit(); - notif_follow = !notif_follow; - editor.putBoolean(Helper.SET_NOTIF_FOLLOW_FILTER, notif_follow); - itemFollow.setChecked(notif_follow); - editor.apply(); - break; - case R.id.action_mention: - editor = sharedpreferences.edit(); - notif_mention = !notif_mention; - editor.putBoolean(Helper.SET_NOTIF_MENTION_FILTER, notif_mention); - itemMention.setChecked(notif_mention); - editor.apply(); - break; - case R.id.action_boost: - editor = sharedpreferences.edit(); - notif_share = !notif_share; - editor.putBoolean(Helper.SET_NOTIF_SHARE_FILTER, notif_share); - itemBoost.setChecked(notif_share); - editor.apply(); - break; + if( social == UpdateAccountInfoAsyncTask.SOCIAL.MASTODON || social == UpdateAccountInfoAsyncTask.SOCIAL.PLEROMA ) + tabStrip.getChildAt(1).setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + //Only shown if the tab has focus + if( tabLayoutNotificationsFragment != null && tabLayoutNotificationsFragment.getUserVisibleHint()){ + PopupMenu popup = new PopupMenu(BaseMainActivity.this, tabStrip.getChildAt(1)); + popup.getMenuInflater() + .inflate(R.menu.option_filter_notifications, popup.getMenu()); + Menu menu = popup.getMenu(); + final MenuItem itemFavourite = menu.findItem(R.id.action_favorite); + final MenuItem itemFollow = menu.findItem(R.id.action_follow); + final MenuItem itemMention = menu.findItem(R.id.action_mention); + final MenuItem itemBoost = menu.findItem(R.id.action_boost); + notif_follow = sharedpreferences.getBoolean(Helper.SET_NOTIF_FOLLOW_FILTER, true); + notif_add = sharedpreferences.getBoolean(Helper.SET_NOTIF_ADD_FILTER, true); + notif_mention = sharedpreferences.getBoolean(Helper.SET_NOTIF_MENTION_FILTER, true); + notif_share = sharedpreferences.getBoolean(Helper.SET_NOTIF_SHARE_FILTER, true); + itemFavourite.setChecked(notif_add); + itemFollow.setChecked(notif_follow); + itemMention.setChecked(notif_mention); + itemBoost.setChecked(notif_share); + popup.setOnDismissListener(new PopupMenu.OnDismissListener() { + @Override + public void onDismiss(PopupMenu menu) { + if( tabLayoutNotificationsFragment != null) + tabLayoutNotificationsFragment.refreshAll(); } - return false; - } - }); - popup.show(); + }); + popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { + public boolean onMenuItemClick(MenuItem item) { + item.setShowAsAction(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW); + item.setActionView(new View(getApplicationContext())); + item.setOnActionExpandListener(new MenuItem.OnActionExpandListener() { + @Override + public boolean onMenuItemActionExpand(MenuItem item) { + return false; + } + + @Override + public boolean onMenuItemActionCollapse(MenuItem item) { + return false; + } + }); + switch (item.getItemId()) { + case R.id.action_favorite: + SharedPreferences.Editor editor = sharedpreferences.edit(); + notif_add = !notif_add; + editor.putBoolean(Helper.SET_NOTIF_ADD_FILTER, notif_add); + itemFavourite.setChecked(notif_add); + editor.apply(); + break; + case R.id.action_follow: + editor = sharedpreferences.edit(); + notif_follow = !notif_follow; + editor.putBoolean(Helper.SET_NOTIF_FOLLOW_FILTER, notif_follow); + itemFollow.setChecked(notif_follow); + editor.apply(); + break; + case R.id.action_mention: + editor = sharedpreferences.edit(); + notif_mention = !notif_mention; + editor.putBoolean(Helper.SET_NOTIF_MENTION_FILTER, notif_mention); + itemMention.setChecked(notif_mention); + editor.apply(); + break; + case R.id.action_boost: + editor = sharedpreferences.edit(); + notif_share = !notif_share; + editor.putBoolean(Helper.SET_NOTIF_SHARE_FILTER, notif_share); + itemBoost.setChecked(notif_share); + editor.apply(); + break; + } + return false; + } + }); + popup.show(); + } + return true; } - return true; - } - }); + }); tabStrip.getChildAt(0).setOnLongClickListener(new View.OnLongClickListener() { diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/activities/WebviewActivity.java b/app/src/main/java/fr/gouv/etalab/mastodon/activities/WebviewActivity.java index b0d938643..6a6670ba2 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/activities/WebviewActivity.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/activities/WebviewActivity.java @@ -17,10 +17,13 @@ package fr.gouv.etalab.mastodon.activities; import android.Manifest; import android.content.Context; +import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.database.sqlite.SQLiteDatabase; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.LayerDrawable; import android.net.Uri; import android.os.AsyncTask; import android.os.Build; @@ -28,6 +31,7 @@ import android.os.Bundle; import android.os.Handler; import android.support.v4.app.ActivityCompat; import android.support.v4.content.ContextCompat; +import android.support.v7.app.AlertDialog; import android.view.Menu; import android.view.MenuItem; import android.view.View; @@ -35,6 +39,7 @@ import android.view.ViewGroup; import android.view.WindowManager; import android.webkit.DownloadListener; import android.webkit.WebView; +import android.widget.ArrayAdapter; import android.widget.FrameLayout; import android.widget.Toast; @@ -46,6 +51,7 @@ import es.dmoral.toasty.Toasty; import fr.gouv.etalab.mastodon.R; import fr.gouv.etalab.mastodon.client.API; import fr.gouv.etalab.mastodon.client.Entities.Results; +import fr.gouv.etalab.mastodon.helper.CountDrawable; import fr.gouv.etalab.mastodon.helper.Helper; import fr.gouv.etalab.mastodon.sqlite.DomainBlockDAO; import fr.gouv.etalab.mastodon.sqlite.Sqlite; @@ -69,6 +75,8 @@ public class WebviewActivity extends BaseActivity { private boolean peertubeLink; private WebView webView; public static List trackingDomains; + private Menu defaultMenu; + private MastalabWebViewClient mastalabWebViewClient; @Override protected void onCreate(Bundle savedInstanceState) { @@ -130,7 +138,8 @@ public class WebviewActivity extends BaseActivity { } }); webView.setWebChromeClient(mastalabWebChromeClient); - webView.setWebViewClient(new MastalabWebViewClient(WebviewActivity.this)); + mastalabWebViewClient = new MastalabWebViewClient(WebviewActivity.this); + webView.setWebViewClient(mastalabWebViewClient); webView.setDownloadListener(new DownloadListener() { @Override public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) { @@ -172,11 +181,42 @@ public class WebviewActivity extends BaseActivity { webView.loadUrl(url); } + + public void setCount(Context context, String count) { + if( defaultMenu != null) { + MenuItem menuItem = defaultMenu.findItem(R.id.action_block); + LayerDrawable icon = (LayerDrawable) menuItem.getIcon(); + + CountDrawable badge; + + // Reuse drawable if possible + Drawable reuse = icon.findDrawableByLayerId(R.id.ic_block_count); + if (reuse instanceof CountDrawable) { + badge = (CountDrawable) reuse; + } else { + badge = new CountDrawable(context); + } + + badge.setCount(count); + icon.mutate(); + icon.setDrawableByLayerId(R.id.ic_block_count, badge); + } + } + + @Override + public boolean onPrepareOptionsMenu(Menu menu) { + setCount(this, "0"); + defaultMenu = menu; + return super.onPrepareOptionsMenu(menu); + } + @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main_webview, menu); + defaultMenu = menu; if( peertubeLink ){ menu.findItem(R.id.action_go).setVisible(false); + menu.findItem(R.id.action_block).setVisible(false); menu.findItem(R.id.action_comment).setVisible(true); } SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, android.content.Context.MODE_PRIVATE); @@ -190,6 +230,44 @@ public class WebviewActivity extends BaseActivity { switch (item.getItemId()) { case android.R.id.home: finish(); + return true; + case R.id.action_block: + SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, android.content.Context.MODE_PRIVATE); + final int theme = sharedpreferences.getInt(Helper.SET_THEME, Helper.THEME_DARK); + + List domains = mastalabWebViewClient.getDomains(); + + final ArrayAdapter arrayAdapter = new ArrayAdapter<>(WebviewActivity.this, R.layout.domains_blocked); + for (String domain: domains) + arrayAdapter.add(domain); + int style; + if (theme == Helper.THEME_DARK) { + style = R.style.DialogDark; + } else if (theme == Helper.THEME_BLACK){ + style = R.style.DialogBlack; + }else { + style = R.style.Dialog; + } + AlertDialog.Builder builder = new AlertDialog.Builder(WebviewActivity.this, style); + builder.setTitle(R.string.list_of_blocked_domains); + + builder.setNegativeButton(R.string.close, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + dialog.dismiss(); + } + }); + + builder.setAdapter(arrayAdapter, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + String strName = arrayAdapter.getItem(which); + assert strName != null; + Toasty.info(WebviewActivity.this, strName, Toast.LENGTH_LONG).show(); + } + }); + builder.show(); + return true; case R.id.action_go: Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/helper/CountDrawable.java b/app/src/main/java/fr/gouv/etalab/mastodon/helper/CountDrawable.java new file mode 100644 index 000000000..8835dac49 --- /dev/null +++ b/app/src/main/java/fr/gouv/etalab/mastodon/helper/CountDrawable.java @@ -0,0 +1,103 @@ +package fr.gouv.etalab.mastodon.helper; + + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.ColorFilter; +import android.graphics.Paint; +import android.graphics.PixelFormat; +import android.graphics.Rect; +import android.graphics.Typeface; +import android.graphics.drawable.Drawable; +import android.support.annotation.NonNull; +import android.support.v4.content.ContextCompat; + +import fr.gouv.etalab.mastodon.R; + + +public class CountDrawable extends Drawable { + + private Paint mBadgePaint; + private Paint mTextPaint; + private Rect mTxtRect = new Rect(); + + private String mCount = ""; + private boolean mWillDraw; + + public CountDrawable(Context context) { + float mTextSize = context.getResources().getDimension(R.dimen.badge_count_textsize); + + mBadgePaint = new Paint(); + mBadgePaint.setColor(ContextCompat.getColor(context.getApplicationContext(), R.color.red_1)); + mBadgePaint.setAntiAlias(true); + mBadgePaint.setStyle(Paint.Style.FILL); + + mTextPaint = new Paint(); + mTextPaint.setColor(Color.WHITE); + mTextPaint.setTypeface(Typeface.DEFAULT); + mTextPaint.setTextSize(mTextSize); + mTextPaint.setAntiAlias(true); + mTextPaint.setTextAlign(Paint.Align.CENTER); + } + + @Override + public void draw(@NonNull Canvas canvas) { + + if (!mWillDraw) { + return; + } + Rect bounds = getBounds(); + float width = bounds.right - bounds.left; + float height = bounds.bottom - bounds.top; + + // Position the badge in the top-right quadrant of the icon. + + /*Using Math.max rather than Math.min */ + + float radius = ((Math.max(width, height) / 2)) / 2; + float centerX = (width - radius - 1) +5; + float centerY = radius -5; + if(mCount.length() <= 2){ + // Draw badge circle. + canvas.drawCircle(centerX, centerY, (int)(radius+5.5), mBadgePaint); + } + else{ + canvas.drawCircle(centerX, centerY, (int)(radius+6.5), mBadgePaint); + } + // Draw badge count text inside the circle. + mTextPaint.getTextBounds(mCount, 0, mCount.length(), mTxtRect); + float textHeight = mTxtRect.bottom - mTxtRect.top; + float textY = centerY + (textHeight / 2f); + if(mCount.length() > 2) + canvas.drawText("99+", centerX, textY, mTextPaint); + else + canvas.drawText(mCount, centerX, textY, mTextPaint); + } + + /* + Sets the count (i.e notifications) to display. + */ + public void setCount(String count) { + mCount = count; + + // Only draw a badge if there are notifications. + mWillDraw = !count.equalsIgnoreCase("0"); + invalidateSelf(); + } + + @Override + public void setAlpha(int alpha) { + // do nothing + } + + @Override + public void setColorFilter(ColorFilter cf) { + // do nothing + } + + @Override + public int getOpacity() { + return PixelFormat.UNKNOWN; + } +} diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/sqlite/DomainBlockDAO.java b/app/src/main/java/fr/gouv/etalab/mastodon/sqlite/DomainBlockDAO.java index b4ea155d5..ecd3b5b79 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/sqlite/DomainBlockDAO.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/sqlite/DomainBlockDAO.java @@ -62,6 +62,14 @@ public class DomainBlockDAO { insert(domain); } + + public int getTotalCount(){ + Cursor mCount= db.rawQuery("SELECT Count(*) FROM " + Sqlite.TABLE_TRACKING_BLOCK, null); + mCount.moveToFirst(); + int count = mCount.getInt(0); + mCount.close(); + return count; + } /*** * Remove all domains */ diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/webview/MastalabWebViewClient.java b/app/src/main/java/fr/gouv/etalab/mastodon/webview/MastalabWebViewClient.java index ca9d99ff8..8da0171b1 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/webview/MastalabWebViewClient.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/webview/MastalabWebViewClient.java @@ -28,6 +28,8 @@ import android.widget.TextView; import java.net.URI; import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.List; import fr.gouv.etalab.mastodon.R; import fr.gouv.etalab.mastodon.activities.WebviewActivity; @@ -40,11 +42,12 @@ import fr.gouv.etalab.mastodon.activities.WebviewActivity; public class MastalabWebViewClient extends WebViewClient { private Activity activity; + private int count = 0; public MastalabWebViewClient(Activity activity){ this.activity = activity; } - + public List domains = new ArrayList<>(); @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); @@ -57,8 +60,15 @@ public class MastalabWebViewClient extends WebViewClient { try { uri = new URI(url); String domain = uri.getHost(); - domain = domain.startsWith("www.") ? domain.substring(4) : domain; - if (WebviewActivity.trackingDomains.contains(domain)) { + if( domain != null) { + domain = domain.startsWith("www.") ? domain.substring(4) : domain; + } + if (domain != null && WebviewActivity.trackingDomains.contains(domain)) { + if( activity instanceof WebviewActivity){ + count++; + domains.add(url); + ((WebviewActivity)activity).setCount(activity, String.valueOf(count)); + } return null; } } catch (URISyntaxException e) { @@ -67,9 +77,16 @@ public class MastalabWebViewClient extends WebViewClient { return super.shouldInterceptRequest(view, url); } + public List getDomains(){ + return this.domains; + } + @Override public void onPageStarted (WebView view, String url, Bitmap favicon) { super.onPageStarted(view, url, favicon); + count = 0; + domains = new ArrayList<>(); + domains.clear(); ActionBar actionBar = ((AppCompatActivity) activity).getSupportActionBar(); LayoutInflater mInflater = LayoutInflater.from(activity); if( actionBar != null){ diff --git a/app/src/main/res/drawable-anydpi/ic_block_script.xml b/app/src/main/res/drawable-anydpi/ic_block_script.xml new file mode 100644 index 000000000..9a8d0b88e --- /dev/null +++ b/app/src/main/res/drawable-anydpi/ic_block_script.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/browser_calls_blocked.xml b/app/src/main/res/drawable/browser_calls_blocked.xml new file mode 100644 index 000000000..783a0a05b --- /dev/null +++ b/app/src/main/res/drawable/browser_calls_blocked.xml @@ -0,0 +1,12 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/domains_blocked.xml b/app/src/main/res/layout/domains_blocked.xml new file mode 100644 index 000000000..65a45a162 --- /dev/null +++ b/app/src/main/res/layout/domains_blocked.xml @@ -0,0 +1,10 @@ + + diff --git a/app/src/main/res/menu/main_webview.xml b/app/src/main/res/menu/main_webview.xml index e1bbefef1..d8f37aae2 100644 --- a/app/src/main/res/menu/main_webview.xml +++ b/app/src/main/res/menu/main_webview.xml @@ -1,6 +1,11 @@ + 2dp 2dp 50dp + 12sp diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d1114bba3..8d087b5ba 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -881,6 +881,8 @@ Patch the Security Provider Update tracking domains The tracking data base has been updated! + http calls blocked by the application + List of blocked calls