From 56284337184f90d530fc9412370747e95ffe179d Mon Sep 17 00:00:00 2001 From: Stefano Pacifici Date: Wed, 9 Sep 2015 09:52:11 +0200 Subject: [PATCH 01/16] iml files removed. They are generated during gradle sync by Android Studio. --- .gitignore | 2 + app/app.iml | 138 ---------------------------------------------------- 2 files changed, 2 insertions(+), 138 deletions(-) delete mode 100644 app/app.iml diff --git a/.gitignore b/.gitignore index 7f036ba..39bb026 100644 --- a/.gitignore +++ b/.gitignore @@ -50,3 +50,5 @@ out # Source: # https://raw.githubusercontent.com/github/gitignore/master/Android.gitignore # https://gitlab.com/fdroid/fdroidclient/raw/master/.gitignore + +*.iml diff --git a/app/app.iml b/app/app.iml deleted file mode 100644 index 8903f3d..0000000 --- a/app/app.iml +++ /dev/null @@ -1,138 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file From 74a75d4adb09c0bf870229a8f5a09302fa5bd21f Mon Sep 17 00:00:00 2001 From: Stefano Pacifici Date: Mon, 14 Sep 2015 13:44:36 +0200 Subject: [PATCH 02/16] TabsManager created --- .../lightning/activity/BrowserActivity.java | 103 +++++------ .../lightning/activity/TabsManager.java | 172 ++++++++++++++++++ 2 files changed, 213 insertions(+), 62 deletions(-) create mode 100644 app/src/main/java/acr/browser/lightning/activity/TabsManager.java diff --git a/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java b/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java index acf0003..969afc0 100644 --- a/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java +++ b/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java @@ -137,7 +137,6 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements private RelativeLayout mSearchBar; // List - private final List mWebViewList = new ArrayList<>(); private LightningView mCurrentView; private WebView mWebView; @@ -189,6 +188,9 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements @Inject BookmarksDialogBuilder bookmarksDialogBuilder; + @Inject + TabsManager tabsManager; + // Image private Bitmap mWebpageBitmap; private final ColorDrawable mBackground = new ColorDrawable(); @@ -237,7 +239,8 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements mShowTabsInDrawer = mPreferences.getShowTabsInDrawer(!isTablet()); mActivity = this; - mWebViewList.clear(); + // TODO Stefano, check this + // mWebViewList.clear(); mClickHandler = new ClickHandler(this); mBrowserFrame = (FrameLayout) findViewById(R.id.content_frame); @@ -272,7 +275,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements if (mShowTabsInDrawer) { - mTabAdapter = new LightningViewAdapter(this, R.layout.tab_list_item, mWebViewList); + mTabAdapter = new LightningViewAdapter(this, R.layout.tab_list_item, tabsManager.getTabsList()); mDrawerListLeft = (RecyclerView) findViewById(R.id.left_drawer_list); mDrawerListLeft.setOverScrollMode(View.OVER_SCROLL_IF_CONTENT_SCROLLS); RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false); @@ -280,7 +283,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements mDrawerListLeft.setHasFixedSize(true); mToolbarLayout.removeView(horizontalListView); } else { - mTabAdapter = new LightningViewAdapter(this, R.layout.tab_list_item_horizontal, mWebViewList); + mTabAdapter = new LightningViewAdapter(this, R.layout.tab_list_item_horizontal, tabsManager.getTabsList()); mDrawerListLeft = horizontalListView; mDrawerListLeft.setOverScrollMode(View.OVER_SCROLL_NEVER); mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED, mDrawerLeft); @@ -873,10 +876,11 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements @Override public void onClick(View v) { - int position = mDrawerListLeft.getChildAdapterPosition(v); - if (mCurrentView != mWebViewList.get(position)) { + final int position = mDrawerListLeft.getChildAdapterPosition(v); + final LightningView tab = tabsManager.getTabAtPosition(position); + if (tab != null && mCurrentView != tab) { mIsNewIntent = false; - showTab(mWebViewList.get(position)); + showTab(tab); } } } @@ -1018,25 +1022,22 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements public void onTrimMemory(int level) { if (level > TRIM_MEMORY_MODERATE && Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { Log.d(Constants.TAG, "Low Memory, Free Memory"); - for (int n = 0, size = mWebViewList.size(); n < size; n++) { - mWebViewList.get(n).freeMemory(); - } + tabsManager.freeMemory(); } } synchronized boolean newTab(String url, boolean show) { // Limit number of tabs for limited version of app - if (!Constants.FULL_VERSION && mWebViewList.size() >= 10) { + if (!Constants.FULL_VERSION && tabsManager.size() >= 10) { Utils.showSnackbar(this, R.string.max_tabs); return false; } mIsNewIntent = false; - LightningView startingTab = new LightningView(mActivity, url, mDarkTheme, isIncognito(), this); + LightningView startingTab = tabsManager.newTab(mActivity, url, mDarkTheme, isIncognito(), this); if (mIdGenerator == 0) { startingTab.resumeTimers(); } mIdGenerator++; - mWebViewList.add(startingTab); if (show) { showTab(startingTab); @@ -1045,7 +1046,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements new Handler().postDelayed(new Runnable() { @Override public void run() { - mDrawerListLeft.smoothScrollToPosition(mWebViewList.size() - 1); + mDrawerListLeft.smoothScrollToPosition(tabsManager.size() - 1); } }, 300); @@ -1053,49 +1054,47 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements } private synchronized void deleteTab(int position) { - if (position >= mWebViewList.size()) { + final LightningView reference = tabsManager.getTabAtPosition(position); + if (reference == null) { return; } - int current = mWebViewList.indexOf(mCurrentView); +// What? + int current = tabsManager.getPositionForTab(mCurrentView); if (current < 0) { return; } - LightningView reference = mWebViewList.get(position); - if (reference == null) { - return; - } if (!reference.getUrl().startsWith(Constants.FILE) && !isIncognito()) { mPreferences.setSavedUrl(reference.getUrl()); } - boolean isShown = reference.isShown(); + final boolean isShown = reference.isShown(); if (isShown) { mBrowserFrame.setBackgroundColor(mBackgroundColor); } if (current > position) { - mWebViewList.remove(position); - showTab(mWebViewList.get(current - 1)); + tabsManager.deleteTab(position); + showTab(tabsManager.getTabAtPosition(current - 1)); updateTabs(); reference.onDestroy(); - } else if (mWebViewList.size() > position + 1) { + } else if (tabsManager.size() > position + 1) { if (current == position) { - showTab(mWebViewList.get(position + 1)); - mWebViewList.remove(position); - showTab(mWebViewList.get(position)); + showTab(tabsManager.getTabAtPosition(position + 1)); + tabsManager.deleteTab(position); + showTab(tabsManager.getTabAtPosition(position)); updateTabs(); } else { - mWebViewList.remove(position); + tabsManager.deleteTab(position); } reference.onDestroy(); - } else if (mWebViewList.size() > 1) { + } else if (tabsManager.size() > 1) { if (current == position) { - showTab(mWebViewList.get(position - 1)); - mWebViewList.remove(position); - showTab(mWebViewList.get(position - 1)); + showTab(tabsManager.getTabAtPosition(position - 1)); + tabsManager.deleteTab(position); + showTab(tabsManager.getTabAtPosition(position - 1)); updateTabs(); } else { - mWebViewList.remove(position); + tabsManager.deleteTab(position); } reference.onDestroy(); @@ -1103,7 +1102,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements if (mCurrentView.getUrl().startsWith(Constants.FILE) || mCurrentView.getUrl().equals(mHomepage)) { closeActivity(); } else { - mWebViewList.remove(position); + tabsManager.deleteTab(position); performExitCleanUp(); reference.pauseTimers(); reference.onDestroy(); @@ -1150,7 +1149,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements @Override public boolean onKeyLongPress(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { - showCloseDialog(mWebViewList.indexOf(mCurrentView)); + showCloseDialog(tabsManager.positionOf(mCurrentView)); } return true; } @@ -1160,12 +1159,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements performExitCleanUp(); mCurrentView = null; mWebView = null; - for (int n = 0, size = mWebViewList.size(); n < size; n++) { - if (mWebViewList.get(n) != null) { - mWebViewList.get(n).onDestroy(); - } - } - mWebViewList.clear(); + tabsManager.shutdown(); mTabAdapter.notifyDataSetChanged(); finish(); } @@ -1189,7 +1183,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements mCurrentView.goBack(); } } else { - deleteTab(mWebViewList.indexOf(mCurrentView)); + deleteTab(tabsManager.positionOf(mCurrentView)); } } else { Log.e(Constants.TAG, "This shouldn't happen ever"); @@ -1220,12 +1214,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements void saveOpenTabs() { if (mPreferences.getRestoreLostTabsEnabled()) { - String s = ""; - for (int n = 0, size = mWebViewList.size(); n < size; n++) { - if (!mWebViewList.get(n).getUrl().isEmpty()) { - s = s + mWebViewList.get(n).getUrl() + "|$|SEPARATOR|$|"; - } - } + final String s = tabsManager.tabsString(); mPreferences.setMemoryUrl(s); } } @@ -1266,13 +1255,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements } mHistoryDatabase = HistoryDatabase.getInstance(); initializePreferences(); - for (int n = 0, size = mWebViewList.size(); n < size; n++) { - if (mWebViewList.get(n) != null) { - mWebViewList.get(n).initializePreferences(null, this); - } else { - mWebViewList.remove(n); - } - } + tabsManager.resume(this); supportInvalidateOptionsMenu(); @@ -1984,7 +1967,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements */ @Override public void onCloseWindow(LightningView view) { - deleteTab(mWebViewList.indexOf(view)); + deleteTab(tabsManager.positionOf(view)); } /** @@ -2278,7 +2261,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements if (mCurrentView.canGoBack()) { mCurrentView.goBack(); } else { - deleteTab(mWebViewList.indexOf(mCurrentView)); + deleteTab(tabsManager.positionOf(mCurrentView)); } } break; @@ -2353,11 +2336,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements super.onReceive(context, intent); boolean isConnected = isConnected(context); Log.d(Constants.TAG, "Network Connected: " + String.valueOf(isConnected)); - for (int n = 0, size = mWebViewList.size(); n < size; n++) { - WebView view = mWebViewList.get(n).getWebView(); - if (view != null) - view.setNetworkAvailable(isConnected); - } + tabsManager.notifyConnectioneStatus(isConnected); } }; diff --git a/app/src/main/java/acr/browser/lightning/activity/TabsManager.java b/app/src/main/java/acr/browser/lightning/activity/TabsManager.java new file mode 100644 index 0000000..aaf4e26 --- /dev/null +++ b/app/src/main/java/acr/browser/lightning/activity/TabsManager.java @@ -0,0 +1,172 @@ +package acr.browser.lightning.activity; + +import android.app.Activity; +import android.content.Context; +import android.support.annotation.Nullable; +import android.webkit.WebView; + +import java.util.ArrayList; +import java.util.List; + +import javax.inject.Inject; + +import acr.browser.lightning.controller.BrowserController; +import acr.browser.lightning.view.LightningView; + +/** + * @author Stefano Pacifici + * @date 2015/09/14 + */ +public class TabsManager { + + private final List mWebViewList = new ArrayList<>(); + + @Inject + public TabsManager() { + } + + /** + * Return a clone of the current tabs list. The list will not be updated, the user has to fetch + * a new copy when notified. + * + * @return a copy of the current tabs list + */ + public List getTabsList() { + return new ArrayList<>(mWebViewList); + } + + /** + * Return the tab at the given position in tabs list, or null if position is not in tabs list + * range. + * + * @param position the index in tabs list + * @return the corespondent {@link LightningView}, or null if the index is invalid + */ + @Nullable + public LightningView getTabAtPosition(final int position) { + if (position < 0 || position >= mWebViewList.size()) { + return null; + } + + return mWebViewList.get(position); + } + + /** + * Try to low memory pressure + */ + public void freeMemory() { + for (LightningView tab: mWebViewList) { + tab.freeMemory(); + } + } + + /** + * Shutdown the manager + */ + public synchronized void shutdown() { + for (LightningView tab: mWebViewList) { + tab.onDestroy(); + } + mWebViewList.clear(); + } + + /** + * Resume the tabs + * + * @param context + */ + public synchronized void resume(final Context context) { + for (LightningView tab: mWebViewList) { + tab.initializePreferences(null, context); + } + } + + /** + * Forward network connection status to the webviews. + * + * @param isConnected + */ + public synchronized void notifyConnectioneStatus(final boolean isConnected) { + for (LightningView tab: mWebViewList) { + final WebView webView = tab.getWebView(); + if (webView != null) { + webView.setNetworkAvailable(isConnected); + } + } + } + /** + * @return The number of currently opened tabs + */ + public int size() { + return mWebViewList.size(); + } + + /** + * Create and return a new tab. The tab is automatically added to the tabs list. + * + * @param activity + * @param url + * @param darkTheme + * @param isIncognito + * @param controller + * @return + */ + public synchronized LightningView newTab(final Activity activity, + final String url, final boolean darkTheme, + final boolean isIncognito, + final BrowserController controller) { + final LightningView tab = new LightningView(activity, url, darkTheme, isIncognito, controller); + mWebViewList.add(tab); + return tab; + } + + /** + * Remove a tab and return its reference or null if the position is not in tabs range + * + * @param position The position of the tab to remove + * @return The removed tab reference or null + */ + @Nullable + public synchronized LightningView deleteTab(final int position) { + if (position >= mWebViewList.size()) { + return null; + } + final LightningView tab = mWebViewList.remove(position); + // TODO This should not be done outside this call + // tab.onDestroy(); + return tab; + } + + /** + * TODO I think it should be removed + * Return the position of the given tab + * @param tab + * @return + */ + public int positionOf(final LightningView tab) { + return mWebViewList.indexOf(tab); + } + + /** + * @return A string representation of the currently opened tabs + */ + public String tabsString() { + final StringBuilder builder = new StringBuilder(); + for (LightningView tab: mWebViewList) { + final String url = tab.getUrl(); + if (url != null && !url.isEmpty()) { + builder.append(url).append("|$|SEPARATOR|$|"); + } + } + return builder.toString(); + } + + /** + * TODO Remove this, temporary workaround + * @param tab + * @return + */ + public int getPositionForTab(final LightningView tab) { + return mWebViewList.indexOf(tab); + } +} From f0c3b743d48d3e75b15bcbe057eb15d0131f52ac Mon Sep 17 00:00:00 2001 From: Stefano Pacifici Date: Mon, 14 Sep 2015 14:19:07 +0200 Subject: [PATCH 03/16] CurrentTab reference removed from BrowserActivity --- .../lightning/activity/BrowserActivity.java | 255 ++++++++++-------- .../lightning/activity/TabsManager.java | 16 ++ 2 files changed, 157 insertions(+), 114 deletions(-) diff --git a/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java b/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java index 969afc0..9f40851 100644 --- a/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java +++ b/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java @@ -137,7 +137,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements private RelativeLayout mSearchBar; // List - private LightningView mCurrentView; + // private LightningView mCurrentView; private WebView mWebView; // Views @@ -387,8 +387,9 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(mSearch.getWindowToken(), 0); searchTheWeb(mSearch.getText().toString()); - if (mCurrentView != null) { - mCurrentView.requestFocus(); + final LightningView currentView = tabsManager.getCurrentTab(); + if (currentView != null) { + currentView.requestFocus(); } return true; default: @@ -409,8 +410,9 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(mSearch.getWindowToken(), 0); searchTheWeb(mSearch.getText().toString()); - if (mCurrentView != null) { - mCurrentView.requestFocus(); + final LightningView currentView = tabsManager.getCurrentTab(); + if (currentView != null) { + currentView.requestFocus(); } return true; } @@ -419,15 +421,16 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements @Override public void onFocusChange(View v, final boolean hasFocus) { - if (!hasFocus && mCurrentView != null) { - if (mCurrentView.getProgress() < 100) { + final LightningView currentView = tabsManager.getCurrentTab(); + if (!hasFocus && currentView != null) { + if (currentView.getProgress() < 100) { setIsLoading(); } else { setIsFinishedLoading(); } - updateUrl(mCurrentView.getUrl(), true); + updateUrl(currentView.getUrl(), true); } else if (hasFocus) { - String url = mCurrentView.getUrl(); + String url = currentView.getUrl(); if (url.startsWith(Constants.FILE)) { mSearch.setText(""); } else { @@ -616,6 +619,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements } private void initializePreferences() { + final LightningView currentView = tabsManager.getCurrentTab(); if (mPreferences == null) { mPreferences = PreferenceManager.getInstance(); } @@ -624,9 +628,9 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements mColorMode &= !mDarkTheme; if (!isIncognito() && !mColorMode && !mDarkTheme && mWebpageBitmap != null) { changeToolbarBackground(mWebpageBitmap, null); - } else if (!isIncognito() && mCurrentView != null && !mDarkTheme - && mCurrentView.getFavicon() != null) { - changeToolbarBackground(mCurrentView.getFavicon(), null); + } else if (!isIncognito() && currentView != null && !mDarkTheme + && currentView.getFavicon() != null) { + changeToolbarBackground(currentView.getFavicon(), null); } if (mFullScreen) { @@ -729,6 +733,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements @Override public boolean onOptionsItemSelected(MenuItem item) { + final LightningView currentView = tabsManager.getCurrentTab(); // Handle action buttons switch (item.getItemId()) { case android.R.id.home: @@ -737,13 +742,13 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements } return true; case R.id.action_back: - if (mCurrentView != null && mCurrentView.canGoBack()) { - mCurrentView.goBack(); + if (currentView != null && currentView.canGoBack()) { + currentView.goBack(); } return true; case R.id.action_forward: - if (mCurrentView != null && mCurrentView.canGoForward()) { - mCurrentView.goForward(); + if (currentView != null && currentView.canGoForward()) { + currentView.goForward(); } return true; case R.id.action_new_tab: @@ -754,11 +759,11 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements overridePendingTransition(R.anim.slide_up_in, R.anim.fade_out_scale); return true; case R.id.action_share: - if (mCurrentView != null && !mCurrentView.getUrl().startsWith(Constants.FILE)) { + if (currentView != null && !currentView.getUrl().startsWith(Constants.FILE)) { Intent shareIntent = new Intent(Intent.ACTION_SEND); shareIntent.setType("text/plain"); - shareIntent.putExtra(Intent.EXTRA_SUBJECT, mCurrentView.getTitle()); - shareIntent.putExtra(Intent.EXTRA_TEXT, mCurrentView.getUrl()); + shareIntent.putExtra(Intent.EXTRA_SUBJECT, currentView.getTitle()); + shareIntent.putExtra(Intent.EXTRA_TEXT, currentView.getUrl()); startActivity(Intent.createChooser(shareIntent, getResources().getString(R.string.dialog_title_share))); } return true; @@ -766,9 +771,9 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements openBookmarks(); return true; case R.id.action_copy: - if (mCurrentView != null && !mCurrentView.getUrl().startsWith(Constants.FILE)) { + if (currentView != null && !currentView.getUrl().startsWith(Constants.FILE)) { ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE); - ClipData clip = ClipData.newPlainText("label", mCurrentView.getUrl()); + ClipData clip = ClipData.newPlainText("label", currentView.getUrl()); clipboard.setPrimaryClip(clip); Utils.showSnackbar(mActivity, R.string.message_link_copied); } @@ -780,9 +785,9 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements openHistory(); return true; case R.id.action_add_bookmark: - if (mCurrentView != null && !mCurrentView.getUrl().startsWith(Constants.FILE)) { - eventBus.post(new BrowserEvents.AddBookmark(mCurrentView.getTitle(), - mCurrentView.getUrl())); + if (currentView != null && !currentView.getUrl().startsWith(Constants.FILE)) { + eventBus.post(new BrowserEvents.AddBookmark(currentView.getTitle(), + currentView.getUrl())); } return true; case R.id.action_find: @@ -790,7 +795,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements return true; case R.id.action_reading_mode: Intent read = new Intent(this, ReadingActivity.class); - read.putExtra(Constants.LOAD_READING_URL, mCurrentView.getUrl()); + read.putExtra(Constants.LOAD_READING_URL, currentView.getUrl()); startActivity(read); return true; default: @@ -822,8 +827,9 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements } private void showSearchInterfaceBar(String text) { - if (mCurrentView != null) { - mCurrentView.find(text); + final LightningView currentView = tabsManager.getCurrentTab(); + if (currentView != null) { + currentView.find(text); } mSearchBar = (RelativeLayout) findViewById(R.id.search_bar); mSearchBar.setVisibility(View.VISIBLE); @@ -876,9 +882,10 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements @Override public void onClick(View v) { + final LightningView currentTab = tabsManager.getCurrentTab(); final int position = mDrawerListLeft.getChildAdapterPosition(v); final LightningView tab = tabsManager.getTabAtPosition(position); - if (tab != null && mCurrentView != tab) { + if (tab != null && currentTab != tab) { mIsNewIntent = false; showTab(tab); } @@ -902,34 +909,35 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements * displays the WebView contained in the LightningView Also handles the * removal of previous views * - * @param view the LightningView to show + * @param newView the LightningView to show */ - private synchronized void showTab(LightningView view) { + private synchronized void showTab(LightningView newView) { + final LightningView currentView = tabsManager.getCurrentTab(); // Set the background color so the color mode color doesn't show through mBrowserFrame.setBackgroundColor(mBackgroundColor); - if (view == null) { + if (newView == null) { return; } final float translation = mToolbarLayout.getTranslationY(); mBrowserFrame.removeAllViews(); - if (mCurrentView != null) { - mCurrentView.setForegroundTab(false); - mCurrentView.onPause(); + if (currentView != null) { + currentView.setForegroundTab(false); + currentView.onPause(); } - mCurrentView = view; - mWebView = view.getWebView(); - mCurrentView.setForegroundTab(true); + tabsManager.setCurrentTab(newView); + mWebView = newView.getWebView(); + newView.setForegroundTab(true); if (mWebView != null) { - updateUrl(mCurrentView.getUrl(), true); - updateProgress(mCurrentView.getProgress()); + updateUrl(newView.getUrl(), true); + updateProgress(newView.getProgress()); } else { updateUrl("", true); updateProgress(0); } mBrowserFrame.addView(mWebView, MATCH_PARENT); - mCurrentView.requestFocus(); - mCurrentView.onResume(); + newView.requestFocus(); + newView.onResume(); if (mFullScreen) { // mToolbarLayout has already been removed @@ -960,7 +968,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements }, 200); // Should update the bookmark status in BookmarksFragment - eventBus.post(new BrowserEvents.CurrentPageUrl(mCurrentView.getUrl())); + eventBus.post(new BrowserEvents.CurrentPageUrl(newView.getUrl())); // new Handler().postDelayed(new Runnable() { // @Override @@ -998,12 +1006,13 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements } private void loadUrlInCurrentView(final String url) { - if (mCurrentView == null) { + final LightningView currentTab = tabsManager.getCurrentTab(); + if (currentTab == null) { // This is a problem, probably an assert will be better than a return return; } - mCurrentView.loadUrl(url); + currentTab.loadUrl(url); eventBus.post(new BrowserEvents.CurrentPageUrl(url)); } @@ -1054,20 +1063,22 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements } private synchronized void deleteTab(int position) { - final LightningView reference = tabsManager.getTabAtPosition(position); - if (reference == null) { + final LightningView tabToDelete = tabsManager.getTabAtPosition(position); + final LightningView currentTab = tabsManager.getCurrentTab(); + + if (tabToDelete == null) { return; } // What? - int current = tabsManager.getPositionForTab(mCurrentView); + int current = tabsManager.getPositionForTab(currentTab); if (current < 0) { return; } - if (!reference.getUrl().startsWith(Constants.FILE) && !isIncognito()) { - mPreferences.setSavedUrl(reference.getUrl()); + if (!tabToDelete.getUrl().startsWith(Constants.FILE) && !isIncognito()) { + mPreferences.setSavedUrl(tabToDelete.getUrl()); } - final boolean isShown = reference.isShown(); + final boolean isShown = tabToDelete.isShown(); if (isShown) { mBrowserFrame.setBackgroundColor(mBackgroundColor); } @@ -1075,7 +1086,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements tabsManager.deleteTab(position); showTab(tabsManager.getTabAtPosition(current - 1)); updateTabs(); - reference.onDestroy(); + tabToDelete.onDestroy(); } else if (tabsManager.size() > position + 1) { if (current == position) { showTab(tabsManager.getTabAtPosition(position + 1)); @@ -1086,7 +1097,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements tabsManager.deleteTab(position); } - reference.onDestroy(); + tabToDelete.onDestroy(); } else if (tabsManager.size() > 1) { if (current == position) { showTab(tabsManager.getTabAtPosition(position - 1)); @@ -1097,16 +1108,15 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements tabsManager.deleteTab(position); } - reference.onDestroy(); + tabToDelete.onDestroy(); } else { - if (mCurrentView.getUrl().startsWith(Constants.FILE) || mCurrentView.getUrl().equals(mHomepage)) { + if (currentTab.getUrl().startsWith(Constants.FILE) || currentTab.getUrl().equals(mHomepage)) { closeActivity(); } else { tabsManager.deleteTab(position); performExitCleanUp(); - reference.pauseTimers(); - reference.onDestroy(); - mCurrentView = null; + tabToDelete.pauseTimers(); + tabToDelete.onDestroy(); mWebView = null; mTabAdapter.notifyDataSetChanged(); finish(); @@ -1123,8 +1133,9 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements } private void performExitCleanUp() { - if (mPreferences.getClearCacheExit() && mCurrentView != null && !isIncognito()) { - WebUtils.clearCache(mCurrentView.getWebView()); + final LightningView currentTab = tabsManager.getCurrentTab(); + if (mPreferences.getClearCacheExit() && currentTab != null && !isIncognito()) { + WebUtils.clearCache(currentTab.getWebView()); Log.d(Constants.TAG, "Cache Cleared"); } @@ -1148,8 +1159,9 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements @Override public boolean onKeyLongPress(int keyCode, KeyEvent event) { + final LightningView currentTab = tabsManager.getCurrentTab(); if (keyCode == KeyEvent.KEYCODE_BACK) { - showCloseDialog(tabsManager.positionOf(mCurrentView)); + showCloseDialog(tabsManager.positionOf(currentTab)); } return true; } @@ -1157,7 +1169,6 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements private void closeBrowser() { mBrowserFrame.setBackgroundColor(mBackgroundColor); performExitCleanUp(); - mCurrentView = null; mWebView = null; tabsManager.shutdown(); mTabAdapter.notifyDataSetChanged(); @@ -1166,24 +1177,25 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements @Override public void onBackPressed() { + final LightningView currentTab = tabsManager.getCurrentTab(); if (mDrawerLayout.isDrawerOpen(mDrawerLeft)) { mDrawerLayout.closeDrawer(mDrawerLeft); } else if (mDrawerLayout.isDrawerOpen(mDrawerRight)) { eventBus .post(new BrowserEvents.UserPressedBack()); } else { - if (mCurrentView != null) { + if (currentTab != null) { Log.d(Constants.TAG, "onBackPressed"); if (mSearch.hasFocus()) { - mCurrentView.requestFocus(); - } else if (mCurrentView.canGoBack()) { - if (!mCurrentView.isShown()) { + currentTab.requestFocus(); + } else if (currentTab.canGoBack()) { + if (!currentTab.isShown()) { onHideCustomView(); } else { - mCurrentView.goBack(); + currentTab.goBack(); } } else { - deleteTab(tabsManager.positionOf(mCurrentView)); + deleteTab(tabsManager.positionOf(currentTab)); } } else { Log.e(Constants.TAG, "This shouldn't happen ever"); @@ -1195,10 +1207,11 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements @Override protected void onPause() { super.onPause(); + final LightningView currentTab = tabsManager.getCurrentTab(); Log.d(Constants.TAG, "onPause"); - if (mCurrentView != null) { - mCurrentView.pauseTimers(); - mCurrentView.onPause(); + if (currentTab != null) { + currentTab.pauseTimers(); + currentTab.onPause(); } try { unregisterReceiver(mNetworkReceiver); @@ -1244,14 +1257,15 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements @Override protected void onResume() { super.onResume(); + final LightningView currentTab = tabsManager.getCurrentTab(); Log.d(Constants.TAG, "onResume"); if (mSearchAdapter != null) { mSearchAdapter.refreshPreferences(); mSearchAdapter.refreshBookmarks(); } - if (mCurrentView != null) { - mCurrentView.resumeTimers(); - mCurrentView.onResume(); + if (currentTab != null) { + currentTab.resumeTimers(); + currentTab.onResume(); } mHistoryDatabase = HistoryDatabase.getInstance(); initializePreferences(); @@ -1271,13 +1285,14 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements * checks if it is a search, url, etc. */ private void searchTheWeb(@NonNull String query) { + final LightningView currentTab = tabsManager.getCurrentTab(); if (query.isEmpty()) { return; } String searchUrl = mSearchText + UrlUtils.QUERY_PLACE_HOLDER; query = query.trim(); - mCurrentView.stopLoading(); - if (mCurrentView != null) { + currentTab.stopLoading(); + if (currentTab != null) { loadUrlInCurrentView(UrlUtils.smartUrlFilter(query, true, searchUrl)); } } @@ -1496,6 +1511,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements @Override public void updateUrl(String url, boolean shortUrl) { + final LightningView currentTab = tabsManager.getCurrentTab(); if (url == null || mSearch == null || mSearch.hasFocus()) { return; } @@ -1511,8 +1527,8 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements mSearch.setText(url); break; case 2: // Title, show the page's title - if (mCurrentView != null && !mCurrentView.getTitle().isEmpty()) { - mSearch.setText(mCurrentView.getTitle()); + if (currentTab != null && !currentTab.getTitle().isEmpty()) { + mSearch.setText(currentTab.getTitle()); } else { mSearch.setText(mUntitledTitle); } @@ -1564,7 +1580,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements * previously searched URLs */ private void initializeSearchSuggestions(final AutoCompleteTextView getUrl) { - + final LightningView currentTab = tabsManager.getCurrentTab(); getUrl.setThreshold(1); getUrl.setDropDownWidth(-1); getUrl.setDropDownAnchor(R.id.toolbar_layout); @@ -1583,8 +1599,8 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements searchTheWeb(url); InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(getUrl.getWindowToken(), 0); - if (mCurrentView != null) { - mCurrentView.requestFocus(); + if (currentTab != null) { + currentTab.requestFocus(); } } catch (NullPointerException e) { Log.e("Browser Error: ", "NullPointerException on item click"); @@ -1798,6 +1814,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements @Override public void onShowCustomView(View view, CustomViewCallback callback) { + final LightningView currentTab = tabsManager.getCurrentTab(); if (view == null) { return; } @@ -1817,7 +1834,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements mFullscreenContainer.addView(mCustomView, COVER_SCREEN_PARAMS); decor.addView(mFullscreenContainer, COVER_SCREEN_PARAMS); setFullscreen(true, true); - mCurrentView.setVisibility(View.GONE); + currentTab.setVisibility(View.GONE); if (view instanceof FrameLayout) { if (((FrameLayout) view).getFocusedChild() instanceof VideoView) { mVideoView = (VideoView) ((FrameLayout) view).getFocusedChild(); @@ -1830,11 +1847,12 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements @Override public void onHideCustomView() { - if (mCustomView == null || mCustomViewCallback == null || mCurrentView == null) { + final LightningView currentTab = tabsManager.getCurrentTab(); + if (mCustomView == null || mCustomViewCallback == null || currentTab == null) { return; } Log.d(Constants.TAG, "onHideCustomView"); - mCurrentView.setVisibility(View.VISIBLE); + currentTab.setVisibility(View.VISIBLE); try { mCustomView.setKeepScreenOn(false); } catch (SecurityException e) { @@ -1984,6 +2002,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements */ @Override public void hideActionBar() { + final LightningView currentTab = tabsManager.getCurrentTab(); if (mFullScreen) { if (mBrowserFrame.findViewById(R.id.toolbar_layout) == null) { mUiLayout.removeView(mToolbarLayout); @@ -1993,7 +2012,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements mToolbarLayout.setTranslationY(0); mWebView.setTranslationY(mToolbarLayout.getHeight()); } - if (mToolbarLayout == null || mCurrentView == null) + if (mToolbarLayout == null || currentTab == null) return; final int height = mToolbarLayout.getHeight(); @@ -2040,7 +2059,8 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements mToolbarLayout.setTranslationY(0); mWebView.setTranslationY(height); } - if (mCurrentView == null) + final LightningView currentTab = tabsManager.getCurrentTab(); + if (currentTab == null) return; final WebView view = mWebView; @@ -2119,6 +2139,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { + final LightningView currentTab = tabsManager.getCurrentTab(); switch (which) { case DialogInterface.BUTTON_POSITIVE: newTab(url, false); @@ -2131,7 +2152,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements break; case DialogInterface.BUTTON_NEUTRAL: - if (mCurrentView != null) { + if (currentTab != null) { loadUrlInCurrentView(url); } break; @@ -2153,6 +2174,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { + final LightningView currentTab = tabsManager.getCurrentTab(); switch (which) { case DialogInterface.BUTTON_POSITIVE: newTab(url, false); @@ -2165,7 +2187,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements case DialogInterface.BUTTON_NEUTRAL: if (API > 8) { Utils.downloadFile(mActivity, url, - mCurrentView.getUserAgent(), "attachment"); + currentTab.getUserAgent(), "attachment"); } break; } @@ -2244,41 +2266,43 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements * See setIsFinishedLoading and setIsLoading for displaying the correct icon */ private void refreshOrStop() { - if (mCurrentView != null) { - if (mCurrentView.getProgress() < 100) { - mCurrentView.stopLoading(); + final LightningView currentTab = tabsManager.getCurrentTab(); + if (currentTab != null) { + if (currentTab.getProgress() < 100) { + currentTab.stopLoading(); } else { - mCurrentView.reload(); + currentTab.reload(); } } } @Override public void onClick(View v) { + final LightningView currentTab = tabsManager.getCurrentTab(); switch (v.getId()) { case R.id.action_back: - if (mCurrentView != null) { - if (mCurrentView.canGoBack()) { - mCurrentView.goBack(); + if (currentTab != null) { + if (currentTab.canGoBack()) { + currentTab.goBack(); } else { - deleteTab(tabsManager.positionOf(mCurrentView)); + deleteTab(tabsManager.positionOf(currentTab)); } } break; case R.id.action_forward: - if (mCurrentView != null) { - if (mCurrentView.canGoForward()) { - mCurrentView.goForward(); + if (currentTab != null) { + if (currentTab.canGoForward()) { + currentTab.goForward(); } } break; case R.id.arrow_button: if (mSearch != null && mSearch.hasFocus()) { - mCurrentView.requestFocus(); + currentTab.requestFocus(); } else if (mShowTabsInDrawer) { mDrawerLayout.openDrawer(mDrawerLeft); - } else if (mCurrentView != null) { - mCurrentView.loadHomepage(); + } else if (currentTab != null) { + currentTab.loadHomepage(); } break; case R.id.new_tab_button: @@ -2296,12 +2320,12 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements break; case R.id.action_reading: Intent read = new Intent(this, ReadingActivity.class); - read.putExtra(Constants.LOAD_READING_URL, mCurrentView.getUrl()); + read.putExtra(Constants.LOAD_READING_URL, currentTab.getUrl()); startActivity(read); break; case R.id.action_toggle_desktop: - mCurrentView.toggleDesktopUA(this); - mCurrentView.reload(); + currentTab.toggleDesktopUA(this); + currentTab.reload(); closeDrawers(); break; } @@ -2386,8 +2410,9 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements */ @Subscribe public void bookmarkCurrentPage(final BookmarkEvents.WantToBookmarkCurrentPage event) { - if (mCurrentView != null) { - eventBus.post(new BrowserEvents.AddBookmark(mCurrentView.getTitle(), mCurrentView.getUrl())); + final LightningView currentTab = tabsManager.getCurrentTab(); + if (currentTab != null) { + eventBus.post(new BrowserEvents.AddBookmark(currentTab.getTitle(), currentTab.getUrl())); } } @@ -2409,12 +2434,13 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements */ @Subscribe public void bookmarkChanged(final BookmarkEvents.BookmarkChanged event) { - if (mCurrentView != null && mCurrentView.getUrl().startsWith(Constants.FILE) - && mCurrentView.getUrl().endsWith(Constants.BOOKMARKS_FILENAME)) { + final LightningView currentTab = tabsManager.getCurrentTab(); + if (currentTab != null && currentTab.getUrl().startsWith(Constants.FILE) + && currentTab.getUrl().endsWith(Constants.BOOKMARKS_FILENAME)) { openBookmarkPage(mWebView); } - if (mCurrentView != null) { - eventBus.post(new BrowserEvents.CurrentPageUrl(mCurrentView.getUrl())); + if (currentTab != null) { + eventBus.post(new BrowserEvents.CurrentPageUrl(currentTab.getUrl())); } } @@ -2425,12 +2451,13 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements */ @Subscribe public void bookmarkDeleted(final BookmarkEvents.Deleted event) { - if (mCurrentView != null && mCurrentView.getUrl().startsWith(Constants.FILE) - && mCurrentView.getUrl().endsWith(Constants.BOOKMARKS_FILENAME)) { + final LightningView currentTab = tabsManager.getCurrentTab(); + if (currentTab != null && currentTab.getUrl().startsWith(Constants.FILE) + && currentTab.getUrl().endsWith(Constants.BOOKMARKS_FILENAME)) { openBookmarkPage(mWebView); } - if (mCurrentView != null) { - eventBus.post(new BrowserEvents.CurrentPageUrl(mCurrentView.getUrl())); + if (currentTab != null) { + eventBus.post(new BrowserEvents.CurrentPageUrl(currentTab.getUrl())); } } diff --git a/app/src/main/java/acr/browser/lightning/activity/TabsManager.java b/app/src/main/java/acr/browser/lightning/activity/TabsManager.java index aaf4e26..0e46366 100644 --- a/app/src/main/java/acr/browser/lightning/activity/TabsManager.java +++ b/app/src/main/java/acr/browser/lightning/activity/TabsManager.java @@ -20,6 +20,7 @@ import acr.browser.lightning.view.LightningView; public class TabsManager { private final List mWebViewList = new ArrayList<>(); + private LightningView mCurrentTab; @Inject public TabsManager() { @@ -169,4 +170,19 @@ public class TabsManager { public int getPositionForTab(final LightningView tab) { return mWebViewList.indexOf(tab); } + + /** + * TODO We should remove also this + * @return + */ + public LightningView getCurrentTab() { + return mCurrentTab; + } + + /** + * TODO We should remove also this + */ + public void setCurrentTab(final LightningView tab) { + mCurrentTab = tab; + } } From 74073178bfa7513939297752520a53c32315ddd4 Mon Sep 17 00:00:00 2001 From: Stefano Pacifici Date: Mon, 14 Sep 2015 14:41:11 +0200 Subject: [PATCH 04/16] mWebView reference removed from BrowserActivity --- .../lightning/activity/BrowserActivity.java | 74 +++++++++++-------- .../lightning/activity/TabsManager.java | 9 +++ 2 files changed, 51 insertions(+), 32 deletions(-) diff --git a/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java b/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java index 9f40851..dfee365 100644 --- a/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java +++ b/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java @@ -136,10 +136,6 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements private ViewGroup mDrawerLeft, mDrawerRight, mUiLayout, mToolbarLayout; private RelativeLayout mSearchBar; - // List - // private LightningView mCurrentView; - private WebView mWebView; - // Views private AnimatedProgressBar mProgressBar; private AutoCompleteTextView mSearch; @@ -620,6 +616,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements private void initializePreferences() { final LightningView currentView = tabsManager.getCurrentTab(); + final WebView currentWebView = currentView.getWebView(); if (mPreferences == null) { mPreferences = PreferenceManager.getInstance(); } @@ -640,8 +637,8 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements mToolbarLayout.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED); height = mToolbarLayout.getMeasuredHeight(); } - if (mWebView != null) - mWebView.setTranslationY(height); + if (currentWebView != null) + currentWebView.setTranslationY(height); mBrowserFrame.setLayoutTransition(null); if (mBrowserFrame.findViewById(R.id.toolbar_layout) == null) { mUiLayout.removeView(mToolbarLayout); @@ -655,8 +652,8 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements mUiLayout.addView(mToolbarLayout, 0); } mBrowserFrame.setLayoutTransition(new LayoutTransition()); - if (mWebView != null) - mWebView.setTranslationY(0); + if (currentWebView != null) + currentWebView.setTranslationY(0); } setFullscreen(mPreferences.getHideStatusBarEnabled(), false); @@ -925,9 +922,9 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements currentView.onPause(); } tabsManager.setCurrentTab(newView); - mWebView = newView.getWebView(); + final WebView currentWebView = currentView.getWebView(); newView.setForegroundTab(true); - if (mWebView != null) { + if (currentWebView != null) { updateUrl(newView.getUrl(), true); updateProgress(newView.getProgress()); } else { @@ -935,7 +932,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements updateProgress(0); } - mBrowserFrame.addView(mWebView, MATCH_PARENT); + mBrowserFrame.addView(currentWebView, MATCH_PARENT); newView.requestFocus(); newView.onResume(); @@ -949,10 +946,10 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements mToolbarLayout.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED); height = mToolbarLayout.getMeasuredHeight(); } - mWebView.setTranslationY(translation + height); + currentWebView.setTranslationY(translation + height); mToolbarLayout.setTranslationY(translation); } else { - mWebView.setTranslationY(0); + currentWebView.setTranslationY(0); } showActionBar(); @@ -1018,7 +1015,8 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements @Override public void closeEmptyTab() { - if (mWebView != null && mWebView.copyBackForwardList().getSize() == 0) { + final WebView currentWebView = tabsManager.getCurrentWebView(); + if (currentWebView != null && currentWebView.copyBackForwardList().getSize() == 0) { closeCurrentTab(); } } @@ -1117,7 +1115,6 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements performExitCleanUp(); tabToDelete.pauseTimers(); tabToDelete.onDestroy(); - mWebView = null; mTabAdapter.notifyDataSetChanged(); finish(); } @@ -1169,7 +1166,6 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements private void closeBrowser() { mBrowserFrame.setBackgroundColor(mBackgroundColor); performExitCleanUp(); - mWebView = null; tabsManager.shutdown(); mTabAdapter.notifyDataSetChanged(); finish(); @@ -1808,7 +1804,10 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements Message click = mClickHandler.obtainMessage(); if (click != null) { click.setTarget(mClickHandler); - mWebView.requestFocusNodeHref(click); + final WebView currentWebView = tabsManager.getCurrentWebView(); + if (currentWebView != null) { + currentWebView.requestFocusNodeHref(click); + } } } @@ -1972,8 +1971,10 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements return; } if (newTab("", true)) { + // TODO Review this + final WebView webView = tabsManager.getTabAtPosition(tabsManager.size() - 1).getWebView(); WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj; - transport.setWebView(mWebView); + transport.setWebView(webView); resultMsg.sendToTarget(); } } @@ -2003,6 +2004,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements @Override public void hideActionBar() { final LightningView currentTab = tabsManager.getCurrentTab(); + final WebView currentWebView = currentTab.getWebView(); if (mFullScreen) { if (mBrowserFrame.findViewById(R.id.toolbar_layout) == null) { mUiLayout.removeView(mToolbarLayout); @@ -2010,13 +2012,13 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements mToolbarLayout.bringToFront(); Log.d(Constants.TAG, "Move view to browser frame"); mToolbarLayout.setTranslationY(0); - mWebView.setTranslationY(mToolbarLayout.getHeight()); + currentWebView.setTranslationY(mToolbarLayout.getHeight()); } if (mToolbarLayout == null || currentTab == null) return; final int height = mToolbarLayout.getHeight(); - final WebView view = mWebView; + final WebView view = currentWebView; if (mToolbarLayout.getTranslationY() > -0.01f) { Animation show = new Animation() { @Override @@ -2030,7 +2032,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements show.setDuration(250); show.setInterpolator(new DecelerateInterpolator()); // show.setFillAfter(true); - mWebView.startAnimation(show); + currentWebView.startAnimation(show); } } } @@ -2041,6 +2043,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements @Override public void showActionBar() { if (mFullScreen) { + final WebView view = tabsManager.getCurrentWebView(); if (mToolbarLayout == null) return; @@ -2057,13 +2060,14 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements mToolbarLayout.bringToFront(); Log.d(Constants.TAG, "Move view to browser frame"); mToolbarLayout.setTranslationY(0); - mWebView.setTranslationY(height); + if (view != null) { + view.setTranslationY(height); + } } final LightningView currentTab = tabsManager.getCurrentTab(); if (currentTab == null) return; - final WebView view = mWebView; final int totalHeight = height; if (mToolbarLayout.getTranslationY() < -(height - 0.01f)) { Animation show = new Animation() { @@ -2079,7 +2083,9 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements show.setDuration(250); show.setInterpolator(new DecelerateInterpolator()); // show.setFillAfter(true); - mWebView.startAnimation(show); + if (view != null) { + view.startAnimation(show); + } } } } @@ -2093,9 +2099,10 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements public void longClickPage(final String url) { HitTestResult result = null; String currentUrl = null; - if (mWebView != null) { - result = mWebView.getHitTestResult(); - currentUrl = mWebView.getUrl(); + final WebView currentWebView = tabsManager.getCurrentWebView(); + if (currentWebView != null) { + result = currentWebView.getHitTestResult(); + currentUrl = currentWebView.getUrl(); } if (currentUrl != null && currentUrl.startsWith(Constants.FILE)) { if (currentUrl.endsWith(HistoryPage.FILENAME)) { @@ -2279,6 +2286,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements @Override public void onClick(View v) { final LightningView currentTab = tabsManager.getCurrentTab(); + final WebView currentWebView = currentTab.getWebView(); switch (v.getId()) { case R.id.action_back: if (currentTab != null) { @@ -2309,13 +2317,13 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements newTab(null, true); break; case R.id.button_next: - mWebView.findNext(false); + currentWebView.findNext(false); break; case R.id.button_back: - mWebView.findNext(true); + currentWebView.findNext(true); break; case R.id.button_quit: - mWebView.clearMatches(); + currentWebView.clearMatches(); mSearchBar.setVisibility(View.GONE); break; case R.id.action_reading: @@ -2435,9 +2443,10 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements @Subscribe public void bookmarkChanged(final BookmarkEvents.BookmarkChanged event) { final LightningView currentTab = tabsManager.getCurrentTab(); + final WebView currentWebView = currentTab.getWebView(); if (currentTab != null && currentTab.getUrl().startsWith(Constants.FILE) && currentTab.getUrl().endsWith(Constants.BOOKMARKS_FILENAME)) { - openBookmarkPage(mWebView); + openBookmarkPage(currentWebView); } if (currentTab != null) { eventBus.post(new BrowserEvents.CurrentPageUrl(currentTab.getUrl())); @@ -2452,9 +2461,10 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements @Subscribe public void bookmarkDeleted(final BookmarkEvents.Deleted event) { final LightningView currentTab = tabsManager.getCurrentTab(); + final WebView currentWebView = currentTab.getWebView(); if (currentTab != null && currentTab.getUrl().startsWith(Constants.FILE) && currentTab.getUrl().endsWith(Constants.BOOKMARKS_FILENAME)) { - openBookmarkPage(mWebView); + openBookmarkPage(currentWebView); } if (currentTab != null) { eventBus.post(new BrowserEvents.CurrentPageUrl(currentTab.getUrl())); diff --git a/app/src/main/java/acr/browser/lightning/activity/TabsManager.java b/app/src/main/java/acr/browser/lightning/activity/TabsManager.java index 0e46366..1c7d0fd 100644 --- a/app/src/main/java/acr/browser/lightning/activity/TabsManager.java +++ b/app/src/main/java/acr/browser/lightning/activity/TabsManager.java @@ -171,6 +171,15 @@ public class TabsManager { return mWebViewList.indexOf(tab); } + /** + * Return the {@link WebView} associated to the current tab, or null if there is no current tab + * @return a {@link WebView} or null + */ + @Nullable + public WebView getCurrentWebView() { + return mCurrentTab != null ? mCurrentTab.getWebView() : null; + } + /** * TODO We should remove also this * @return From 51f783cea435f01dd5c3f597d857854a31a726b1 Mon Sep 17 00:00:00 2001 From: Stefano Pacifici Date: Mon, 14 Sep 2015 17:58:21 +0200 Subject: [PATCH 05/16] TabsFragment extracted --- .../lightning/activity/BrowserActivity.java | 290 ++++-------------- .../lightning/activity/TabsManager.java | 26 +- .../browser/lightning/app/AppComponent.java | 3 + .../browser/lightning/bus/BrowserEvents.java | 6 + .../acr/browser/lightning/bus/TabEvents.java | 49 +++ .../lightning/fragment/TabsFragment.java | 281 +++++++++++++++++ app/src/main/res/layout/activity_main.xml | 7 +- app/src/main/res/layout/tab_drawer.xml | 6 +- app/src/main/res/layout/tab_strip.xml | 9 + app/src/main/res/layout/toolbar.xml | 7 +- 10 files changed, 447 insertions(+), 237 deletions(-) create mode 100644 app/src/main/java/acr/browser/lightning/bus/TabEvents.java create mode 100644 app/src/main/java/acr/browser/lightning/fragment/TabsFragment.java create mode 100644 app/src/main/res/layout/tab_strip.xml diff --git a/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java b/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java index dfee365..d235410 100644 --- a/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java +++ b/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java @@ -106,6 +106,7 @@ import acr.browser.lightning.R; import acr.browser.lightning.app.BrowserApp; import acr.browser.lightning.bus.BookmarkEvents; import acr.browser.lightning.bus.BrowserEvents; +import acr.browser.lightning.bus.TabEvents; import acr.browser.lightning.constant.BookmarkPage; import acr.browser.lightning.constant.Constants; import acr.browser.lightning.constant.HistoryPage; @@ -113,6 +114,7 @@ import acr.browser.lightning.controller.BrowserController; import acr.browser.lightning.database.BookmarkManager; import acr.browser.lightning.database.HistoryDatabase; import acr.browser.lightning.dialog.BookmarksDialogBuilder; +import acr.browser.lightning.fragment.TabsFragment; import acr.browser.lightning.object.ClickHandler; import acr.browser.lightning.object.SearchAdapter; import acr.browser.lightning.preference.PreferenceManager; @@ -132,7 +134,6 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements private DrawerLayout mDrawerLayout; private FrameLayout mBrowserFrame; private FullscreenHolder mFullscreenContainer; - private RecyclerView mDrawerListLeft; private ViewGroup mDrawerLeft, mDrawerRight, mUiLayout, mToolbarLayout; private RelativeLayout mSearchBar; @@ -144,7 +145,6 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements private View mCustomView; // Adapter - private LightningViewAdapter mTabAdapter; private SearchAdapter mSearchAdapter; // Callback @@ -247,7 +247,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements mUiLayout = (LinearLayout) findViewById(R.id.ui_layout); mProgressBar = (AnimatedProgressBar) findViewById(R.id.progress_view); setupFrameLayoutButton(R.id.new_tab_button, R.id.icon_plus); - mDrawerLeft = (LinearLayout) findViewById(R.id.left_drawer); + mDrawerLeft = (FrameLayout) findViewById(R.id.left_drawer); // Drawer stutters otherwise mDrawerLeft.setLayerType(View.LAYER_TYPE_HARDWARE, null); mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); @@ -267,29 +267,19 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements mHomepage = mPreferences.getHomepage(); - RecyclerView horizontalListView = (RecyclerView) findViewById(R.id.twv_list); - - + final TabsFragment tabsFragment = new TabsFragment(); + final int containerId = mShowTabsInDrawer ? R.id.left_drawer : R.id.tabs_toolbar_container; + final Bundle arguments = new Bundle(); + arguments.putBoolean(TabsFragment.VERTICAL_MODE, mShowTabsInDrawer); + tabsFragment.setArguments(arguments); + getSupportFragmentManager() + .beginTransaction() + .add(containerId, tabsFragment) + .commit(); if (mShowTabsInDrawer) { - mTabAdapter = new LightningViewAdapter(this, R.layout.tab_list_item, tabsManager.getTabsList()); - mDrawerListLeft = (RecyclerView) findViewById(R.id.left_drawer_list); - mDrawerListLeft.setOverScrollMode(View.OVER_SCROLL_IF_CONTENT_SCROLLS); - RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false); - mDrawerListLeft.setLayoutManager(layoutManager); - mDrawerListLeft.setHasFixedSize(true); - mToolbarLayout.removeView(horizontalListView); - } else { - mTabAdapter = new LightningViewAdapter(this, R.layout.tab_list_item_horizontal, tabsManager.getTabsList()); - mDrawerListLeft = horizontalListView; - mDrawerListLeft.setOverScrollMode(View.OVER_SCROLL_NEVER); - mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED, mDrawerLeft); - RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false); - mDrawerListLeft.setLayoutManager(layoutManager); - mDrawerListLeft.setHasFixedSize(true); + mToolbarLayout.removeView(findViewById(R.id.tabs_toolbar_container)); } - mDrawerListLeft.setAdapter(mTabAdapter); - mHistoryDatabase = HistoryDatabase.getInstance(); if (actionBar == null) @@ -872,56 +862,29 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements builder.show(); } - /** - * The click listener for ListView in the navigation drawer - */ - private class DrawerItemClickListener implements OnClickListener { - - @Override - public void onClick(View v) { - final LightningView currentTab = tabsManager.getCurrentTab(); - final int position = mDrawerListLeft.getChildAdapterPosition(v); - final LightningView tab = tabsManager.getTabAtPosition(position); - if (tab != null && currentTab != tab) { - mIsNewIntent = false; - showTab(tab); - } - } - } - - /** - * long click listener for Navigation Drawer - */ - private class DrawerItemLongClickListener implements OnLongClickListener { - - @Override - public boolean onLongClick(View v) { - int position = mDrawerListLeft.getChildAdapterPosition(v); - showCloseDialog(position); - return true; - } - } - /** * displays the WebView contained in the LightningView Also handles the * removal of previous views * - * @param newView the LightningView to show + * @param position the poition of the tab to display */ - private synchronized void showTab(LightningView newView) { + private synchronized void showTab(final int position) { final LightningView currentView = tabsManager.getCurrentTab(); + final LightningView newView = tabsManager.switchToTab(position); + // Set the background color so the color mode color doesn't show through mBrowserFrame.setBackgroundColor(mBackgroundColor); - if (newView == null) { + if (newView == null || currentView == newView) { return; } + mIsNewIntent = false; + final float translation = mToolbarLayout.getTranslationY(); mBrowserFrame.removeAllViews(); if (currentView != null) { currentView.setForegroundTab(false); currentView.onPause(); } - tabsManager.setCurrentTab(newView); final WebView currentWebView = currentView.getWebView(); newView.setForegroundTab(true); if (currentWebView != null) { @@ -1047,15 +1010,17 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements mIdGenerator++; if (show) { - showTab(startingTab); + showTab(tabsManager.size() - 1); } updateTabs(); - new Handler().postDelayed(new Runnable() { - @Override - public void run() { - mDrawerListLeft.smoothScrollToPosition(tabsManager.size() - 1); - } - }, 300); + +// TODO Restore this +// new Handler().postDelayed(new Runnable() { +// @Override +// public void run() { +// mDrawerListLeft.smoothScrollToPosition(tabsManager.size() - 1); +// } +// }, 300); return true; } @@ -1082,14 +1047,14 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements } if (current > position) { tabsManager.deleteTab(position); - showTab(tabsManager.getTabAtPosition(current - 1)); + showTab(current - 1); updateTabs(); tabToDelete.onDestroy(); } else if (tabsManager.size() > position + 1) { if (current == position) { - showTab(tabsManager.getTabAtPosition(position + 1)); + showTab(position + 1); tabsManager.deleteTab(position); - showTab(tabsManager.getTabAtPosition(position)); + showTab(position); updateTabs(); } else { tabsManager.deleteTab(position); @@ -1098,9 +1063,9 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements tabToDelete.onDestroy(); } else if (tabsManager.size() > 1) { if (current == position) { - showTab(tabsManager.getTabAtPosition(position - 1)); + showTab(position - 1); tabsManager.deleteTab(position); - showTab(tabsManager.getTabAtPosition(position - 1)); + showTab(position - 1); updateTabs(); } else { tabsManager.deleteTab(position); @@ -1115,11 +1080,11 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements performExitCleanUp(); tabToDelete.pauseTimers(); tabToDelete.onDestroy(); - mTabAdapter.notifyDataSetChanged(); + eventBus.post(new BrowserEvents.TabsChanged()); finish(); } } - mTabAdapter.notifyDataSetChanged(); + eventBus.post(new BrowserEvents.TabsChanged()); if (mIsNewIntent && isShown) { mIsNewIntent = false; @@ -1167,7 +1132,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements mBrowserFrame.setBackgroundColor(mBackgroundColor); performExitCleanUp(); tabsManager.shutdown(); - mTabAdapter.notifyDataSetChanged(); + eventBus.post(new BrowserEvents.TabsChanged()); finish(); } @@ -1293,157 +1258,6 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements } } - public class LightningViewAdapter extends RecyclerView.Adapter { - - private final Context context; - private final int layoutResourceId; - private List data = null; - private final CloseTabListener mExitListener; - private final Drawable mBackgroundTabDrawable; - private final Drawable mForegroundTabDrawable; - private final Bitmap mForegroundTabBitmap; - private final DrawerItemClickListener mClickListener; - private final DrawerItemLongClickListener mLongClickListener; - private ColorMatrix mColorMatrix; - private Paint mPaint; - private ColorFilter mFilter; - private static final float DESATURATED = 0.5f; - - public LightningViewAdapter(Context context, int layoutResourceId, List data) { - this.layoutResourceId = layoutResourceId; - this.context = context; - this.data = data; - this.mExitListener = new CloseTabListener(); - this.mClickListener = new DrawerItemClickListener(); - this.mLongClickListener = new DrawerItemLongClickListener(); - - if (mShowTabsInDrawer) { - mBackgroundTabDrawable = null; - mForegroundTabBitmap = null; - mForegroundTabDrawable = ThemeUtils.getSelectedBackground(context, mDarkTheme); - } else { - int backgroundColor = Utils.mixTwoColors(ThemeUtils.getPrimaryColor(mActivity), Color.BLACK, 0.75f); - Bitmap backgroundTabBitmap = Bitmap.createBitmap(Utils.dpToPx(175), Utils.dpToPx(30), Bitmap.Config.ARGB_8888); - Utils.drawTrapezoid(new Canvas(backgroundTabBitmap), backgroundColor, true); - mBackgroundTabDrawable = new BitmapDrawable(getResources(), backgroundTabBitmap); - - int foregroundColor = ThemeUtils.getPrimaryColor(context); - mForegroundTabBitmap = Bitmap.createBitmap(Utils.dpToPx(175), Utils.dpToPx(30), Bitmap.Config.ARGB_8888); - Utils.drawTrapezoid(new Canvas(mForegroundTabBitmap), foregroundColor, false); - mForegroundTabDrawable = null; - } - } - - @Override - public LightningViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { - LayoutInflater inflater = LayoutInflater.from(viewGroup.getContext()); - View view = inflater.inflate(layoutResourceId, viewGroup, false); - return new LightningViewHolder(view); - } - - @Override - public void onBindViewHolder(final LightningViewHolder holder, int position) { - holder.exitButton.setTag(position); - holder.exitButton.setOnClickListener(mExitListener); - holder.layout.setOnClickListener(mClickListener); - holder.layout.setOnLongClickListener(mLongClickListener); - - ViewCompat.jumpDrawablesToCurrentState(holder.exitButton); - - LightningView web = data.get(position); - holder.txtTitle.setText(web.getTitle()); - - final Bitmap favicon = web.getFavicon(); - if (web.isForegroundTab()) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - holder.txtTitle.setTextAppearance(R.style.boldText); - } else { - holder.txtTitle.setTextAppearance(context, R.style.boldText); - } - Drawable foregroundDrawable; - if (!mShowTabsInDrawer) { - foregroundDrawable = new BitmapDrawable(getResources(), mForegroundTabBitmap); - if (!isIncognito() && mColorMode) { - foregroundDrawable.setColorFilter(mCurrentUiColor, PorterDuff.Mode.SRC_IN); - } - } else { - foregroundDrawable = mForegroundTabDrawable; - } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { - holder.layout.setBackground(foregroundDrawable); - } else { - holder.layout.setBackgroundDrawable(foregroundDrawable); - } - if (!isIncognito() && mColorMode) { - changeToolbarBackground(favicon, foregroundDrawable); - } - holder.favicon.setImageBitmap(favicon); - } else { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - holder.txtTitle.setTextAppearance(R.style.normalText); - } else { - holder.txtTitle.setTextAppearance(context, R.style.normalText); - } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { - holder.layout.setBackground(mBackgroundTabDrawable); - } else { - holder.layout.setBackgroundDrawable(mBackgroundTabDrawable); - } - holder.favicon.setImageBitmap(getDesaturatedBitmap(favicon)); - } - } - - @Override - public int getItemCount() { - return (data != null) ? data.size() : 0; - } - - public Bitmap getDesaturatedBitmap(Bitmap favicon) { - Bitmap grayscaleBitmap = Bitmap.createBitmap(favicon.getWidth(), - favicon.getHeight(), Bitmap.Config.ARGB_8888); - - Canvas c = new Canvas(grayscaleBitmap); - if (mColorMatrix == null || mFilter == null || mPaint == null) { - mPaint = new Paint(); - mColorMatrix = new ColorMatrix(); - mColorMatrix.setSaturation(DESATURATED); - mFilter = new ColorMatrixColorFilter(mColorMatrix); - mPaint.setColorFilter(mFilter); - } - - c.drawBitmap(favicon, 0, 0, mPaint); - return grayscaleBitmap; - } - - public class LightningViewHolder extends RecyclerView.ViewHolder { - - public LightningViewHolder(View view) { - super(view); - txtTitle = (TextView) view.findViewById(R.id.textTab); - favicon = (ImageView) view.findViewById(R.id.faviconTab); - exit = (ImageView) view.findViewById(R.id.deleteButton); - layout = (LinearLayout) view.findViewById(R.id.tab_item_background); - exitButton = (FrameLayout) view.findViewById(R.id.deleteAction); - exit.setColorFilter(mIconColor, PorterDuff.Mode.SRC_IN); - } - - final TextView txtTitle; - final ImageView favicon; - final ImageView exit; - final FrameLayout exitButton; - final LinearLayout layout; - } - } - - private class CloseTabListener implements OnClickListener { - - @Override - public void onClick(View v) { - deleteTab((int) v.getTag()); - } - - } - /** * Animates the color of the toolbar from one color to another. Optionally animates * the color of the tab background, for use when the tabs are displayed on the top @@ -1684,7 +1498,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements @Override public void updateTabs() { - mTabAdapter.notifyDataSetChanged(); + eventBus.post(new BrowserEvents.TabsChanged()); } /** @@ -2482,5 +2296,33 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements public void closeBookmarks(final BookmarkEvents.CloseBookmarks event) { mDrawerLayout.closeDrawer(mDrawerRight); } + + /** + * The user wants to close a tab + * + * @param event contains the position inside the tabs adapter + */ + @Subscribe + public void closeTab(final TabEvents.CloseTab event) { + deleteTab(event.position); + } + + /** + * The user clicked on a tab, let's show it + * + * @param event contains the tab position in the tabs adapter + */ + public void showTab(final TabEvents.ShowTab event) { + BrowserActivity.this.showTab(event.position); + } + + /** + * The user long pressed on a tab, ask him if he want to close the tab + * + * @param event contains the tab position in the tabs adapter + */ + public void showCloseDialog(final TabEvents.ShowCloseDialog event) { + BrowserActivity.this.showCloseDialog(event.position); + } }; } diff --git a/app/src/main/java/acr/browser/lightning/activity/TabsManager.java b/app/src/main/java/acr/browser/lightning/activity/TabsManager.java index 1c7d0fd..3f3a994 100644 --- a/app/src/main/java/acr/browser/lightning/activity/TabsManager.java +++ b/app/src/main/java/acr/browser/lightning/activity/TabsManager.java @@ -181,7 +181,7 @@ public class TabsManager { } /** - * TODO We should remove also this + * TODO We should remove also this, but probably not * @return */ public LightningView getCurrentTab() { @@ -189,9 +189,27 @@ public class TabsManager { } /** - * TODO We should remove also this + * Switch the current tab to the one at the given position. It returns the selected. After this + * call {@link TabsManager#getCurrentTab()} return the same reference returned by this method if + * position is valid. + * + * @return the selected tab or null if position is out of tabs range */ - public void setCurrentTab(final LightningView tab) { - mCurrentTab = tab; + @Nullable + public LightningView switchToTab(final int position) { + if (position < 0 || position >= mWebViewList.size()) { + return null; + } else { + final LightningView tab = mWebViewList.get(position); + mCurrentTab = tab; + return tab; + } } + +// /** +// * TODO We should remove also this +// */ +// public void setCurrentTab(final LightningView tab) { +// mCurrentTab = tab; +// } } diff --git a/app/src/main/java/acr/browser/lightning/app/AppComponent.java b/app/src/main/java/acr/browser/lightning/app/AppComponent.java index dbaf0bc..a3927bf 100644 --- a/app/src/main/java/acr/browser/lightning/app/AppComponent.java +++ b/app/src/main/java/acr/browser/lightning/app/AppComponent.java @@ -7,6 +7,7 @@ import acr.browser.lightning.constant.BookmarkPage; import acr.browser.lightning.dialog.BookmarksDialogBuilder; import acr.browser.lightning.fragment.BookmarkSettingsFragment; import acr.browser.lightning.fragment.BookmarksFragment; +import acr.browser.lightning.fragment.TabsFragment; import acr.browser.lightning.object.SearchAdapter; import dagger.Component; @@ -28,4 +29,6 @@ public interface AppComponent { void inject(BookmarksDialogBuilder builder); void inject(BookmarkPage bookmarkPage); + + void inject(TabsFragment fragment); } diff --git a/app/src/main/java/acr/browser/lightning/bus/BrowserEvents.java b/app/src/main/java/acr/browser/lightning/bus/BrowserEvents.java index 15ff373..696f103 100644 --- a/app/src/main/java/acr/browser/lightning/bus/BrowserEvents.java +++ b/app/src/main/java/acr/browser/lightning/bus/BrowserEvents.java @@ -41,4 +41,10 @@ public final class BrowserEvents { */ public static class UserPressedBack { } + + /** + * Notify that the user closed or opened a tab + */ + public static class TabsChanged { + } } diff --git a/app/src/main/java/acr/browser/lightning/bus/TabEvents.java b/app/src/main/java/acr/browser/lightning/bus/TabEvents.java new file mode 100644 index 0000000..5fd4118 --- /dev/null +++ b/app/src/main/java/acr/browser/lightning/bus/TabEvents.java @@ -0,0 +1,49 @@ +package acr.browser.lightning.bus; + +/** + * @author Stefano Pacifici + * @date 2015/09/14 + */ +public final class TabEvents { + + private TabEvents() { + // No instances + } + + + /** + * Sended by {@link acr.browser.lightning.fragment.TabsFragment} when the user click on the + * tab exit button + */ + public static class CloseTab { + public final int position; + + public CloseTab(int position) { + this.position = position; + } + } + + /** + * Sended by {@link acr.browser.lightning.fragment.TabsFragment} when the user click on the + * tab itself. + */ + public static class ShowTab { + public final int position; + + public ShowTab(int position) { + this.position = position; + } + } + + /** + * Sended by {@link acr.browser.lightning.fragment.TabsFragment} when the user long press on the + * tab itself. + */ + public static class ShowCloseDialog { + public final int position; + + public ShowCloseDialog(int position) { + this.position = position; + } + } +} diff --git a/app/src/main/java/acr/browser/lightning/fragment/TabsFragment.java b/app/src/main/java/acr/browser/lightning/fragment/TabsFragment.java new file mode 100644 index 0000000..d42aeb3 --- /dev/null +++ b/app/src/main/java/acr/browser/lightning/fragment/TabsFragment.java @@ -0,0 +1,281 @@ +package acr.browser.lightning.fragment; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.ColorFilter; +import android.graphics.ColorMatrix; +import android.graphics.ColorMatrixColorFilter; +import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.support.v4.view.ViewCompat; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.RecyclerView.LayoutManager; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.squareup.otto.Bus; +import com.squareup.otto.Subscribe; + +import java.util.List; + +import javax.inject.Inject; + +import acr.browser.lightning.R; +import acr.browser.lightning.activity.TabsManager; +import acr.browser.lightning.app.BrowserApp; +import acr.browser.lightning.bus.BrowserEvents; +import acr.browser.lightning.bus.TabEvents; +import acr.browser.lightning.utils.ThemeUtils; +import acr.browser.lightning.utils.Utils; +import acr.browser.lightning.view.LightningView; + +/** + * @author Stefano Pacifici based on Anthony C. Restaino's code + * @date 2015/09/14 + */ +public class TabsFragment extends Fragment { + + private static final String TAG = TabsFragment.class.getSimpleName(); + + /** + * Arguments boolean to tell the fragment it is displayed in the drawner or on the tab strip + * If true, the fragment is in the left drawner in the strip otherwise. + */ + public static final String VERTICAL_MODE = TAG + ".VERTICAL_MODE"; + + private boolean mDarkTheme = false; // TODO Only temporary + private int mIconColor = 0; // TODO Only temporary + private boolean mColorMode = true; // TODO Only temporary + private boolean isIncognito = false; // TODO Only temporary + private int mCurrentUiColor = 0; // TODO Only temporary + + private RecyclerView mRecyclerView; + private LightningViewAdapter mTabsAdapter; + + @Inject + TabsManager tabsManager; + + @Inject + Bus bus; + + public TabsFragment() { + BrowserApp.getAppComponent().inject(this); + } + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + final Bundle arguments = getArguments(); + final boolean vertical = arguments.getBoolean(VERTICAL_MODE, true); + final View view; + final LayoutManager layoutManager; + if (vertical) { + view = inflater.inflate(R.layout.tab_drawer, container, false); + layoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false); + } else { + view = inflater.inflate(R.layout.tab_strip, container, false); + layoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false); + } + mRecyclerView = (RecyclerView) view.findViewById(R.id.tabs_list); + mRecyclerView.setLayoutManager(layoutManager); + mTabsAdapter = new LightningViewAdapter(vertical); + mRecyclerView.setAdapter(mTabsAdapter); + mRecyclerView.setHasFixedSize(true); + return view; + } + + @Override + public void onDestroyView() { + mRecyclerView = null; + mTabsAdapter = null; + } + + @Override + public void onStart() { + super.onStart(); + bus.register(this); + } + + @Override + public void onStop() { + super.onStop(); + bus.unregister(this); + } + + @Subscribe + public void tabsChanged(final BrowserEvents.TabsChanged event) { + if (mTabsAdapter != null) { + mTabsAdapter.notifyDataSetChanged(); + } + } + + public class LightningViewAdapter extends RecyclerView.Adapter { + + private final int layoutResourceId; + private final Drawable mBackgroundTabDrawable; + private final Drawable mForegroundTabDrawable; + private final Bitmap mForegroundTabBitmap; + private ColorMatrix mColorMatrix; + private Paint mPaint; + private ColorFilter mFilter; + private static final float DESATURATED = 0.5f; + + private final boolean vertical; + + public LightningViewAdapter(final boolean vertical) { + this.layoutResourceId = vertical ? R.layout.tab_list_item : R.layout.tab_list_item_horizontal; + this.vertical = vertical; + + if (vertical) { + mBackgroundTabDrawable = null; + mForegroundTabBitmap = null; + mForegroundTabDrawable = ThemeUtils.getSelectedBackground(getContext(), mDarkTheme); + } else { + int backgroundColor = Utils.mixTwoColors(ThemeUtils.getPrimaryColor(getContext()), Color.BLACK, 0.75f); + Bitmap backgroundTabBitmap = Bitmap.createBitmap(Utils.dpToPx(175), Utils.dpToPx(30), Bitmap.Config.ARGB_8888); + Utils.drawTrapezoid(new Canvas(backgroundTabBitmap), backgroundColor, true); + mBackgroundTabDrawable = new BitmapDrawable(getResources(), backgroundTabBitmap); + + int foregroundColor = ThemeUtils.getPrimaryColor(getContext()); + mForegroundTabBitmap = Bitmap.createBitmap(Utils.dpToPx(175), Utils.dpToPx(30), Bitmap.Config.ARGB_8888); + Utils.drawTrapezoid(new Canvas(mForegroundTabBitmap), foregroundColor, false); + mForegroundTabDrawable = null; + } + } + + @Override + public LightningViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { + LayoutInflater inflater = LayoutInflater.from(viewGroup.getContext()); + View view = inflater.inflate(layoutResourceId, viewGroup, false); + return new LightningViewHolder(view); + } + + @Override + public void onBindViewHolder(final LightningViewHolder holder, int position) { + holder.exitButton.setTag(position); + + ViewCompat.jumpDrawablesToCurrentState(holder.exitButton); + + LightningView web = tabsManager.getTabAtPosition(position); + holder.txtTitle.setText(web.getTitle()); + + final Bitmap favicon = web.getFavicon(); + if (web.isForegroundTab()) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + holder.txtTitle.setTextAppearance(R.style.boldText); + } else { + holder.txtTitle.setTextAppearance(getContext(), R.style.boldText); + } + Drawable foregroundDrawable; + if (!vertical) { + foregroundDrawable = new BitmapDrawable(getResources(), mForegroundTabBitmap); + if (!isIncognito && mColorMode) { + foregroundDrawable.setColorFilter(mCurrentUiColor, PorterDuff.Mode.SRC_IN); + } + } else { + foregroundDrawable = mForegroundTabDrawable; + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + holder.layout.setBackground(foregroundDrawable); + } else { + holder.layout.setBackgroundDrawable(foregroundDrawable); + } + if (!isIncognito && mColorMode) { + // TODO Restore this + // changeToolbarBackground(favicon, foregroundDrawable); + } + holder.favicon.setImageBitmap(favicon); + } else { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + holder.txtTitle.setTextAppearance(R.style.normalText); + } else { + holder.txtTitle.setTextAppearance(getContext(), R.style.normalText); + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + holder.layout.setBackground(mBackgroundTabDrawable); + } else { + holder.layout.setBackgroundDrawable(mBackgroundTabDrawable); + } + holder.favicon.setImageBitmap(getDesaturatedBitmap(favicon)); + } + } + + @Override + public int getItemCount() { + return tabsManager.size(); + } + + public Bitmap getDesaturatedBitmap(Bitmap favicon) { + Bitmap grayscaleBitmap = Bitmap.createBitmap(favicon.getWidth(), + favicon.getHeight(), Bitmap.Config.ARGB_8888); + + Canvas c = new Canvas(grayscaleBitmap); + if (mColorMatrix == null || mFilter == null || mPaint == null) { + mPaint = new Paint(); + mColorMatrix = new ColorMatrix(); + mColorMatrix.setSaturation(DESATURATED); + mFilter = new ColorMatrixColorFilter(mColorMatrix); + mPaint.setColorFilter(mFilter); + } + + c.drawBitmap(favicon, 0, 0, mPaint); + return grayscaleBitmap; + } + + public class LightningViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener { + + public LightningViewHolder(View view) { + super(view); + txtTitle = (TextView) view.findViewById(R.id.textTab); + favicon = (ImageView) view.findViewById(R.id.faviconTab); + exit = (ImageView) view.findViewById(R.id.deleteButton); + layout = (LinearLayout) view.findViewById(R.id.tab_item_background); + exitButton = (FrameLayout) view.findViewById(R.id.deleteAction); + exit.setColorFilter(mIconColor, PorterDuff.Mode.SRC_IN); + + exitButton.setOnClickListener(this); + layout.setOnClickListener(this); + layout.setOnLongClickListener(this); + } + + final TextView txtTitle; + final ImageView favicon; + final ImageView exit; + final FrameLayout exitButton; + final LinearLayout layout; + + @Override + public void onClick(View v) { + if (v == exitButton) { + // Close tab + bus.post(new TabEvents.CloseTab(getAdapterPosition())); + } + if (v == layout) { + bus.post(new TabEvents.ShowTab(getAdapterPosition())); + } + } + + @Override + public boolean onLongClick(View v) { + // Show close dialog + bus.post(new TabEvents.ShowCloseDialog(getAdapterPosition())); + return true; + } + } + } + +} diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 31777df..655df01 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -25,7 +25,12 @@ - + + android:dividerHeight="0dp" + android:overScrollMode="ifContentScrolls" /> + + diff --git a/app/src/main/res/layout/toolbar.xml b/app/src/main/res/layout/toolbar.xml index 9b144f3..cc0fbcb 100644 --- a/app/src/main/res/layout/toolbar.xml +++ b/app/src/main/res/layout/toolbar.xml @@ -8,13 +8,10 @@ android:elevation="2dp" android:orientation="vertical"> - + android:id="@+id/tabs_toolbar_container"/> Date: Tue, 15 Sep 2015 14:24:31 +0200 Subject: [PATCH 06/16] In the middle of events rewiring (back/forward) --- .../lightning/activity/BrowserActivity.java | 76 ++++++++++--------- .../lightning/activity/TabsManager.java | 9 +-- .../lightning/bus/NavigationEvents.java | 25 ++++++ .../acr/browser/lightning/bus/TabEvents.java | 7 ++ .../lightning/fragment/TabsFragment.java | 49 +++++++++++- app/src/main/res/layout/activity_main.xml | 4 +- app/src/main/res/layout/tab_drawer.xml | 4 +- 7 files changed, 127 insertions(+), 47 deletions(-) create mode 100644 app/src/main/java/acr/browser/lightning/bus/NavigationEvents.java diff --git a/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java b/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java index d235410..93a5221 100644 --- a/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java +++ b/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java @@ -235,8 +235,6 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements mShowTabsInDrawer = mPreferences.getShowTabsInDrawer(!isTablet()); mActivity = this; - // TODO Stefano, check this - // mWebViewList.clear(); mClickHandler = new ClickHandler(this); mBrowserFrame = (FrameLayout) findViewById(R.id.content_frame); @@ -246,15 +244,15 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements mUiLayout = (LinearLayout) findViewById(R.id.ui_layout); mProgressBar = (AnimatedProgressBar) findViewById(R.id.progress_view); - setupFrameLayoutButton(R.id.new_tab_button, R.id.icon_plus); mDrawerLeft = (FrameLayout) findViewById(R.id.left_drawer); // Drawer stutters otherwise mDrawerLeft.setLayerType(View.LAYER_TYPE_HARDWARE, null); mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); mDrawerRight = (ViewGroup) findViewById(R.id.right_drawer); mDrawerRight.setLayerType(View.LAYER_TYPE_HARDWARE, null); - ImageView tabTitleImage = (ImageView) findViewById(R.id.plusIcon); - tabTitleImage.setColorFilter(mIconColor, PorterDuff.Mode.SRC_IN); +// TODO Probably should be moved to the TabsFragement +// ImageView tabTitleImage = (ImageView) findViewById(R.id.plusIcon); +// tabTitleImage.setColorFilter(mIconColor, PorterDuff.Mode.SRC_IN); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && !mShowTabsInDrawer) { getWindow().setStatusBarColor(Color.BLACK); @@ -313,10 +311,8 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements mProxyUtils = ProxyUtils.getInstance(); - setupFrameLayoutButton(R.id.action_back, R.id.icon_back); - setupFrameLayoutButton(R.id.action_forward, R.id.icon_forward); - setupFrameLayoutButton(R.id.action_toggle_desktop, R.id.icon_desktop); setupFrameLayoutButton(R.id.action_reading, R.id.icon_reading); + setupFrameLayoutButton(R.id.action_toggle_desktop, R.id.icon_desktop); // create the search EditText in the ToolBar mSearch = (AutoCompleteTextView) actionBar.getCustomView().findViewById(R.id.search); @@ -870,7 +866,9 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements */ private synchronized void showTab(final int position) { final LightningView currentView = tabsManager.getCurrentTab(); + final WebView currentWebView = currentView != null ? currentView.getWebView() : null; final LightningView newView = tabsManager.switchToTab(position); + final WebView newWebView = newView != null ? newView.getWebView() : null; // Set the background color so the color mode color doesn't show through mBrowserFrame.setBackgroundColor(mBackgroundColor); @@ -885,7 +883,6 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements currentView.setForegroundTab(false); currentView.onPause(); } - final WebView currentWebView = currentView.getWebView(); newView.setForegroundTab(true); if (currentWebView != null) { updateUrl(newView.getUrl(), true); @@ -895,7 +892,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements updateProgress(0); } - mBrowserFrame.addView(currentWebView, MATCH_PARENT); + mBrowserFrame.addView(newWebView, MATCH_PARENT); newView.requestFocus(); newView.onResume(); @@ -909,10 +906,10 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements mToolbarLayout.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED); height = mToolbarLayout.getMeasuredHeight(); } - currentWebView.setTranslationY(translation + height); + newWebView.setTranslationY(translation + height); mToolbarLayout.setTranslationY(translation); } else { - currentWebView.setTranslationY(0); + newWebView.setTranslationY(0); } showActionBar(); @@ -2102,22 +2099,23 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements final LightningView currentTab = tabsManager.getCurrentTab(); final WebView currentWebView = currentTab.getWebView(); switch (v.getId()) { - case R.id.action_back: - if (currentTab != null) { - if (currentTab.canGoBack()) { - currentTab.goBack(); - } else { - deleteTab(tabsManager.positionOf(currentTab)); - } - } - break; - case R.id.action_forward: - if (currentTab != null) { - if (currentTab.canGoForward()) { - currentTab.goForward(); - } - } - break; +// TODO Remove this +// case R.id.action_back: +// if (currentTab != null) { +// if (currentTab.canGoBack()) { +// currentTab.goBack(); +// } else { +// deleteTab(tabsManager.positionOf(currentTab)); +// } +// } +// break; +// case R.id.action_forward: +// if (currentTab != null) { +// if (currentTab.canGoForward()) { +// currentTab.goForward(); +// } +// } +// break; case R.id.arrow_button: if (mSearch != null && mSearch.hasFocus()) { currentTab.requestFocus(); @@ -2127,9 +2125,6 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements currentTab.loadHomepage(); } break; - case R.id.new_tab_button: - newTab(null, true); - break; case R.id.button_next: currentWebView.findNext(false); break; @@ -2168,11 +2163,12 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements return true; } + // TODO Check if all the calls are relative to TabsFragement private void setupFrameLayoutButton(@IdRes int buttonId, @IdRes int imageId) { - View frameButton = findViewById(buttonId); + final View frameButton = findViewById(buttonId); + final ImageView buttonImage = (ImageView) findViewById(imageId); frameButton.setOnClickListener(this); frameButton.setOnLongClickListener(this); - ImageView buttonImage = (ImageView) findViewById(imageId); buttonImage.setColorFilter(mIconColor, PorterDuff.Mode.SRC_IN); } @@ -2219,7 +2215,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements */ @Subscribe public void loadBookmarkInNewTab(final BookmarkEvents.AsNewTab event) { - newTab(event.bookmark.getUrl(), true); + BrowserActivity.this.newTab(event.bookmark.getUrl(), true); mDrawerLayout.closeDrawers(); } @@ -2312,6 +2308,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements * * @param event contains the tab position in the tabs adapter */ + @Subscribe public void showTab(final TabEvents.ShowTab event) { BrowserActivity.this.showTab(event.position); } @@ -2321,8 +2318,19 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements * * @param event contains the tab position in the tabs adapter */ + @Subscribe public void showCloseDialog(final TabEvents.ShowCloseDialog event) { BrowserActivity.this.showCloseDialog(event.position); } + + /** + * The user wants to create a new tab + * + * @param event a marker + */ + @Subscribe + public void newTab(final TabEvents.NewTab event) { + BrowserActivity.this.newTab(null, true); + } }; } diff --git a/app/src/main/java/acr/browser/lightning/activity/TabsManager.java b/app/src/main/java/acr/browser/lightning/activity/TabsManager.java index 3f3a994..d4cf26b 100644 --- a/app/src/main/java/acr/browser/lightning/activity/TabsManager.java +++ b/app/src/main/java/acr/browser/lightning/activity/TabsManager.java @@ -9,6 +9,7 @@ import java.util.ArrayList; import java.util.List; import javax.inject.Inject; +import javax.inject.Singleton; import acr.browser.lightning.controller.BrowserController; import acr.browser.lightning.view.LightningView; @@ -17,6 +18,7 @@ import acr.browser.lightning.view.LightningView; * @author Stefano Pacifici * @date 2015/09/14 */ +@Singleton public class TabsManager { private final List mWebViewList = new ArrayList<>(); @@ -205,11 +207,4 @@ public class TabsManager { return tab; } } - -// /** -// * TODO We should remove also this -// */ -// public void setCurrentTab(final LightningView tab) { -// mCurrentTab = tab; -// } } diff --git a/app/src/main/java/acr/browser/lightning/bus/NavigationEvents.java b/app/src/main/java/acr/browser/lightning/bus/NavigationEvents.java new file mode 100644 index 0000000..2bdaded --- /dev/null +++ b/app/src/main/java/acr/browser/lightning/bus/NavigationEvents.java @@ -0,0 +1,25 @@ +package acr.browser.lightning.bus; + +/** + * @author Stefano Pacifici + * @date 2015/09/15 + */ +public class NavigationEvents { + private NavigationEvents() { + // No instances please + } + + /** + * Fired by {@link acr.browser.lightning.fragment.TabsFragment} when the user presses back + * button. + */ + public static class GoBack { + } + + /** + * Fired by {@link acr.browser.lightning.fragment.TabsFragment} when teh user presses forward + * button. + */ + public static class GoForward { + } +} diff --git a/app/src/main/java/acr/browser/lightning/bus/TabEvents.java b/app/src/main/java/acr/browser/lightning/bus/TabEvents.java index 5fd4118..f219da6 100644 --- a/app/src/main/java/acr/browser/lightning/bus/TabEvents.java +++ b/app/src/main/java/acr/browser/lightning/bus/TabEvents.java @@ -46,4 +46,11 @@ public final class TabEvents { this.position = position; } } + + /** + * Sended by {@link acr.browser.lightning.fragment.TabsFragment} when the user want to create a + * new tab. + */ + public static class NewTab { + } } diff --git a/app/src/main/java/acr/browser/lightning/fragment/TabsFragment.java b/app/src/main/java/acr/browser/lightning/fragment/TabsFragment.java index d42aeb3..7a2a30c 100644 --- a/app/src/main/java/acr/browser/lightning/fragment/TabsFragment.java +++ b/app/src/main/java/acr/browser/lightning/fragment/TabsFragment.java @@ -13,6 +13,8 @@ import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Bundle; +import android.support.annotation.IdRes; +import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.support.v4.view.ViewCompat; @@ -38,6 +40,7 @@ import acr.browser.lightning.R; import acr.browser.lightning.activity.TabsManager; import acr.browser.lightning.app.BrowserApp; import acr.browser.lightning.bus.BrowserEvents; +import acr.browser.lightning.bus.NavigationEvents; import acr.browser.lightning.bus.TabEvents; import acr.browser.lightning.utils.ThemeUtils; import acr.browser.lightning.utils.Utils; @@ -47,7 +50,7 @@ import acr.browser.lightning.view.LightningView; * @author Stefano Pacifici based on Anthony C. Restaino's code * @date 2015/09/14 */ -public class TabsFragment extends Fragment { +public class TabsFragment extends Fragment implements View.OnClickListener, View.OnLongClickListener { private static final String TAG = TabsFragment.class.getSimpleName(); @@ -86,6 +89,11 @@ public class TabsFragment extends Fragment { if (vertical) { view = inflater.inflate(R.layout.tab_drawer, container, false); layoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false); + // TODO Handle also long press + setupFrameLayoutButton(view, R.id.new_tab_button, R.id.icon_plus); + setupFrameLayoutButton(view, R.id.action_back, R.id.icon_back); + setupFrameLayoutButton(view, R.id.action_forward, R.id.icon_forward); + } else { view = inflater.inflate(R.layout.tab_strip, container, false); layoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false); @@ -98,6 +106,15 @@ public class TabsFragment extends Fragment { return view; } + private void setupFrameLayoutButton(@NonNull final View root, @IdRes final int buttonId, + @IdRes final int imageId) { + final View frameButton = root.findViewById(buttonId); + final ImageView buttonImage = (ImageView) root.findViewById(imageId); + frameButton.setOnClickListener(this); + frameButton.setOnLongClickListener(this); + buttonImage.setColorFilter(mIconColor, PorterDuff.Mode.SRC_IN); + } + @Override public void onDestroyView() { mRecyclerView = null; @@ -110,6 +127,13 @@ public class TabsFragment extends Fragment { bus.register(this); } + @Override + public void onResume() { + super.onResume(); + // Force adapter refresh + mTabsAdapter.notifyDataSetChanged(); + } + @Override public void onStop() { super.onStop(); @@ -123,6 +147,28 @@ public class TabsFragment extends Fragment { } } + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.new_tab_button: + bus.post(new TabEvents.NewTab()); + break; + case R.id.action_back: + bus.post(new NavigationEvents.GoBack()); + break; + case R.id.action_forward: + bus.post(new NavigationEvents.GoForward()); + break; + default: + break; + } + } + + @Override + public boolean onLongClick(View v) { + return false; + } + public class LightningViewAdapter extends RecyclerView.Adapter { private final int layoutResourceId; @@ -277,5 +323,4 @@ public class TabsFragment extends Fragment { } } } - } diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 655df01..5f87668 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -30,7 +30,9 @@ android:layout_height="match_parent" android:background="?attr/drawerBackground" android:id="@+id/left_drawer" - android:fitsSystemWindows="true" /> + android:fitsSystemWindows="true" + android:layout_gravity="start" + android:weightSum="1" /> Date: Tue, 15 Sep 2015 16:10:34 +0200 Subject: [PATCH 07/16] Back, Forward and Plus rewired --- .../lightning/activity/BrowserActivity.java | 76 ++++++++++++------- .../browser/lightning/bus/BookmarkEvents.java | 7 -- .../browser/lightning/bus/BrowserEvents.java | 5 +- .../lightning/bus/NavigationEvents.java | 2 + .../acr/browser/lightning/bus/TabEvents.java | 9 +++ .../lightning/fragment/TabsFragment.java | 25 +++++- 6 files changed, 84 insertions(+), 40 deletions(-) diff --git a/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java b/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java index 93a5221..1309e9e 100644 --- a/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java +++ b/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java @@ -106,6 +106,7 @@ import acr.browser.lightning.R; import acr.browser.lightning.app.BrowserApp; import acr.browser.lightning.bus.BookmarkEvents; import acr.browser.lightning.bus.BrowserEvents; +import acr.browser.lightning.bus.NavigationEvents; import acr.browser.lightning.bus.TabEvents; import acr.browser.lightning.constant.BookmarkPage; import acr.browser.lightning.constant.Constants; @@ -269,6 +270,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements final int containerId = mShowTabsInDrawer ? R.id.left_drawer : R.id.tabs_toolbar_container; final Bundle arguments = new Bundle(); arguments.putBoolean(TabsFragment.VERTICAL_MODE, mShowTabsInDrawer); + arguments.putBoolean(TabsFragment.USE_DARK_THEME, mDarkTheme); tabsFragment.setArguments(arguments); getSupportFragmentManager() .beginTransaction() @@ -2099,23 +2101,6 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements final LightningView currentTab = tabsManager.getCurrentTab(); final WebView currentWebView = currentTab.getWebView(); switch (v.getId()) { -// TODO Remove this -// case R.id.action_back: -// if (currentTab != null) { -// if (currentTab.canGoBack()) { -// currentTab.goBack(); -// } else { -// deleteTab(tabsManager.positionOf(currentTab)); -// } -// } -// break; -// case R.id.action_forward: -// if (currentTab != null) { -// if (currentTab.canGoForward()) { -// currentTab.goForward(); -// } -// } -// break; case R.id.arrow_button: if (mSearch != null && mSearch.hasFocus()) { currentTab.requestFocus(); @@ -2150,16 +2135,6 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements @Override public boolean onLongClick(View view) { - switch (view.getId()) { - case R.id.new_tab_button: - String url = mPreferences.getSavedUrl(); - if (url != null) { - newTab(url, true); - Utils.showSnackbar(mActivity, R.string.deleted_tab); - } - mPreferences.setSavedUrl(null); - break; - } return true; } @@ -2332,5 +2307,52 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements public void newTab(final TabEvents.NewTab event) { BrowserActivity.this.newTab(null, true); } + + /** + * The user wants to go back on current tab + * + * @param event a marker + */ + @Subscribe + public void goBack(final NavigationEvents.GoBack event) { + final LightningView currentTab = tabsManager.getCurrentTab(); + if (currentTab != null) { + if (currentTab.canGoBack()) { + currentTab.goBack(); + } else { + deleteTab(tabsManager.positionOf(currentTab)); + } + } + } + + /** + * The user wants to go forward on current tab + * + * @param event a marker + */ + @Subscribe + public void goForward(final NavigationEvents.GoForward event) { + final LightningView currentTab = tabsManager.getCurrentTab(); + if (currentTab != null) { + if (currentTab.canGoForward()) { + currentTab.goForward(); + } + } + } + + /** + * The user long pressed the new tab button + * + * @param event a marker + */ + @Subscribe + public void newTabLongPress(final TabEvents.NewTabLongPress event) { + String url = mPreferences.getSavedUrl(); + if (url != null) { + BrowserActivity.this.newTab(url, true); + Utils.showSnackbar(mActivity, R.string.deleted_tab); + } + mPreferences.setSavedUrl(null); + } }; } diff --git a/app/src/main/java/acr/browser/lightning/bus/BookmarkEvents.java b/app/src/main/java/acr/browser/lightning/bus/BookmarkEvents.java index 3331eb7..7b8846d 100644 --- a/app/src/main/java/acr/browser/lightning/bus/BookmarkEvents.java +++ b/app/src/main/java/acr/browser/lightning/bus/BookmarkEvents.java @@ -61,13 +61,6 @@ public final class BookmarkEvents { } } - /** - * The {@link acr.browser.lightning.fragment.BookmarksFragment} want to know the url (and title) - * of the currently shown web page. - */ - // public static class WantInfoAboutCurrentPage { - // } - /** * Sended by the {@link acr.browser.lightning.fragment.BookmarksFragment} when it wants to close * itself (generally in reply to a {@link acr.browser.lightning.bus.BrowserEvents.UserPressedBack} diff --git a/app/src/main/java/acr/browser/lightning/bus/BrowserEvents.java b/app/src/main/java/acr/browser/lightning/bus/BrowserEvents.java index 696f103..d461205 100644 --- a/app/src/main/java/acr/browser/lightning/bus/BrowserEvents.java +++ b/app/src/main/java/acr/browser/lightning/bus/BrowserEvents.java @@ -24,9 +24,8 @@ public final class BrowserEvents { } /** - * Used to reply to {@link acr.browser.lightning.fragment.BookmarksFragment} message - * {@link acr.browser.lightning.bus.BookmarkEvents.WantInfoAboutCurrentPage}. This is generally - * used to update the {@link acr.browser.lightning.fragment.BookmarksFragment} interface. + * Notify the current page has a new url. This is generally used to update the + * {@link acr.browser.lightning.fragment.BookmarksFragment} interface. */ public static class CurrentPageUrl { public final String url; diff --git a/app/src/main/java/acr/browser/lightning/bus/NavigationEvents.java b/app/src/main/java/acr/browser/lightning/bus/NavigationEvents.java index 2bdaded..732ca23 100644 --- a/app/src/main/java/acr/browser/lightning/bus/NavigationEvents.java +++ b/app/src/main/java/acr/browser/lightning/bus/NavigationEvents.java @@ -1,6 +1,8 @@ package acr.browser.lightning.bus; /** + * Collections of navigation events, like go back or go forward + * * @author Stefano Pacifici * @date 2015/09/15 */ diff --git a/app/src/main/java/acr/browser/lightning/bus/TabEvents.java b/app/src/main/java/acr/browser/lightning/bus/TabEvents.java index f219da6..a2bac5c 100644 --- a/app/src/main/java/acr/browser/lightning/bus/TabEvents.java +++ b/app/src/main/java/acr/browser/lightning/bus/TabEvents.java @@ -1,6 +1,8 @@ package acr.browser.lightning.bus; /** + * A collection of events been sent by {@link acr.browser.lightning.fragment.TabsFragment} + * * @author Stefano Pacifici * @date 2015/09/14 */ @@ -53,4 +55,11 @@ public final class TabEvents { */ public static class NewTab { } + + /** + * Sended by {@link acr.browser.lightning.fragment.TabsFragment} when the user long presses on + * new tab button. + */ + public static class NewTabLongPress { + } } diff --git a/app/src/main/java/acr/browser/lightning/fragment/TabsFragment.java b/app/src/main/java/acr/browser/lightning/fragment/TabsFragment.java index 7a2a30c..43738f1 100644 --- a/app/src/main/java/acr/browser/lightning/fragment/TabsFragment.java +++ b/app/src/main/java/acr/browser/lightning/fragment/TabsFragment.java @@ -59,9 +59,10 @@ public class TabsFragment extends Fragment implements View.OnClickListener, View * If true, the fragment is in the left drawner in the strip otherwise. */ public static final String VERTICAL_MODE = TAG + ".VERTICAL_MODE"; + public static final String USE_DARK_THEME = TAG + ".USE_DARK_THEME"; - private boolean mDarkTheme = false; // TODO Only temporary - private int mIconColor = 0; // TODO Only temporary + private boolean mDarkTheme; + private int mIconColor; private boolean mColorMode = true; // TODO Only temporary private boolean isIncognito = false; // TODO Only temporary private int mCurrentUiColor = 0; // TODO Only temporary @@ -79,6 +80,17 @@ public class TabsFragment extends Fragment implements View.OnClickListener, View BrowserApp.getAppComponent().inject(this); } + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + final Bundle arguments = getArguments(); + final Context context = getContext(); + mDarkTheme = arguments.getBoolean(USE_DARK_THEME, false); + mIconColor = mDarkTheme ? + ThemeUtils.getIconDarkThemeColor(context) : + ThemeUtils.getIconLightThemeColor(context); + } + @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -166,7 +178,14 @@ public class TabsFragment extends Fragment implements View.OnClickListener, View @Override public boolean onLongClick(View v) { - return false; + switch (v.getId()) { + case R.id.action_new_tab: + bus.post(new TabEvents.NewTabLongPress()); + break; + default: + break; + } + return true; } public class LightningViewAdapter extends RecyclerView.Adapter { From 5c2cf07e20211a25e6a3418acaa6fef8a1ea6857 Mon Sep 17 00:00:00 2001 From: Stefano Pacifici Date: Wed, 16 Sep 2015 16:49:59 +0200 Subject: [PATCH 08/16] PreferenceManager injected --- .../browser/lightning/utils/ProxyUtils.java | 2 +- .../lightning/activity/BrowserActivity.java | 15 +-- .../lightning/activity/IncognitoActivity.java | 10 +- .../lightning/activity/MainActivity.java | 12 +- .../lightning/activity/ReadingActivity.java | 3 +- .../lightning/activity/TabsManager.java | 3 +- .../activity/ThemableBrowserActivity.java | 8 +- .../activity/ThemableSettingsActivity.java | 5 +- .../browser/lightning/app/AppComponent.java | 6 + .../browser/lightning/constant/StartPage.java | 5 +- .../lightning/download/DownloadHandler.java | 3 +- .../fragment/AdvancedSettingsFragment.java | 39 +++---- .../lightning/fragment/BookmarksFragment.java | 4 +- .../fragment/DisplaySettingsFragment.java | 40 ++++--- .../fragment/GeneralSettingsFragment.java | 104 +++++++++--------- .../fragment/LightningPreferenceFragment.java | 27 +++++ .../fragment/PrivacySettingsFragment.java | 34 +++--- .../lightning/fragment/TabsFragment.java | 1 + .../lightning/object/SearchAdapter.java | 5 +- .../preference/PreferenceManager.java | 18 ++- .../acr/browser/lightning/utils/AdBlock.java | 5 +- .../browser/lightning/view/LightningView.java | 8 +- 22 files changed, 194 insertions(+), 163 deletions(-) create mode 100644 app/src/main/java/acr/browser/lightning/fragment/LightningPreferenceFragment.java diff --git a/app/src/LightningPlus/java/acr/browser/lightning/utils/ProxyUtils.java b/app/src/LightningPlus/java/acr/browser/lightning/utils/ProxyUtils.java index 269c185..3942f7d 100644 --- a/app/src/LightningPlus/java/acr/browser/lightning/utils/ProxyUtils.java +++ b/app/src/LightningPlus/java/acr/browser/lightning/utils/ProxyUtils.java @@ -28,7 +28,7 @@ public class ProxyUtils { private static ProxyUtils mInstance; private ProxyUtils(Context context) { - mPreferences = PreferenceManager.getInstance(); + mPreferences = BrowserApp.getAppComponent().getPreferenceManager(); mI2PHelper = new I2PAndroidHelper(context.getApplicationContext()); } diff --git a/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java b/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java index 1309e9e..2831051 100644 --- a/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java +++ b/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java @@ -169,7 +169,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements // Storage private HistoryDatabase mHistoryDatabase; - private PreferenceManager mPreferences; + // The singleton BookmarkManager @Inject @@ -188,6 +188,9 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements @Inject TabsManager tabsManager; + @Inject + PreferenceManager mPreferences; + // Image private Bitmap mWebpageBitmap; private final ColorDrawable mBackground = new ColorDrawable(); @@ -207,7 +210,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements public abstract boolean isIncognito(); - abstract void initializeTabs(); +// abstract void initializeTabs(); abstract void closeActivity(); @@ -229,7 +232,6 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements setSupportActionBar(toolbar); ActionBar actionBar = getSupportActionBar(); - mPreferences = PreferenceManager.getInstance(); //TODO make sure dark theme flag gets set correctly mDarkTheme = mPreferences.getUseTheme() != 0 || isIncognito(); mIconColor = mDarkTheme ? ThemeUtils.getIconDarkThemeColor(this) : ThemeUtils.getIconLightThemeColor(this); @@ -356,7 +358,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements WebIconDatabase.getInstance().open(getDir("icons", MODE_PRIVATE).getPath()); } - initializeTabs(); +// initializeTabs(); mProxyUtils.checkForProxy(this); } @@ -565,6 +567,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements } } + /* TODO !!!! THIS MUST BY RESTORED ASAP !!!! void restoreOrNewTab() { mIdGenerator = 0; @@ -601,13 +604,11 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements newTab(url, true); } } + */ private void initializePreferences() { final LightningView currentView = tabsManager.getCurrentTab(); final WebView currentWebView = currentView.getWebView(); - if (mPreferences == null) { - mPreferences = PreferenceManager.getInstance(); - } mFullScreen = mPreferences.getFullScreenEnabled(); mColorMode = mPreferences.getColorModeEnabled(); mColorMode &= !mDarkTheme; diff --git a/app/src/main/java/acr/browser/lightning/activity/IncognitoActivity.java b/app/src/main/java/acr/browser/lightning/activity/IncognitoActivity.java index b7be9d3..b46e42f 100644 --- a/app/src/main/java/acr/browser/lightning/activity/IncognitoActivity.java +++ b/app/src/main/java/acr/browser/lightning/activity/IncognitoActivity.java @@ -18,13 +18,13 @@ public class IncognitoActivity extends BrowserActivity { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { CookieSyncManager.createInstance(this); } - cookieManager.setAcceptCookie(PreferenceManager.getInstance().getIncognitoCookiesEnabled()); + cookieManager.setAcceptCookie(mPreferences.getIncognitoCookiesEnabled()); } - @Override - public synchronized void initializeTabs() { - newTab(null, true); - } +// @Override +// public synchronized void initializeTabs() { +// newTab(null, true); +// } @Override public boolean onCreateOptionsMenu(Menu menu) { diff --git a/app/src/main/java/acr/browser/lightning/activity/MainActivity.java b/app/src/main/java/acr/browser/lightning/activity/MainActivity.java index 68d6022..808ea0c 100644 --- a/app/src/main/java/acr/browser/lightning/activity/MainActivity.java +++ b/app/src/main/java/acr/browser/lightning/activity/MainActivity.java @@ -18,14 +18,14 @@ public class MainActivity extends BrowserActivity { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { CookieSyncManager.createInstance(this); } - cookieManager.setAcceptCookie(PreferenceManager.getInstance().getCookiesEnabled()); + cookieManager.setAcceptCookie(mPreferences.getCookiesEnabled()); } - @Override - public synchronized void initializeTabs() { - restoreOrNewTab(); - // if incognito mode use newTab(null, true); instead - } +// @Override +// public synchronized void initializeTabs() { +// // restoreOrNewTab(); +// // if incognito mode use newTab(null, true); instead +// } @Override public boolean onCreateOptionsMenu(Menu menu) { diff --git a/app/src/main/java/acr/browser/lightning/activity/ReadingActivity.java b/app/src/main/java/acr/browser/lightning/activity/ReadingActivity.java index 8474e85..e1847b6 100644 --- a/app/src/main/java/acr/browser/lightning/activity/ReadingActivity.java +++ b/app/src/main/java/acr/browser/lightning/activity/ReadingActivity.java @@ -22,6 +22,7 @@ import android.widget.SeekBar.OnSeekBarChangeListener; import android.widget.TextView; import acr.browser.lightning.R; +import acr.browser.lightning.app.BrowserApp; import acr.browser.lightning.constant.Constants; import acr.browser.lightning.preference.PreferenceManager; import acr.browser.lightning.reading.HtmlFetcher; @@ -49,7 +50,7 @@ public class ReadingActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { overridePendingTransition(R.anim.slide_in_from_right, R.anim.fade_out_scale); - mPreferences = PreferenceManager.getInstance(); + mPreferences = BrowserApp.getAppComponent().getPreferenceManager(); mInvert = mPreferences.getInvertColors(); final int color; if (mInvert) { diff --git a/app/src/main/java/acr/browser/lightning/activity/TabsManager.java b/app/src/main/java/acr/browser/lightning/activity/TabsManager.java index d4cf26b..c3dd109 100644 --- a/app/src/main/java/acr/browser/lightning/activity/TabsManager.java +++ b/app/src/main/java/acr/browser/lightning/activity/TabsManager.java @@ -12,6 +12,7 @@ import javax.inject.Inject; import javax.inject.Singleton; import acr.browser.lightning.controller.BrowserController; +import acr.browser.lightning.preference.PreferenceManager; import acr.browser.lightning.view.LightningView; /** @@ -25,7 +26,7 @@ public class TabsManager { private LightningView mCurrentTab; @Inject - public TabsManager() { + public TabsManager(final Context context, final PreferenceManager preferenceManager) { } /** diff --git a/app/src/main/java/acr/browser/lightning/activity/ThemableBrowserActivity.java b/app/src/main/java/acr/browser/lightning/activity/ThemableBrowserActivity.java index a09c20b..1ab4a62 100644 --- a/app/src/main/java/acr/browser/lightning/activity/ThemableBrowserActivity.java +++ b/app/src/main/java/acr/browser/lightning/activity/ThemableBrowserActivity.java @@ -15,8 +15,8 @@ public abstract class ThemableBrowserActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { - mTheme = PreferenceManager.getInstance().getUseTheme(); - mShowTabsInDrawer = PreferenceManager.getInstance().getShowTabsInDrawer(!isTablet()); + mTheme = 0; //PreferenceManager.getInstance().getUseTheme(); + mShowTabsInDrawer = false; // PreferenceManager.getInstance().getShowTabsInDrawer(!isTablet()); // set the theme if (mTheme == 1) { @@ -30,8 +30,8 @@ public abstract class ThemableBrowserActivity extends AppCompatActivity { @Override protected void onResume() { super.onResume(); - int theme = PreferenceManager.getInstance().getUseTheme(); - boolean drawerTabs = PreferenceManager.getInstance().getShowTabsInDrawer(!isTablet()); + int theme = 0; // PreferenceManager.getInstance().getUseTheme(); + boolean drawerTabs = false; // PreferenceManager.getInstance().getShowTabsInDrawer(!isTablet()); if (theme != mTheme || mShowTabsInDrawer != drawerTabs) { restart(); } diff --git a/app/src/main/java/acr/browser/lightning/activity/ThemableSettingsActivity.java b/app/src/main/java/acr/browser/lightning/activity/ThemableSettingsActivity.java index c5a4573..475c0ee 100644 --- a/app/src/main/java/acr/browser/lightning/activity/ThemableSettingsActivity.java +++ b/app/src/main/java/acr/browser/lightning/activity/ThemableSettingsActivity.java @@ -4,6 +4,7 @@ import android.graphics.drawable.ColorDrawable; import android.os.Bundle; import acr.browser.lightning.R; +import acr.browser.lightning.app.BrowserApp; import acr.browser.lightning.preference.PreferenceManager; import acr.browser.lightning.utils.ThemeUtils; @@ -13,7 +14,7 @@ public abstract class ThemableSettingsActivity extends AppCompatPreferenceActivi @Override protected void onCreate(Bundle savedInstanceState) { - mTheme = PreferenceManager.getInstance().getUseTheme(); + mTheme = BrowserApp.getAppComponent().getPreferenceManager().getUseTheme(); // set the theme if (mTheme == 0) { @@ -32,7 +33,7 @@ public abstract class ThemableSettingsActivity extends AppCompatPreferenceActivi @Override protected void onResume() { super.onResume(); - if (PreferenceManager.getInstance().getUseTheme() != mTheme) { + if (BrowserApp.getAppComponent().getPreferenceManager().getUseTheme() != mTheme) { restart(); } } diff --git a/app/src/main/java/acr/browser/lightning/app/AppComponent.java b/app/src/main/java/acr/browser/lightning/app/AppComponent.java index a3927bf..94e9682 100644 --- a/app/src/main/java/acr/browser/lightning/app/AppComponent.java +++ b/app/src/main/java/acr/browser/lightning/app/AppComponent.java @@ -7,8 +7,10 @@ import acr.browser.lightning.constant.BookmarkPage; import acr.browser.lightning.dialog.BookmarksDialogBuilder; import acr.browser.lightning.fragment.BookmarkSettingsFragment; import acr.browser.lightning.fragment.BookmarksFragment; +import acr.browser.lightning.fragment.LightningPreferenceFragment; import acr.browser.lightning.fragment.TabsFragment; import acr.browser.lightning.object.SearchAdapter; +import acr.browser.lightning.preference.PreferenceManager; import dagger.Component; /** @@ -31,4 +33,8 @@ public interface AppComponent { void inject(BookmarkPage bookmarkPage); void inject(TabsFragment fragment); + + PreferenceManager getPreferenceManager(); + + void inject(LightningPreferenceFragment fragment); } diff --git a/app/src/main/java/acr/browser/lightning/constant/StartPage.java b/app/src/main/java/acr/browser/lightning/constant/StartPage.java index 118696f..144b146 100644 --- a/app/src/main/java/acr/browser/lightning/constant/StartPage.java +++ b/app/src/main/java/acr/browser/lightning/constant/StartPage.java @@ -57,11 +57,12 @@ public class StartPage { StringBuilder homepageBuilder = new StringBuilder(StartPage.HEAD); String icon; String searchUrl; - switch (PreferenceManager.getInstance().getSearchChoice()) { + final PreferenceManager preferenceManager = BrowserApp.getAppComponent().getPreferenceManager(); + switch (preferenceManager.getSearchChoice()) { case 0: // CUSTOM SEARCH icon = "file:///android_asset/lightning.png"; - searchUrl = PreferenceManager.getInstance().getSearchUrl(); + searchUrl = preferenceManager.getSearchUrl(); break; case 1: // GOOGLE_SEARCH; diff --git a/app/src/main/java/acr/browser/lightning/download/DownloadHandler.java b/app/src/main/java/acr/browser/lightning/download/DownloadHandler.java index 191560c..4a715a7 100644 --- a/app/src/main/java/acr/browser/lightning/download/DownloadHandler.java +++ b/app/src/main/java/acr/browser/lightning/download/DownloadHandler.java @@ -20,6 +20,7 @@ import android.webkit.CookieManager; import android.webkit.URLUtil; import acr.browser.lightning.R; +import acr.browser.lightning.app.BrowserApp; import acr.browser.lightning.preference.PreferenceManager; import acr.browser.lightning.utils.Utils; @@ -170,7 +171,7 @@ public class DownloadHandler { // or, should it be set to one of several Environment.DIRECTORY* dirs // depending on mimetype? - String location = PreferenceManager.getInstance().getDownloadDirectory(); + String location = BrowserApp.getAppComponent().getPreferenceManager().getDownloadDirectory(); request.setDestinationInExternalPublicDir(location, filename); // let this downloaded file be scanned by MediaScanner - so that it can // show up in Gallery app, for example. diff --git a/app/src/main/java/acr/browser/lightning/fragment/AdvancedSettingsFragment.java b/app/src/main/java/acr/browser/lightning/fragment/AdvancedSettingsFragment.java index 597d600..b8bbd51 100644 --- a/app/src/main/java/acr/browser/lightning/fragment/AdvancedSettingsFragment.java +++ b/app/src/main/java/acr/browser/lightning/fragment/AdvancedSettingsFragment.java @@ -18,7 +18,7 @@ import acr.browser.lightning.R; import acr.browser.lightning.constant.Constants; import acr.browser.lightning.preference.PreferenceManager; -public class AdvancedSettingsFragment extends PreferenceFragment implements Preference.OnPreferenceClickListener, Preference.OnPreferenceChangeListener { +public class AdvancedSettingsFragment extends LightningPreferenceFragment implements Preference.OnPreferenceClickListener, Preference.OnPreferenceChangeListener { private static final String SETTINGS_NEWWINDOW = "allow_new_window"; private static final String SETTINGS_ENABLECOOKIES = "allow_cookies"; @@ -29,7 +29,6 @@ public class AdvancedSettingsFragment extends PreferenceFragment implements Pref private static final String SETTINGS_TEXTENCODING = "text_encoding"; private Activity mActivity; - private PreferenceManager mPreferences; private CheckBoxPreference cbAllowPopups, cbenablecookies, cbcookiesInkognito, cbrestoreTabs; private Preference renderingmode, urlcontent, textEncoding; private CharSequence[] mUrlOptions; @@ -46,8 +45,6 @@ public class AdvancedSettingsFragment extends PreferenceFragment implements Pref } private void initPrefs() { - // mPreferences storage - mPreferences = PreferenceManager.getInstance(); renderingmode = findPreference(SETTINGS_RENDERINGMODE); textEncoding = findPreference(SETTINGS_TEXTENCODING); @@ -65,7 +62,7 @@ public class AdvancedSettingsFragment extends PreferenceFragment implements Pref cbcookiesInkognito.setOnPreferenceChangeListener(this); cbrestoreTabs.setOnPreferenceChangeListener(this); - switch (mPreferences.getRenderingMode()) { + switch (preferenceManager.getRenderingMode()) { case 0: renderingmode.setSummary(getString(R.string.name_normal)); break; @@ -80,16 +77,16 @@ public class AdvancedSettingsFragment extends PreferenceFragment implements Pref break; } - textEncoding.setSummary(mPreferences.getTextEncoding()); + textEncoding.setSummary(preferenceManager.getTextEncoding()); mUrlOptions = getResources().getStringArray(R.array.url_content_array); - int option = mPreferences.getUrlBoxContentChoice(); + int option = preferenceManager.getUrlBoxContentChoice(); urlcontent.setSummary(mUrlOptions[option]); - cbAllowPopups.setChecked(mPreferences.getPopupsEnabled()); - cbenablecookies.setChecked(mPreferences.getCookiesEnabled()); - cbcookiesInkognito.setChecked(mPreferences.getIncognitoCookiesEnabled()); - cbrestoreTabs.setChecked(mPreferences.getRestoreLostTabsEnabled()); + cbAllowPopups.setChecked(preferenceManager.getPopupsEnabled()); + cbenablecookies.setChecked(preferenceManager.getCookiesEnabled()); + cbcookiesInkognito.setChecked(preferenceManager.getIncognitoCookiesEnabled()); + cbrestoreTabs.setChecked(preferenceManager.getRestoreLostTabsEnabled()); } @Override @@ -114,19 +111,19 @@ public class AdvancedSettingsFragment extends PreferenceFragment implements Pref // switch preferences switch (preference.getKey()) { case SETTINGS_NEWWINDOW: - mPreferences.setPopupsEnabled((Boolean) newValue); + preferenceManager.setPopupsEnabled((Boolean) newValue); cbAllowPopups.setChecked((Boolean) newValue); return true; case SETTINGS_ENABLECOOKIES: - mPreferences.setCookiesEnabled((Boolean) newValue); + preferenceManager.setCookiesEnabled((Boolean) newValue); cbenablecookies.setChecked((Boolean) newValue); return true; case SETTINGS_COOKIESINKOGNITO: - mPreferences.setIncognitoCookiesEnabled((Boolean) newValue); + preferenceManager.setIncognitoCookiesEnabled((Boolean) newValue); cbcookiesInkognito.setChecked((Boolean) newValue); return true; case SETTINGS_RESTORETABS: - mPreferences.setRestoreLostTabsEnabled((Boolean) newValue); + preferenceManager.setRestoreLostTabsEnabled((Boolean) newValue); cbrestoreTabs.setChecked((Boolean) newValue); return true; default: @@ -142,12 +139,12 @@ public class AdvancedSettingsFragment extends PreferenceFragment implements Pref mActivity.getString(R.string.name_grayscale), mActivity.getString(R.string.name_inverted_grayscale)}; - int n = mPreferences.getRenderingMode(); + int n = preferenceManager.getRenderingMode(); picker.setSingleChoiceItems(chars, n, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { - mPreferences.setRenderingMode(which); + preferenceManager.setRenderingMode(which); switch (which) { case 0: renderingmode.setSummary(getString(R.string.name_normal)); @@ -178,12 +175,12 @@ public class AdvancedSettingsFragment extends PreferenceFragment implements Pref AlertDialog.Builder picker = new AlertDialog.Builder(mActivity); picker.setTitle(getResources().getString(R.string.text_encoding)); final List textEncodingList = Arrays.asList(Constants.TEXT_ENCODINGS); - int n = textEncodingList.indexOf(mPreferences.getTextEncoding()); + int n = textEncodingList.indexOf(preferenceManager.getTextEncoding()); picker.setSingleChoiceItems(Constants.TEXT_ENCODINGS, n, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { - mPreferences.setTextEncoding(Constants.TEXT_ENCODINGS[which]); + preferenceManager.setTextEncoding(Constants.TEXT_ENCODINGS[which]); textEncoding.setSummary(Constants.TEXT_ENCODINGS[which]); } }); @@ -201,12 +198,12 @@ public class AdvancedSettingsFragment extends PreferenceFragment implements Pref AlertDialog.Builder picker = new AlertDialog.Builder(mActivity); picker.setTitle(getResources().getString(R.string.url_contents)); - int n = mPreferences.getUrlBoxContentChoice(); + int n = preferenceManager.getUrlBoxContentChoice(); picker.setSingleChoiceItems(mUrlOptions, n, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { - mPreferences.setUrlBoxContentChoice(which); + preferenceManager.setUrlBoxContentChoice(which); if (which < mUrlOptions.length) { urlcontent.setSummary(mUrlOptions[which]); } diff --git a/app/src/main/java/acr/browser/lightning/fragment/BookmarksFragment.java b/app/src/main/java/acr/browser/lightning/fragment/BookmarksFragment.java index fdf15f2..2c01ac5 100644 --- a/app/src/main/java/acr/browser/lightning/fragment/BookmarksFragment.java +++ b/app/src/main/java/acr/browser/lightning/fragment/BookmarksFragment.java @@ -64,6 +64,9 @@ public class BookmarksFragment extends Fragment implements View.OnClickListener, @Inject BookmarksDialogBuilder bookmarksDialogBuilder; + @Inject + PreferenceManager preferenceManager; + // Adapter private BookmarkViewAdapter mBookmarkAdapter; @@ -151,7 +154,6 @@ public class BookmarksFragment extends Fragment implements View.OnClickListener, // TODO this code depend way too much on BrowserActivity super.onActivityCreated(savedInstanceState); final BrowserActivity activity = (BrowserActivity) getActivity(); - final PreferenceManager preferenceManager =PreferenceManager.getInstance(); boolean darkTheme = preferenceManager.getUseTheme() != 0 || activity.isIncognito(); mWebpageBitmap = ThemeUtils.getThemedBitmap(activity, R.drawable.ic_webpage, darkTheme); mFolderBitmap = ThemeUtils.getThemedBitmap(activity, R.drawable.ic_folder, darkTheme); diff --git a/app/src/main/java/acr/browser/lightning/fragment/DisplaySettingsFragment.java b/app/src/main/java/acr/browser/lightning/fragment/DisplaySettingsFragment.java index d33c40e..304bba8 100644 --- a/app/src/main/java/acr/browser/lightning/fragment/DisplaySettingsFragment.java +++ b/app/src/main/java/acr/browser/lightning/fragment/DisplaySettingsFragment.java @@ -21,7 +21,7 @@ import android.widget.TextView; import acr.browser.lightning.R; import acr.browser.lightning.preference.PreferenceManager; -public class DisplaySettingsFragment extends PreferenceFragment implements Preference.OnPreferenceClickListener, Preference.OnPreferenceChangeListener { +public class DisplaySettingsFragment extends LightningPreferenceFragment implements Preference.OnPreferenceClickListener, Preference.OnPreferenceChangeListener { private static final String SETTINGS_HIDESTATUSBAR = "fullScreenOption"; private static final String SETTINGS_FULLSCREEN = "fullscreen"; @@ -38,7 +38,6 @@ public class DisplaySettingsFragment extends PreferenceFragment implements Prefe private static final float XSMALL = 10.0f; private Activity mActivity; - private PreferenceManager mPreferences; private CheckBoxPreference cbstatus, cbfullscreen, cbviewport, cboverview, cbreflow; private Preference theme; private String[] mThemeOptions; @@ -57,9 +56,8 @@ public class DisplaySettingsFragment extends PreferenceFragment implements Prefe private void initPrefs() { // mPreferences storage - mPreferences = PreferenceManager.getInstance(); mThemeOptions = this.getResources().getStringArray(R.array.themes); - mCurrentTheme = mPreferences.getUseTheme(); + mCurrentTheme = preferenceManager.getUseTheme(); theme = findPreference(SETTINGS_THEME); Preference textsize = findPreference(SETTINGS_TEXTSIZE); @@ -77,13 +75,13 @@ public class DisplaySettingsFragment extends PreferenceFragment implements Prefe cboverview.setOnPreferenceChangeListener(this); cbreflow.setOnPreferenceChangeListener(this); - cbstatus.setChecked(mPreferences.getHideStatusBarEnabled()); - cbfullscreen.setChecked(mPreferences.getFullScreenEnabled()); - cbviewport.setChecked(mPreferences.getUseWideViewportEnabled()); - cboverview.setChecked(mPreferences.getOverviewModeEnabled()); - cbreflow.setChecked(mPreferences.getTextReflowEnabled()); + cbstatus.setChecked(preferenceManager.getHideStatusBarEnabled()); + cbfullscreen.setChecked(preferenceManager.getFullScreenEnabled()); + cbviewport.setChecked(preferenceManager.getUseWideViewportEnabled()); + cboverview.setChecked(preferenceManager.getOverviewModeEnabled()); + cbreflow.setChecked(preferenceManager.getTextReflowEnabled()); - theme.setSummary(mThemeOptions[mPreferences.getUseTheme()]); + theme.setSummary(mThemeOptions[preferenceManager.getUseTheme()]); } @Override @@ -105,23 +103,23 @@ public class DisplaySettingsFragment extends PreferenceFragment implements Prefe // switch preferences switch (preference.getKey()) { case SETTINGS_HIDESTATUSBAR: - mPreferences.setHideStatusBarEnabled((Boolean) newValue); + preferenceManager.setHideStatusBarEnabled((Boolean) newValue); cbstatus.setChecked((Boolean) newValue); return true; case SETTINGS_FULLSCREEN: - mPreferences.setFullScreenEnabled((Boolean) newValue); + preferenceManager.setFullScreenEnabled((Boolean) newValue); cbfullscreen.setChecked((Boolean) newValue); return true; case SETTINGS_VIEWPORT: - mPreferences.setUseWideViewportEnabled((Boolean) newValue); + preferenceManager.setUseWideViewportEnabled((Boolean) newValue); cbviewport.setChecked((Boolean) newValue); return true; case SETTINGS_OVERVIEWMODE: - mPreferences.setOverviewModeEnabled((Boolean) newValue); + preferenceManager.setOverviewModeEnabled((Boolean) newValue); cboverview.setChecked((Boolean) newValue); return true; case SETTINGS_REFLOW: - mPreferences.setTextReflowEnabled((Boolean) newValue); + preferenceManager.setTextReflowEnabled((Boolean) newValue); cbreflow.setChecked((Boolean) newValue); return true; default: @@ -157,14 +155,14 @@ public class DisplaySettingsFragment extends PreferenceFragment implements Prefe }); final int MAX = 5; bar.setMax(MAX); - bar.setProgress(MAX - mPreferences.getTextSize()); + bar.setProgress(MAX - preferenceManager.getTextSize()); builder.setView(view); builder.setTitle(R.string.title_text_size); builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface arg0, int arg1) { - mPreferences.setTextSize(MAX - bar.getProgress()); + preferenceManager.setTextSize(MAX - bar.getProgress()); } }); @@ -194,12 +192,12 @@ public class DisplaySettingsFragment extends PreferenceFragment implements Prefe AlertDialog.Builder picker = new AlertDialog.Builder(mActivity); picker.setTitle(getResources().getString(R.string.theme)); - int n = mPreferences.getUseTheme(); + int n = preferenceManager.getUseTheme(); picker.setSingleChoiceItems(mThemeOptions, n, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { - mPreferences.setUseTheme(which); + preferenceManager.setUseTheme(which); if (which < mThemeOptions.length) { theme.setSummary(mThemeOptions[which]); } @@ -210,7 +208,7 @@ public class DisplaySettingsFragment extends PreferenceFragment implements Prefe @Override public void onClick(DialogInterface dialog, int which) { - if (mCurrentTheme != mPreferences.getUseTheme()) { + if (mCurrentTheme != preferenceManager.getUseTheme()) { getActivity().onBackPressed(); } } @@ -218,7 +216,7 @@ public class DisplaySettingsFragment extends PreferenceFragment implements Prefe picker.setOnCancelListener(new DialogInterface.OnCancelListener() { @Override public void onCancel(DialogInterface dialog) { - if (mCurrentTheme != mPreferences.getUseTheme()) { + if (mCurrentTheme != preferenceManager.getUseTheme()) { getActivity().onBackPressed(); } } diff --git a/app/src/main/java/acr/browser/lightning/fragment/GeneralSettingsFragment.java b/app/src/main/java/acr/browser/lightning/fragment/GeneralSettingsFragment.java index 6698e29..68714cd 100644 --- a/app/src/main/java/acr/browser/lightning/fragment/GeneralSettingsFragment.java +++ b/app/src/main/java/acr/browser/lightning/fragment/GeneralSettingsFragment.java @@ -28,7 +28,7 @@ import acr.browser.lightning.preference.PreferenceManager; import acr.browser.lightning.utils.ProxyUtils; import acr.browser.lightning.utils.Utils; -public class GeneralSettingsFragment extends PreferenceFragment implements Preference.OnPreferenceClickListener, Preference.OnPreferenceChangeListener { +public class GeneralSettingsFragment extends LightningPreferenceFragment implements Preference.OnPreferenceClickListener, Preference.OnPreferenceChangeListener { private static final String SETTINGS_PROXY = "proxy"; private static final String SETTINGS_FLASH = "cb_flash"; @@ -45,7 +45,6 @@ public class GeneralSettingsFragment extends PreferenceFragment implements Prefe private Activity mActivity; private static final int API = android.os.Build.VERSION.SDK_INT; - private PreferenceManager mPreferences; private CharSequence[] mProxyChoices; private Preference proxy, useragent, downloadloc, home, searchengine; private String mDownloadLocation; @@ -65,9 +64,6 @@ public class GeneralSettingsFragment extends PreferenceFragment implements Prefe } private void initPrefs() { - // mPreferences storage - mPreferences = PreferenceManager.getInstance(); - proxy = findPreference(SETTINGS_PROXY); useragent = findPreference(SETTINGS_USERAGENT); downloadloc = findPreference(SETTINGS_DOWNLOAD); @@ -95,23 +91,23 @@ public class GeneralSettingsFragment extends PreferenceFragment implements Prefe cbgooglesuggest.setOnPreferenceChangeListener(this); cbDrawerTabs.setOnPreferenceChangeListener(this); - mAgentChoice = mPreferences.getUserAgentChoice(); - mHomepage = mPreferences.getHomepage(); - mDownloadLocation = mPreferences.getDownloadDirectory(); + mAgentChoice = preferenceManager.getUserAgentChoice(); + mHomepage = preferenceManager.getHomepage(); + mDownloadLocation = preferenceManager.getDownloadDirectory(); mProxyChoices = getResources().getStringArray(R.array.proxy_choices_array); - int choice = mPreferences.getProxyChoice(); + int choice = preferenceManager.getProxyChoice(); if (choice == Constants.PROXY_MANUAL) { - proxy.setSummary(mPreferences.getProxyHost() + ':' + mPreferences.getProxyPort()); + proxy.setSummary(preferenceManager.getProxyHost() + ':' + preferenceManager.getProxyPort()); } else { proxy.setSummary(mProxyChoices[choice]); } if (API >= 19) { - mPreferences.setFlashSupport(0); + preferenceManager.setFlashSupport(0); } - setSearchEngineSummary(mPreferences.getSearchChoice()); + setSearchEngineSummary(preferenceManager.getSearchChoice()); downloadloc.setSummary(Constants.EXTERNAL_STORAGE + '/' + mDownloadLocation); @@ -139,9 +135,9 @@ public class GeneralSettingsFragment extends PreferenceFragment implements Prefe useragent.setSummary(getResources().getString(R.string.agent_custom)); } - int flashNum = mPreferences.getFlashSupport(); - boolean imagesBool = mPreferences.getBlockImagesEnabled(); - boolean enableJSBool = mPreferences.getJavaScriptEnabled(); + int flashNum = preferenceManager.getFlashSupport(); + boolean imagesBool = preferenceManager.getBlockImagesEnabled(); + boolean enableJSBool = preferenceManager.getJavaScriptEnabled(); proxy.setEnabled(Constants.FULL_VERSION); cbAds.setEnabled(Constants.FULL_VERSION); @@ -150,17 +146,17 @@ public class GeneralSettingsFragment extends PreferenceFragment implements Prefe cbImages.setChecked(imagesBool); cbJsScript.setChecked(enableJSBool); cbFlash.setChecked(flashNum > 0); - cbAds.setChecked(Constants.FULL_VERSION && mPreferences.getAdBlockEnabled()); - cbColorMode.setChecked(mPreferences.getColorModeEnabled()); - cbgooglesuggest.setChecked(mPreferences.getGoogleSearchSuggestionsEnabled()); - cbDrawerTabs.setChecked(mPreferences.getShowTabsInDrawer(true)); + cbAds.setChecked(Constants.FULL_VERSION && preferenceManager.getAdBlockEnabled()); + cbColorMode.setChecked(preferenceManager.getColorModeEnabled()); + cbgooglesuggest.setChecked(preferenceManager.getGoogleSearchSuggestionsEnabled()); + cbDrawerTabs.setChecked(preferenceManager.getShowTabsInDrawer(true)); } private void searchUrlPicker() { final AlertDialog.Builder urlPicker = new AlertDialog.Builder(mActivity); urlPicker.setTitle(getResources().getString(R.string.custom_url)); final EditText getSearchUrl = new EditText(mActivity); - String mSearchUrl = mPreferences.getSearchUrl(); + String mSearchUrl = preferenceManager.getSearchUrl(); getSearchUrl.setText(mSearchUrl); urlPicker.setView(getSearchUrl); urlPicker.setPositiveButton(getResources().getString(R.string.action_ok), @@ -168,7 +164,7 @@ public class GeneralSettingsFragment extends PreferenceFragment implements Prefe @Override public void onClick(DialogInterface dialog, int which) { String text = getSearchUrl.getText().toString(); - mPreferences.setSearchUrl(text); + preferenceManager.setSearchUrl(text); searchengine.setSummary(getResources().getString(R.string.custom_url) + ": " + text); } @@ -185,7 +181,7 @@ public class GeneralSettingsFragment extends PreferenceFragment implements Prefe new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int id) { - mPreferences.setFlashSupport(1); + preferenceManager.setFlashSupport(1); } }) .setNegativeButton(getResources().getString(R.string.action_auto), @@ -193,13 +189,13 @@ public class GeneralSettingsFragment extends PreferenceFragment implements Prefe @Override public void onClick(DialogInterface dialog, int which) { - mPreferences.setFlashSupport(2); + preferenceManager.setFlashSupport(2); } }).setOnCancelListener(new DialogInterface.OnCancelListener() { @Override public void onCancel(DialogInterface dialog) { - mPreferences.setFlashSupport(0); + preferenceManager.setFlashSupport(0); } }); @@ -210,7 +206,7 @@ public class GeneralSettingsFragment extends PreferenceFragment implements Prefe private void proxyChoicePicker() { AlertDialog.Builder picker = new AlertDialog.Builder(mActivity); picker.setTitle(getResources().getString(R.string.http_proxy)); - picker.setSingleChoiceItems(mProxyChoices, mPreferences.getProxyChoice(), + picker.setSingleChoiceItems(mProxyChoices, preferenceManager.getProxyChoice(), new DialogInterface.OnClickListener() { @Override @@ -240,7 +236,7 @@ public class GeneralSettingsFragment extends PreferenceFragment implements Prefe break; } - mPreferences.setProxyChoice(choice); + preferenceManager.setProxyChoice(choice); if (choice < mProxyChoices.length) proxy.setSummary(mProxyChoices[choice]); } @@ -258,8 +254,8 @@ public class GeneralSettingsFragment extends PreferenceFragment implements Prefe filterArray[0] = new InputFilter.LengthFilter(maxCharacters - 1); eProxyPort.setFilters(filterArray); - eProxyHost.setText(mPreferences.getProxyHost()); - eProxyPort.setText(Integer.toString(mPreferences.getProxyPort())); + eProxyHost.setText(preferenceManager.getProxyHost()); + eProxyPort.setText(Integer.toString(preferenceManager.getProxyPort())); new AlertDialog.Builder(mActivity) .setTitle(R.string.manual_proxy) @@ -274,10 +270,10 @@ public class GeneralSettingsFragment extends PreferenceFragment implements Prefe // larger than max integer proxyPort = Integer.parseInt(eProxyPort.getText().toString()); } catch (NumberFormatException ignored) { - proxyPort = mPreferences.getProxyPort(); + proxyPort = preferenceManager.getProxyPort(); } - mPreferences.setProxyHost(proxyHost); - mPreferences.setProxyPort(proxyPort); + preferenceManager.setProxyHost(proxyHost); + preferenceManager.setProxyPort(proxyPort); proxy.setSummary(proxyHost + ':' + proxyPort); } }).show(); @@ -291,13 +287,13 @@ public class GeneralSettingsFragment extends PreferenceFragment implements Prefe "DuckDuckGo (Privacy)", "DuckDuckGo Lite (Privacy)", "Baidu (Chinese)", "Yandex (Russian)"}; - int n = mPreferences.getSearchChoice(); + int n = preferenceManager.getSearchChoice(); picker.setSingleChoiceItems(chars, n, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { - mPreferences.setSearchChoice(which); + preferenceManager.setSearchChoice(which); setSearchEngineSummary(which); } }); @@ -313,7 +309,7 @@ public class GeneralSettingsFragment extends PreferenceFragment implements Prefe private void homepageDialog() { AlertDialog.Builder picker = new AlertDialog.Builder(mActivity); picker.setTitle(getResources().getString(R.string.home)); - mHomepage = mPreferences.getHomepage(); + mHomepage = preferenceManager.getHomepage(); int n; if (mHomepage.contains("about:home")) { n = 1; @@ -331,15 +327,15 @@ public class GeneralSettingsFragment extends PreferenceFragment implements Prefe public void onClick(DialogInterface dialog, int which) { switch (which + 1) { case 1: - mPreferences.setHomepage("about:home"); + preferenceManager.setHomepage("about:home"); home.setSummary(getResources().getString(R.string.action_homepage)); break; case 2: - mPreferences.setHomepage("about:blank"); + preferenceManager.setHomepage("about:blank"); home.setSummary(getResources().getString(R.string.action_blank)); break; case 3: - mPreferences.setHomepage("about:bookmarks"); + preferenceManager.setHomepage("about:bookmarks"); home.setSummary(getResources().getString(R.string.action_bookmarks)); break; case 4: @@ -361,7 +357,7 @@ public class GeneralSettingsFragment extends PreferenceFragment implements Prefe final AlertDialog.Builder homePicker = new AlertDialog.Builder(mActivity); homePicker.setTitle(getResources().getString(R.string.title_custom_homepage)); final EditText getHome = new EditText(mActivity); - mHomepage = mPreferences.getHomepage(); + mHomepage = preferenceManager.getHomepage(); if (!mHomepage.startsWith("about:")) { getHome.setText(mHomepage); } else { @@ -373,7 +369,7 @@ public class GeneralSettingsFragment extends PreferenceFragment implements Prefe @Override public void onClick(DialogInterface dialog, int which) { String text = getHome.getText().toString(); - mPreferences.setHomepage(text); + preferenceManager.setHomepage(text); home.setSummary(text); } }); @@ -383,7 +379,7 @@ public class GeneralSettingsFragment extends PreferenceFragment implements Prefe private void downloadLocDialog() { AlertDialog.Builder picker = new AlertDialog.Builder(mActivity); picker.setTitle(getResources().getString(R.string.title_download_location)); - mDownloadLocation = mPreferences.getDownloadDirectory(); + mDownloadLocation = preferenceManager.getDownloadDirectory(); int n; if (mDownloadLocation.contains(Environment.DIRECTORY_DOWNLOADS)) { n = 1; @@ -397,7 +393,7 @@ public class GeneralSettingsFragment extends PreferenceFragment implements Prefe public void onClick(DialogInterface dialog, int which) { switch (which + 1) { case 1: - mPreferences.setDownloadDirectory(Environment.DIRECTORY_DOWNLOADS); + preferenceManager.setDownloadDirectory(Environment.DIRECTORY_DOWNLOADS); downloadloc.setSummary(Constants.EXTERNAL_STORAGE + '/' + Environment.DIRECTORY_DOWNLOADS); break; @@ -419,12 +415,12 @@ public class GeneralSettingsFragment extends PreferenceFragment implements Prefe private void agentDialog() { AlertDialog.Builder agentPicker = new AlertDialog.Builder(mActivity); agentPicker.setTitle(getResources().getString(R.string.title_user_agent)); - mAgentChoice = mPreferences.getUserAgentChoice(); + mAgentChoice = preferenceManager.getUserAgentChoice(); agentPicker.setSingleChoiceItems(R.array.user_agent, mAgentChoice - 1, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { - mPreferences.setUserAgentChoice(which + 1); + preferenceManager.setUserAgentChoice(which + 1); switch (which + 1) { case 1: useragent.setSummary(getResources().getString(R.string.agent_default)); @@ -467,7 +463,7 @@ public class GeneralSettingsFragment extends PreferenceFragment implements Prefe @Override public void onClick(DialogInterface dialog, int which) { String text = getAgent.getText().toString(); - mPreferences.setUserAgentString(text); + preferenceManager.setUserAgentString(text); useragent.setSummary(getResources().getString(R.string.agent_custom)); } }); @@ -479,7 +475,7 @@ public class GeneralSettingsFragment extends PreferenceFragment implements Prefe LinearLayout layout = new LinearLayout(mActivity); downLocationPicker.setTitle(getResources().getString(R.string.title_download_location)); final EditText getDownload = new EditText(mActivity); - getDownload.setText(mPreferences.getDownloadDirectory()); + getDownload.setText(preferenceManager.getDownloadDirectory()); int padding = Utils.dpToPx(10); @@ -507,7 +503,7 @@ public class GeneralSettingsFragment extends PreferenceFragment implements Prefe @Override public void onClick(DialogInterface dialog, int which) { String text = getDownload.getText().toString(); - mPreferences.setDownloadDirectory(text); + preferenceManager.setDownloadDirectory(text); downloadloc.setSummary(Constants.EXTERNAL_STORAGE + '/' + text); } }); @@ -582,37 +578,37 @@ public class GeneralSettingsFragment extends PreferenceFragment implements Prefe if (cbFlash.isChecked()) { getFlashChoice(); } else { - mPreferences.setFlashSupport(0); + preferenceManager.setFlashSupport(0); } if (!Utils.isFlashInstalled(mActivity) && cbFlash.isChecked()) { Utils.createInformativeDialog(mActivity, R.string.title_warning, R.string.dialog_adobe_not_installed); cbFlash.setEnabled(false); - mPreferences.setFlashSupport(0); + preferenceManager.setFlashSupport(0); } cbFlash.setChecked((Boolean) newValue); return true; case SETTINGS_ADS: - mPreferences.setAdBlockEnabled((Boolean) newValue); + preferenceManager.setAdBlockEnabled((Boolean) newValue); cbAds.setChecked((Boolean) newValue); return true; case SETTINGS_IMAGES: - mPreferences.setBlockImagesEnabled((Boolean) newValue); + preferenceManager.setBlockImagesEnabled((Boolean) newValue); cbImages.setChecked((Boolean) newValue); return true; case SETTINGS_JAVASCRIPT: - mPreferences.setJavaScriptEnabled((Boolean) newValue); + preferenceManager.setJavaScriptEnabled((Boolean) newValue); cbJsScript.setChecked((Boolean) newValue); return true; case SETTINGS_COLORMODE: - mPreferences.setColorModeEnabled((Boolean) newValue); + preferenceManager.setColorModeEnabled((Boolean) newValue); cbColorMode.setChecked((Boolean) newValue); return true; case SETTINGS_GOOGLESUGGESTIONS: - mPreferences.setGoogleSearchSuggestionsEnabled((Boolean) newValue); + preferenceManager.setGoogleSearchSuggestionsEnabled((Boolean) newValue); cbgooglesuggest.setChecked((Boolean) newValue); return true; case SETTINGS_DRAWERTABS: - mPreferences.setShowTabsInDrawer((Boolean) newValue); + preferenceManager.setShowTabsInDrawer((Boolean) newValue); cbDrawerTabs.setChecked((Boolean) newValue); default: return false; diff --git a/app/src/main/java/acr/browser/lightning/fragment/LightningPreferenceFragment.java b/app/src/main/java/acr/browser/lightning/fragment/LightningPreferenceFragment.java new file mode 100644 index 0000000..194b3cb --- /dev/null +++ b/app/src/main/java/acr/browser/lightning/fragment/LightningPreferenceFragment.java @@ -0,0 +1,27 @@ +package acr.browser.lightning.fragment; + +import android.os.Bundle; +import android.preference.PreferenceFragment; + +import javax.inject.Inject; + +import acr.browser.lightning.app.BrowserApp; +import acr.browser.lightning.preference.PreferenceManager; + +/** + * Simplify {@link PreferenceManager} inject in all the PreferenceFragments + * + * @author Stefano Pacifici + * @date 2015/09/16 + */ +public class LightningPreferenceFragment extends PreferenceFragment { + + @Inject + PreferenceManager preferenceManager; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + BrowserApp.getAppComponent().inject(this); + } +} diff --git a/app/src/main/java/acr/browser/lightning/fragment/PrivacySettingsFragment.java b/app/src/main/java/acr/browser/lightning/fragment/PrivacySettingsFragment.java index 66b9c11..8bd540c 100644 --- a/app/src/main/java/acr/browser/lightning/fragment/PrivacySettingsFragment.java +++ b/app/src/main/java/acr/browser/lightning/fragment/PrivacySettingsFragment.java @@ -20,7 +20,7 @@ import acr.browser.lightning.preference.PreferenceManager; import acr.browser.lightning.utils.Utils; import acr.browser.lightning.utils.WebUtils; -public class PrivacySettingsFragment extends PreferenceFragment implements Preference.OnPreferenceClickListener, Preference.OnPreferenceChangeListener { +public class PrivacySettingsFragment extends LightningPreferenceFragment implements Preference.OnPreferenceClickListener, Preference.OnPreferenceChangeListener { private static final String SETTINGS_LOCATION = "location"; private static final String SETTINGS_THIRDPCOOKIES = "third_party"; @@ -35,7 +35,6 @@ public class PrivacySettingsFragment extends PreferenceFragment implements Prefe private static final String SETTINGS_WEBSTORAGEEXIT = "clear_webstorage_exit"; private Activity mActivity; - private PreferenceManager mPreferences; private CheckBoxPreference cblocation, cb3cookies, cbsavepasswords, cbcacheexit, cbhistoryexit, cbcookiesexit, cbwebstorageexit; private Handler messageHandler; @@ -52,9 +51,6 @@ public class PrivacySettingsFragment extends PreferenceFragment implements Prefe } private void initPrefs() { - // mPreferences storage - mPreferences = PreferenceManager.getInstance(); - Preference clearcache = findPreference(SETTINGS_CLEARCACHE); Preference clearhistory = findPreference(SETTINGS_CLEARHISTORY); Preference clearcookies = findPreference(SETTINGS_CLEARCOOKIES); @@ -81,13 +77,13 @@ public class PrivacySettingsFragment extends PreferenceFragment implements Prefe cbcookiesexit.setOnPreferenceChangeListener(this); cbwebstorageexit.setOnPreferenceChangeListener(this); - cblocation.setChecked(mPreferences.getLocationEnabled()); - cbsavepasswords.setChecked(mPreferences.getSavePasswordsEnabled()); - cbcacheexit.setChecked(mPreferences.getClearCacheExit()); - cbhistoryexit.setChecked(mPreferences.getClearHistoryExitEnabled()); - cbcookiesexit.setChecked(mPreferences.getClearCookiesExitEnabled()); - cb3cookies.setChecked(mPreferences.getBlockThirdPartyCookiesEnabled()); - cbwebstorageexit.setChecked(mPreferences.getClearWebStorageExitEnabled()); + cblocation.setChecked(preferenceManager.getLocationEnabled()); + cbsavepasswords.setChecked(preferenceManager.getSavePasswordsEnabled()); + cbcacheexit.setChecked(preferenceManager.getClearCacheExit()); + cbhistoryexit.setChecked(preferenceManager.getClearHistoryExitEnabled()); + cbcookiesexit.setChecked(preferenceManager.getClearCookiesExitEnabled()); + cb3cookies.setChecked(preferenceManager.getBlockThirdPartyCookiesEnabled()); + cbwebstorageexit.setChecked(preferenceManager.getClearWebStorageExitEnabled()); cb3cookies.setEnabled(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP); @@ -213,31 +209,31 @@ public class PrivacySettingsFragment extends PreferenceFragment implements Prefe // switch preferences switch (preference.getKey()) { case SETTINGS_LOCATION: - mPreferences.setLocationEnabled((Boolean) newValue); + preferenceManager.setLocationEnabled((Boolean) newValue); cblocation.setChecked((Boolean) newValue); return true; case SETTINGS_THIRDPCOOKIES: - mPreferences.setBlockThirdPartyCookiesEnabled((Boolean) newValue); + preferenceManager.setBlockThirdPartyCookiesEnabled((Boolean) newValue); cb3cookies.setChecked((Boolean) newValue); return true; case SETTINGS_SAVEPASSWORD: - mPreferences.setSavePasswordsEnabled((Boolean) newValue); + preferenceManager.setSavePasswordsEnabled((Boolean) newValue); cbsavepasswords.setChecked((Boolean) newValue); return true; case SETTINGS_CACHEEXIT: - mPreferences.setClearCacheExit((Boolean) newValue); + preferenceManager.setClearCacheExit((Boolean) newValue); cbcacheexit.setChecked((Boolean) newValue); return true; case SETTINGS_HISTORYEXIT: - mPreferences.setClearHistoryExitEnabled((Boolean) newValue); + preferenceManager.setClearHistoryExitEnabled((Boolean) newValue); cbhistoryexit.setChecked((Boolean) newValue); return true; case SETTINGS_COOKIEEXIT: - mPreferences.setClearCookiesExitEnabled((Boolean) newValue); + preferenceManager.setClearCookiesExitEnabled((Boolean) newValue); cbcookiesexit.setChecked((Boolean) newValue); return true; case SETTINGS_WEBSTORAGEEXIT: - mPreferences.setClearWebStorageExitEnabled((Boolean) newValue); + preferenceManager.setClearWebStorageExitEnabled((Boolean) newValue); cbwebstorageexit.setChecked((Boolean) newValue); return true; default: diff --git a/app/src/main/java/acr/browser/lightning/fragment/TabsFragment.java b/app/src/main/java/acr/browser/lightning/fragment/TabsFragment.java index 43738f1..678c332 100644 --- a/app/src/main/java/acr/browser/lightning/fragment/TabsFragment.java +++ b/app/src/main/java/acr/browser/lightning/fragment/TabsFragment.java @@ -129,6 +129,7 @@ public class TabsFragment extends Fragment implements View.OnClickListener, View @Override public void onDestroyView() { + super.onDestroyView(); mRecyclerView = null; mTabsAdapter = null; } diff --git a/app/src/main/java/acr/browser/lightning/object/SearchAdapter.java b/app/src/main/java/acr/browser/lightning/object/SearchAdapter.java index c79bb54..f61aabc 100644 --- a/app/src/main/java/acr/browser/lightning/object/SearchAdapter.java +++ b/app/src/main/java/acr/browser/lightning/object/SearchAdapter.java @@ -61,6 +61,7 @@ public class SearchAdapter extends BaseAdapter implements Filterable { private final boolean mDarkTheme; private final boolean mIncognito; @Inject BookmarkManager mBookmarkManager; + @Inject PreferenceManager mPreferenceManager; private static final String CACHE_FILE_TYPE = ".sgg"; private static final String ENCODING = "ISO-8859-1"; private static final long INTERVAL_DAY = 86400000; @@ -76,7 +77,7 @@ public class SearchAdapter extends BaseAdapter implements Filterable { BrowserApp.getAppComponent().inject(this); mDatabaseHandler = HistoryDatabase.getInstance(); mAllBookmarks.addAll(mBookmarkManager.getAllBookmarks(true)); - mUseGoogle = PreferenceManager.getInstance().getGoogleSearchSuggestionsEnabled(); + mUseGoogle = mPreferenceManager.getGoogleSearchSuggestionsEnabled(); mContext = context; mSearchSubtitle = mContext.getString(R.string.suggestion); mDarkTheme = dark || incognito; @@ -118,7 +119,7 @@ public class SearchAdapter extends BaseAdapter implements Filterable { } public void refreshPreferences() { - mUseGoogle = PreferenceManager.getInstance().getGoogleSearchSuggestionsEnabled(); + mUseGoogle = mPreferenceManager.getGoogleSearchSuggestionsEnabled(); if (!mUseGoogle) { synchronized (mSuggestions) { mSuggestions.clear(); diff --git a/app/src/main/java/acr/browser/lightning/preference/PreferenceManager.java b/app/src/main/java/acr/browser/lightning/preference/PreferenceManager.java index 9e186b4..438fad0 100644 --- a/app/src/main/java/acr/browser/lightning/preference/PreferenceManager.java +++ b/app/src/main/java/acr/browser/lightning/preference/PreferenceManager.java @@ -1,11 +1,16 @@ package acr.browser.lightning.preference; +import android.content.Context; import android.content.SharedPreferences; import android.os.Environment; +import javax.inject.Inject; +import javax.inject.Singleton; + import acr.browser.lightning.app.BrowserApp; import acr.browser.lightning.constant.Constants; +@Singleton public class PreferenceManager { private static class Name { @@ -56,20 +61,13 @@ public class PreferenceManager { public static final String INITIAL_CHECK_FOR_I2P = "checkForI2P"; } - private static PreferenceManager mInstance; private final SharedPreferences mPrefs; private static final String PREFERENCES = "settings"; - public static PreferenceManager getInstance() { - if (mInstance == null) { - mInstance = new PreferenceManager(); - } - return mInstance; - } - - private PreferenceManager() { - mPrefs = BrowserApp.getAppContext().getSharedPreferences(PREFERENCES, 0); + @Inject + PreferenceManager(final Context context) { + mPrefs = context.getSharedPreferences(PREFERENCES, 0); } public boolean getAdBlockEnabled() { diff --git a/app/src/main/java/acr/browser/lightning/utils/AdBlock.java b/app/src/main/java/acr/browser/lightning/utils/AdBlock.java index 0f06386..5ac6baf 100644 --- a/app/src/main/java/acr/browser/lightning/utils/AdBlock.java +++ b/app/src/main/java/acr/browser/lightning/utils/AdBlock.java @@ -13,6 +13,7 @@ import java.util.HashSet; import java.util.Locale; import java.util.Set; +import acr.browser.lightning.app.BrowserApp; import acr.browser.lightning.constant.Constants; import acr.browser.lightning.preference.PreferenceManager; @@ -44,11 +45,11 @@ public class AdBlock { if (mBlockedDomainsList.isEmpty() && Constants.FULL_VERSION) { loadHostsFile(context); } - mBlockAds = PreferenceManager.getInstance().getAdBlockEnabled(); + mBlockAds = BrowserApp.getAppComponent().getPreferenceManager().getAdBlockEnabled(); } public void updatePreference() { - mBlockAds = PreferenceManager.getInstance().getAdBlockEnabled(); + mBlockAds = BrowserApp.getAppComponent().getPreferenceManager().getAdBlockEnabled(); } private void loadBlockedDomainsList(final Context context) { diff --git a/app/src/main/java/acr/browser/lightning/view/LightningView.java b/app/src/main/java/acr/browser/lightning/view/LightningView.java index b4b377c..011d97e 100644 --- a/app/src/main/java/acr/browser/lightning/view/LightningView.java +++ b/app/src/main/java/acr/browser/lightning/view/LightningView.java @@ -55,6 +55,8 @@ import java.io.FileOutputStream; import java.io.IOException; import java.net.URISyntaxException; +import javax.inject.Inject; + import acr.browser.lightning.R; import acr.browser.lightning.app.BrowserApp; import acr.browser.lightning.constant.Constants; @@ -80,7 +82,8 @@ public class LightningView { private static String mDefaultUserAgent; // TODO fix so that mWebpageBitmap can be static - static changes the icon when switching from light to dark and then back to light private final Bitmap mWebpageBitmap; - private static PreferenceManager mPreferences; + @Inject + PreferenceManager mPreferences; private final AdBlock mAdBlock; private final IntentUtils mIntentUtils; private final Paint mPaint = new Paint(); @@ -102,7 +105,7 @@ public class LightningView { @SuppressLint("NewApi") public LightningView(Activity activity, String url, boolean darkTheme, boolean isIncognito, BrowserController controller) { - + mPreferences = BrowserApp.getAppComponent().getPreferenceManager(); mActivity = activity; mWebView = new WebView(activity); mIsIncognitoTab = isIncognito; @@ -178,7 +181,6 @@ public class LightningView { } else if (settings == null) { settings = mWebView.getSettings(); } - mPreferences = PreferenceManager.getInstance(); settings.setDefaultTextEncodingName(mPreferences.getTextEncoding()); mHomepage = mPreferences.getHomepage(); From 2563e81f7a76bd9455c2de5755b4dd8cc1006685 Mon Sep 17 00:00:00 2001 From: Stefano Pacifici Date: Wed, 16 Sep 2015 17:42:20 +0200 Subject: [PATCH 09/16] Bookmark page generation moved to LightningView to avoid call loop between BrowserActivity and LightningView through BrowserController --- .../lightning/activity/BrowserActivity.java | 29 +-------------- .../browser/lightning/app/AppComponent.java | 2 + .../lightning/constant/BookmarkPage.java | 5 ++- .../controller/BrowserController.java | 2 - .../browser/lightning/utils/IntentUtils.java | 15 +++++--- .../browser/lightning/view/LightningView.java | 37 +++++++++++++++---- 6 files changed, 46 insertions(+), 44 deletions(-) diff --git a/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java b/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java index 2831051..eb3821d 100644 --- a/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java +++ b/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java @@ -1471,31 +1471,6 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements return super.onCreateOptionsMenu(menu); } - /** - * open the HTML bookmarks page, parameter view is the WebView that should show the page - */ - @Override - public void openBookmarkPage(WebView view) { - if (view == null) - return; - Bitmap folderIcon = ThemeUtils.getThemedBitmap(this, R.drawable.ic_folder, false); - FileOutputStream outputStream = null; - File image = new File(mActivity.getCacheDir(), "folder.png"); - try { - outputStream = new FileOutputStream(image); - folderIcon.compress(Bitmap.CompressFormat.PNG, 100, outputStream); - folderIcon.recycle(); - } catch (FileNotFoundException e) { - e.printStackTrace(); - } finally { - Utils.close(outputStream); - } - File bookmarkWebPage = new File(mActivity.getFilesDir(), Constants.BOOKMARKS_FILENAME); - - bookmarkPage.buildBookmarkPage(null, bookmarkManager.getBookmarksFromFolder(null, true)); - view.loadUrl(Constants.FILE + bookmarkWebPage); - } - @Override public void updateTabs() { eventBus.post(new BrowserEvents.TabsChanged()); @@ -2232,7 +2207,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements final WebView currentWebView = currentTab.getWebView(); if (currentTab != null && currentTab.getUrl().startsWith(Constants.FILE) && currentTab.getUrl().endsWith(Constants.BOOKMARKS_FILENAME)) { - openBookmarkPage(currentWebView); + currentTab.loadBookmarkpage(); } if (currentTab != null) { eventBus.post(new BrowserEvents.CurrentPageUrl(currentTab.getUrl())); @@ -2250,7 +2225,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements final WebView currentWebView = currentTab.getWebView(); if (currentTab != null && currentTab.getUrl().startsWith(Constants.FILE) && currentTab.getUrl().endsWith(Constants.BOOKMARKS_FILENAME)) { - openBookmarkPage(currentWebView); + currentTab.loadBookmarkpage(); } if (currentTab != null) { eventBus.post(new BrowserEvents.CurrentPageUrl(currentTab.getUrl())); diff --git a/app/src/main/java/acr/browser/lightning/app/AppComponent.java b/app/src/main/java/acr/browser/lightning/app/AppComponent.java index 94e9682..14e0b56 100644 --- a/app/src/main/java/acr/browser/lightning/app/AppComponent.java +++ b/app/src/main/java/acr/browser/lightning/app/AppComponent.java @@ -37,4 +37,6 @@ public interface AppComponent { PreferenceManager getPreferenceManager(); void inject(LightningPreferenceFragment fragment); + + BookmarkPage getBookmarkPage(); } diff --git a/app/src/main/java/acr/browser/lightning/constant/BookmarkPage.java b/app/src/main/java/acr/browser/lightning/constant/BookmarkPage.java index 6137cc1..2c3a8dc 100644 --- a/app/src/main/java/acr/browser/lightning/constant/BookmarkPage.java +++ b/app/src/main/java/acr/browser/lightning/constant/BookmarkPage.java @@ -62,7 +62,8 @@ public final class BookmarkPage { CACHE_DIR = context.getCacheDir(); } - public void buildBookmarkPage(final String folder, final List list) { + public void buildBookmarkPage(final String folder) { + final List list = manager.getBookmarksFromFolder(folder, true); final File bookmarkWebPage; if (folder == null || folder.isEmpty()) { bookmarkWebPage = new File(FILES_DIR, Constants.BOOKMARKS_FILENAME); @@ -83,7 +84,7 @@ public final class BookmarkPage { new Thread(new Runnable() { @Override public void run() { - buildBookmarkPage(item.getTitle(), manager.getBookmarksFromFolder(item.getTitle(), true)); + buildBookmarkPage(item.getTitle()); } }).run(); } else { diff --git a/app/src/main/java/acr/browser/lightning/controller/BrowserController.java b/app/src/main/java/acr/browser/lightning/controller/BrowserController.java index 21750a8..7f4944a 100644 --- a/app/src/main/java/acr/browser/lightning/controller/BrowserController.java +++ b/app/src/main/java/acr/browser/lightning/controller/BrowserController.java @@ -48,8 +48,6 @@ public interface BrowserController { void longClickPage(String url); - void openBookmarkPage(WebView view); - void showFileChooser(ValueCallback filePathCallback); void closeEmptyTab(); diff --git a/app/src/main/java/acr/browser/lightning/utils/IntentUtils.java b/app/src/main/java/acr/browser/lightning/utils/IntentUtils.java index fb4e177..820d274 100644 --- a/app/src/main/java/acr/browser/lightning/utils/IntentUtils.java +++ b/app/src/main/java/acr/browser/lightning/utils/IntentUtils.java @@ -2,6 +2,7 @@ package acr.browser.lightning.utils; import android.app.Activity; import android.content.ActivityNotFoundException; +import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; @@ -19,7 +20,7 @@ import acr.browser.lightning.controller.BrowserController; public class IntentUtils { - private final Activity mActivity; + private final Context mActivity; private static final Pattern ACCEPTED_URI_SCHEMA = Pattern.compile("(?i)" + // switch on case insensitive matching @@ -28,8 +29,8 @@ public class IntentUtils { "(?:http|https|file):\\/\\/" + "|(?:inline|data|about|javascript):" + "|(?:.*:.*@)" + ')' + "(.*)"); - public IntentUtils(BrowserController controller) { - mActivity = controller.getActivity(); + public IntentUtils(Context context) { + mActivity = context.getApplicationContext(); } public boolean startActivityForUrl(WebView tab, String url) { @@ -64,9 +65,11 @@ public class IntentUtils { return false; } try { - if (mActivity.startActivityIfNeeded(intent, -1)) { - return true; - } + // TODO Restore this +// if (mActivity.startActivityIfNeeded(intent, -1)) { +// return true; +// } + mActivity.startActivity(intent); } catch (ActivityNotFoundException ex) { ex.printStackTrace(); } diff --git a/app/src/main/java/acr/browser/lightning/view/LightningView.java b/app/src/main/java/acr/browser/lightning/view/LightningView.java index 011d97e..c3bcb82 100644 --- a/app/src/main/java/acr/browser/lightning/view/LightningView.java +++ b/app/src/main/java/acr/browser/lightning/view/LightningView.java @@ -51,6 +51,7 @@ import android.widget.LinearLayout; import java.io.ByteArrayInputStream; import java.io.File; +import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.net.URISyntaxException; @@ -75,14 +76,13 @@ public class LightningView { private final Title mTitle; private WebView mWebView; private final boolean mIsIncognitoTab; - private final BrowserController mBrowserController; + private final BrowserController mBrowserController = null; // TODO REMOVE private final GestureDetector mGestureDetector; private final Activity mActivity; private static String mHomepage; private static String mDefaultUserAgent; // TODO fix so that mWebpageBitmap can be static - static changes the icon when switching from light to dark and then back to light private final Bitmap mWebpageBitmap; - @Inject PreferenceManager mPreferences; private final AdBlock mAdBlock; private final IntentUtils mIntentUtils; @@ -104,7 +104,7 @@ public class LightningView { private static final String[] PERMISSIONS = new String[]{Manifest.permission.ACCESS_FINE_LOCATION}; @SuppressLint("NewApi") - public LightningView(Activity activity, String url, boolean darkTheme, boolean isIncognito, BrowserController controller) { + public LightningView(Activity activity, String url, boolean darkTheme, boolean isIncognito) { mPreferences = BrowserApp.getAppComponent().getPreferenceManager(); mActivity = activity; mWebView = new WebView(activity); @@ -117,9 +117,7 @@ public class LightningView { mMaxFling = ViewConfiguration.get(activity).getScaledMaximumFlingVelocity(); - mBrowserController = controller; - - mIntentUtils = new IntentUtils(mBrowserController); + mIntentUtils = new IntentUtils(activity); mWebView.setDrawingCacheBackgroundColor(Color.WHITE); mWebView.setFocusableInTouchMode(true); mWebView.setFocusable(true); @@ -161,12 +159,37 @@ public class LightningView { if (mHomepage.startsWith("about:home")) { mWebView.loadUrl(StartPage.getHomepage(mActivity)); } else if (mHomepage.startsWith("about:bookmarks")) { - mBrowserController.openBookmarkPage(mWebView); + loadBookmarkpage(); } else { mWebView.loadUrl(mHomepage); } } + /** + * Load the HTML bookmarks page in this view + */ + public void loadBookmarkpage() { + if (mWebView == null) + return; + Bitmap folderIcon = ThemeUtils.getThemedBitmap(mActivity, R.drawable.ic_folder, false); + FileOutputStream outputStream = null; + File image = new File(mActivity.getCacheDir(), "folder.png"); + try { + outputStream = new FileOutputStream(image); + folderIcon.compress(Bitmap.CompressFormat.PNG, 100, outputStream); + folderIcon.recycle(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } finally { + Utils.close(outputStream); + } + File bookmarkWebPage = new File(mActivity.getFilesDir(), Constants.BOOKMARKS_FILENAME); + + BrowserApp.getAppComponent().getBookmarkPage().buildBookmarkPage(null); + mWebView.loadUrl(Constants.FILE + bookmarkWebPage); + + } + /** * Initialize the preference driven settings of the WebView * From 030b839aa63c029e2811cae26e892595e121a968 Mon Sep 17 00:00:00 2001 From: Stefano Pacifici Date: Thu, 17 Sep 2015 09:46:00 +0200 Subject: [PATCH 10/16] Trying to remove BrowserController interface --- .../browser/lightning/utils/ProxyUtils.java | 11 ++++--- .../lightning/activity/BrowserActivity.java | 29 ++++++++++--------- .../lightning/activity/TabsManager.java | 2 +- .../browser/lightning/app/AppComponent.java | 8 +++++ .../browser/lightning/bus/BrowserEvents.java | 24 +++++++++++++++ .../controller/BrowserController.java | 4 --- .../browser/lightning/view/LightningView.java | 24 +++++++++------ 7 files changed, 70 insertions(+), 32 deletions(-) diff --git a/app/src/LightningPlus/java/acr/browser/lightning/utils/ProxyUtils.java b/app/src/LightningPlus/java/acr/browser/lightning/utils/ProxyUtils.java index 3942f7d..3847e58 100644 --- a/app/src/LightningPlus/java/acr/browser/lightning/utils/ProxyUtils.java +++ b/app/src/LightningPlus/java/acr/browser/lightning/utils/ProxyUtils.java @@ -11,6 +11,7 @@ import net.i2p.android.ui.I2PAndroidHelper; import acr.browser.lightning.R; import acr.browser.lightning.app.BrowserApp; +import acr.browser.lightning.bus.BrowserEvents; import acr.browser.lightning.constant.Constants; import acr.browser.lightning.preference.PreferenceManager; import info.guardianproject.netcipher.proxy.OrbotHelper; @@ -144,13 +145,15 @@ public class ProxyUtils { } - public boolean isProxyReady(Activity activity) { + public boolean isProxyReady() { if (mPreferences.getProxyChoice() == Constants.PROXY_I2P) { if (!mI2PHelper.isI2PAndroidRunning()) { - Utils.showSnackbar(activity, R.string.i2p_not_running); + BrowserApp.getAppComponent().getBus() + .post(new BrowserEvents.ShowSnackBarMessage(R.string.i2p_not_running)); return false; } else if (!mI2PHelper.areTunnelsActive()) { - Utils.showSnackbar(activity, R.string.i2p_tunnels_not_ready); + BrowserApp.getAppComponent().getBus() + .post(new BrowserEvents.ShowSnackBarMessage(R.string.i2p_tunnels_not_ready)); return false; } } @@ -201,7 +204,7 @@ public class ProxyUtils { break; case Constants.PROXY_I2P: - I2PAndroidHelper ih = new I2PAndroidHelper(activity.getApplicationContext()); + I2PAndroidHelper ih = new I2PAndroidHelper(BrowserApp.getAppContext()); if (!ih.isI2PAndroidInstalled()) { choice = Constants.NO_PROXY; ih.promptToInstall(activity); diff --git a/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java b/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java index eb3821d..09f27dd 100644 --- a/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java +++ b/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java @@ -38,6 +38,7 @@ import android.provider.MediaStore; import android.support.annotation.IdRes; import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import android.support.design.widget.Snackbar; import android.support.v4.view.GravityCompat; import android.support.v4.view.ViewCompat; import android.support.v4.widget.DrawerLayout; @@ -1012,7 +1013,8 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements if (show) { showTab(tabsManager.size() - 1); } - updateTabs(); + // TODO Check is this is callable directly from LightningView + eventBus.post(new BrowserEvents.TabsChanged()); // TODO Restore this // new Handler().postDelayed(new Runnable() { @@ -1048,14 +1050,14 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements if (current > position) { tabsManager.deleteTab(position); showTab(current - 1); - updateTabs(); + eventBus.post(new BrowserEvents.TabsChanged()); tabToDelete.onDestroy(); } else if (tabsManager.size() > position + 1) { if (current == position) { showTab(position + 1); tabsManager.deleteTab(position); showTab(position); - updateTabs(); + eventBus.post(new BrowserEvents.TabsChanged()); } else { tabsManager.deleteTab(position); } @@ -1066,7 +1068,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements showTab(position - 1); tabsManager.deleteTab(position); showTab(position - 1); - updateTabs(); + eventBus.post(new BrowserEvents.TabsChanged()); } else { tabsManager.deleteTab(position); } @@ -1424,11 +1426,6 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements getUrl.setAdapter(mSearchAdapter); } - @Override - public boolean proxyIsNotReady() { - return !mProxyUtils.isProxyReady(this); - } - /** * function that opens the HTML history page in the browser */ @@ -1471,11 +1468,6 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements return super.onCreateOptionsMenu(menu); } - @Override - public void updateTabs() { - eventBus.post(new BrowserEvents.TabsChanged()); - } - /** * opens a file chooser * param ValueCallback is the message from the WebView indicating a file chooser @@ -2326,9 +2318,18 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements String url = mPreferences.getSavedUrl(); if (url != null) { BrowserActivity.this.newTab(url, true); + Utils.showSnackbar(mActivity, R.string.deleted_tab); } mPreferences.setSavedUrl(null); } + + @Subscribe + public void displayInSnackbar(final BrowserEvents.ShowSnackBarMessage event) { + if (event.message != null) { + Utils.showSnackbar(BrowserActivity.this, event.message); + } else { + Utils.showSnackbar(mActivity, event.stringRes); } + } }; } diff --git a/app/src/main/java/acr/browser/lightning/activity/TabsManager.java b/app/src/main/java/acr/browser/lightning/activity/TabsManager.java index c3dd109..1510cb7 100644 --- a/app/src/main/java/acr/browser/lightning/activity/TabsManager.java +++ b/app/src/main/java/acr/browser/lightning/activity/TabsManager.java @@ -119,7 +119,7 @@ public class TabsManager { final String url, final boolean darkTheme, final boolean isIncognito, final BrowserController controller) { - final LightningView tab = new LightningView(activity, url, darkTheme, isIncognito, controller); + final LightningView tab = new LightningView(activity, url, darkTheme, isIncognito); mWebViewList.add(tab); return tab; } diff --git a/app/src/main/java/acr/browser/lightning/app/AppComponent.java b/app/src/main/java/acr/browser/lightning/app/AppComponent.java index 14e0b56..76e1e46 100644 --- a/app/src/main/java/acr/browser/lightning/app/AppComponent.java +++ b/app/src/main/java/acr/browser/lightning/app/AppComponent.java @@ -1,5 +1,9 @@ package acr.browser.lightning.app; +import android.content.Context; + +import com.squareup.otto.Bus; + import javax.inject.Singleton; import acr.browser.lightning.activity.BrowserActivity; @@ -39,4 +43,8 @@ public interface AppComponent { void inject(LightningPreferenceFragment fragment); BookmarkPage getBookmarkPage(); + + Bus getBus(); + + Context getApplicationContext(); } diff --git a/app/src/main/java/acr/browser/lightning/bus/BrowserEvents.java b/app/src/main/java/acr/browser/lightning/bus/BrowserEvents.java index d461205..250d8d2 100644 --- a/app/src/main/java/acr/browser/lightning/bus/BrowserEvents.java +++ b/app/src/main/java/acr/browser/lightning/bus/BrowserEvents.java @@ -1,5 +1,10 @@ package acr.browser.lightning.bus; +import android.support.annotation.IdRes; +import android.support.annotation.StringRes; + +import acr.browser.lightning.R; + /** * Created by Stefano Pacifici on 26/08/15. */ @@ -46,4 +51,23 @@ public final class BrowserEvents { */ public static class TabsChanged { } + + /** + * Notify the Browser to display a SnackBar in the main activity + */ + public static class ShowSnackBarMessage { + public final String message; + @StringRes + public final int stringRes; + + public ShowSnackBarMessage(final String message) { + this.message = message; + this.stringRes = -1; + } + + public ShowSnackBarMessage(@StringRes final int stringRes) { + this.message = null; + this.stringRes = stringRes; + } + } } diff --git a/app/src/main/java/acr/browser/lightning/controller/BrowserController.java b/app/src/main/java/acr/browser/lightning/controller/BrowserController.java index 7f4944a..51e4528 100644 --- a/app/src/main/java/acr/browser/lightning/controller/BrowserController.java +++ b/app/src/main/java/acr/browser/lightning/controller/BrowserController.java @@ -24,8 +24,6 @@ public interface BrowserController { void openFileChooser(ValueCallback uploadMsg); - void updateTabs(); - void onLongPress(); void onShowCustomView(View view, CustomViewCallback callback); @@ -52,8 +50,6 @@ public interface BrowserController { void closeEmptyTab(); - boolean proxyIsNotReady(); - // void updateBookmarkIndicator(String url); } diff --git a/app/src/main/java/acr/browser/lightning/view/LightningView.java b/app/src/main/java/acr/browser/lightning/view/LightningView.java index c3bcb82..cdce9a3 100644 --- a/app/src/main/java/acr/browser/lightning/view/LightningView.java +++ b/app/src/main/java/acr/browser/lightning/view/LightningView.java @@ -49,6 +49,8 @@ import android.webkit.WebViewClient; import android.widget.EditText; import android.widget.LinearLayout; +import com.squareup.otto.Bus; + import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileNotFoundException; @@ -60,6 +62,7 @@ import javax.inject.Inject; import acr.browser.lightning.R; import acr.browser.lightning.app.BrowserApp; +import acr.browser.lightning.bus.BrowserEvents; import acr.browser.lightning.constant.Constants; import acr.browser.lightning.constant.StartPage; import acr.browser.lightning.controller.BrowserController; @@ -68,6 +71,7 @@ import acr.browser.lightning.preference.PreferenceManager; import acr.browser.lightning.utils.AdBlock; import acr.browser.lightning.utils.IntentUtils; import acr.browser.lightning.utils.PermissionsManager; +import acr.browser.lightning.utils.ProxyUtils; import acr.browser.lightning.utils.ThemeUtils; import acr.browser.lightning.utils.Utils; @@ -103,8 +107,11 @@ public class LightningView { private final PermissionsManager mPermissionsManager; private static final String[] PERMISSIONS = new String[]{Manifest.permission.ACCESS_FINE_LOCATION}; + private final Bus eventBus; + @SuppressLint("NewApi") public LightningView(Activity activity, String url, boolean darkTheme, boolean isIncognito) { + eventBus = BrowserApp.getAppComponent().getBus(); mPreferences = BrowserApp.getAppComponent().getPreferenceManager(); mActivity = activity; mWebView = new WebView(activity); @@ -419,7 +426,7 @@ public class LightningView { public void setForegroundTab(boolean isForeground) { isForegroundTab = isForeground; - mBrowserController.updateTabs(); + eventBus.post(new BrowserEvents.TabsChanged()); } public boolean isForegroundTab() { @@ -522,7 +529,7 @@ public class LightningView { public synchronized void reload() { // Check if configured proxy is available - if (mBrowserController.proxyIsNotReady()) { + if (!ProxyUtils.getInstance().isProxyReady()) { // User has been notified return; } @@ -625,8 +632,7 @@ public class LightningView { public synchronized void loadUrl(String url) { // Check if configured proxy is available - if (mBrowserController.proxyIsNotReady()) { - // User has been notified + if (!ProxyUtils.getInstance().isProxyReady()) { return; } @@ -697,7 +703,7 @@ public class LightningView { if (API >= android.os.Build.VERSION_CODES.KITKAT && mInvertPage) { view.evaluateJavascript(Constants.JAVASCRIPT_INVERT_PAGE, null); } - mBrowserController.updateTabs(); + eventBus.post(new BrowserEvents.TabsChanged()); } @Override @@ -707,7 +713,7 @@ public class LightningView { mBrowserController.showActionBar(); } mTitle.setFavicon(mWebpageBitmap); - mBrowserController.updateTabs(); + eventBus.post(new BrowserEvents.TabsChanged()); } @Override @@ -839,7 +845,7 @@ public class LightningView { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { // Check if configured proxy is available - if (mBrowserController.proxyIsNotReady()) { + if (!ProxyUtils.getInstance().isProxyReady()) { // User has been notified return true; } @@ -897,7 +903,7 @@ public class LightningView { if (icon == null) return; mTitle.setFavicon(icon); - mBrowserController.updateTabs(); + eventBus.post(new BrowserEvents.TabsChanged()); ; cacheFavicon(icon); } @@ -908,7 +914,7 @@ public class LightningView { } else { mTitle.setTitle(mActivity.getString(R.string.untitled)); } - mBrowserController.updateTabs(); + eventBus.post(new BrowserEvents.TabsChanged()); ; if (view != null) mBrowserController.updateHistory(title, view.getUrl()); } From 36150188164966779fdb662e0af854272e83fbf9 Mon Sep 17 00:00:00 2001 From: Stefano Pacifici Date: Thu, 17 Sep 2015 11:23:35 +0200 Subject: [PATCH 11/16] ClickHandler removed, avoid call loop duirng long press on a webview between BrowserActivity and LightningView --- .../lightning/activity/BrowserActivity.java | 75 ----------------- .../browser/lightning/app/AppComponent.java | 3 + .../browser/lightning/bus/BrowserEvents.java | 1 + .../controller/BrowserController.java | 4 +- .../lightning/object/ClickHandler.java | 30 ------- .../browser/lightning/view/LightningView.java | 82 +++++++++++++++++-- 6 files changed, 82 insertions(+), 113 deletions(-) delete mode 100644 app/src/main/java/acr/browser/lightning/object/ClickHandler.java diff --git a/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java b/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java index 09f27dd..d42a574 100644 --- a/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java +++ b/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java @@ -117,7 +117,6 @@ import acr.browser.lightning.database.BookmarkManager; import acr.browser.lightning.database.HistoryDatabase; import acr.browser.lightning.dialog.BookmarksDialogBuilder; import acr.browser.lightning.fragment.TabsFragment; -import acr.browser.lightning.object.ClickHandler; import acr.browser.lightning.object.SearchAdapter; import acr.browser.lightning.preference.PreferenceManager; import acr.browser.lightning.receiver.NetworkReceiver; @@ -150,7 +149,6 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements private SearchAdapter mSearchAdapter; // Callback - private ClickHandler mClickHandler; private CustomViewCallback mCustomViewCallback; private ValueCallback mUploadMessage; private ValueCallback mFilePathCallback; @@ -240,7 +238,6 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements mActivity = this; - mClickHandler = new ClickHandler(this); mBrowserFrame = (FrameLayout) findViewById(R.id.content_frame); mToolbarLayout = (LinearLayout) findViewById(R.id.toolbar_layout); // initialize background ColorDrawable @@ -1572,26 +1569,6 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements mActivity.startActivityForResult(chooserIntent, 1); } - /** - * handles long presses for the browser, tries to get the - * url of the item that was clicked and sends it (it can be null) - * to the click handler that does cool stuff with it - */ - @Override - public void onLongPress() { - if (mClickHandler == null) { - mClickHandler = new ClickHandler(mActivity); - } - Message click = mClickHandler.obtainMessage(); - if (click != null) { - click.setTarget(mClickHandler); - final WebView currentWebView = tabsManager.getCurrentWebView(); - if (currentWebView != null) { - currentWebView.requestFocusNodeHref(click); - } - } - } - @Override public void onShowCustomView(View view, CustomViewCallback callback) { final LightningView currentTab = tabsManager.getCurrentTab(); @@ -1871,58 +1848,6 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements } } - /** - * handles a long click on the page, parameter String url - * is the url that should have been obtained from the WebView touch node - * thingy, if it is null, this method tries to deal with it and find a workaround - */ - @Override - public void longClickPage(final String url) { - HitTestResult result = null; - String currentUrl = null; - final WebView currentWebView = tabsManager.getCurrentWebView(); - if (currentWebView != null) { - result = currentWebView.getHitTestResult(); - currentUrl = currentWebView.getUrl(); - } - if (currentUrl != null && currentUrl.startsWith(Constants.FILE)) { - if (currentUrl.endsWith(HistoryPage.FILENAME)) { - if (url != null) { - longPressHistoryLink(url); - } else if (result != null && result.getExtra() != null) { - final String newUrl = result.getExtra(); - longPressHistoryLink(newUrl); - } - } else if (currentUrl.endsWith(Constants.BOOKMARKS_FILENAME)) { - if (url != null) { - bookmarksDialogBuilder.showLongPressedDialogForUrl(this, url); - } else if (result != null && result.getExtra() != null) { - final String newUrl = result.getExtra(); - bookmarksDialogBuilder.showLongPressedDialogForUrl(this, newUrl); - } - } - } else { - if (url != null) { - if (result != null) { - if (result.getType() == HitTestResult.SRC_IMAGE_ANCHOR_TYPE || result.getType() == HitTestResult.IMAGE_TYPE) { - longPressImage(url); - } else { - longPressLink(url); - } - } else { - longPressLink(url); - } - } else if (result != null && result.getExtra() != null) { - final String newUrl = result.getExtra(); - if (result.getType() == HitTestResult.SRC_IMAGE_ANCHOR_TYPE || result.getType() == HitTestResult.IMAGE_TYPE) { - longPressImage(newUrl); - } else { - longPressLink(newUrl); - } - } - } - } - private void longPressHistoryLink(final String url) { DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() { @Override diff --git a/app/src/main/java/acr/browser/lightning/app/AppComponent.java b/app/src/main/java/acr/browser/lightning/app/AppComponent.java index 76e1e46..6b54710 100644 --- a/app/src/main/java/acr/browser/lightning/app/AppComponent.java +++ b/app/src/main/java/acr/browser/lightning/app/AppComponent.java @@ -15,6 +15,7 @@ import acr.browser.lightning.fragment.LightningPreferenceFragment; import acr.browser.lightning.fragment.TabsFragment; import acr.browser.lightning.object.SearchAdapter; import acr.browser.lightning.preference.PreferenceManager; +import acr.browser.lightning.view.LightningView; import dagger.Component; /** @@ -47,4 +48,6 @@ public interface AppComponent { Bus getBus(); Context getApplicationContext(); + + void inject(LightningView lightningView); } diff --git a/app/src/main/java/acr/browser/lightning/bus/BrowserEvents.java b/app/src/main/java/acr/browser/lightning/bus/BrowserEvents.java index 250d8d2..06e4d2d 100644 --- a/app/src/main/java/acr/browser/lightning/bus/BrowserEvents.java +++ b/app/src/main/java/acr/browser/lightning/bus/BrowserEvents.java @@ -1,6 +1,7 @@ package acr.browser.lightning.bus; import android.support.annotation.IdRes; +import android.support.annotation.Nullable; import android.support.annotation.StringRes; import acr.browser.lightning.R; diff --git a/app/src/main/java/acr/browser/lightning/controller/BrowserController.java b/app/src/main/java/acr/browser/lightning/controller/BrowserController.java index 51e4528..34ae451 100644 --- a/app/src/main/java/acr/browser/lightning/controller/BrowserController.java +++ b/app/src/main/java/acr/browser/lightning/controller/BrowserController.java @@ -24,7 +24,7 @@ public interface BrowserController { void openFileChooser(ValueCallback uploadMsg); - void onLongPress(); +// void onLongPress(); void onShowCustomView(View view, CustomViewCallback callback); @@ -44,7 +44,7 @@ public interface BrowserController { void showActionBar(); - void longClickPage(String url); + // void longClickPage(String url); void showFileChooser(ValueCallback filePathCallback); diff --git a/app/src/main/java/acr/browser/lightning/object/ClickHandler.java b/app/src/main/java/acr/browser/lightning/object/ClickHandler.java deleted file mode 100644 index 841c03f..0000000 --- a/app/src/main/java/acr/browser/lightning/object/ClickHandler.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2014 A.C.R. Development - */ -package acr.browser.lightning.object; - -import android.content.Context; -import android.os.Handler; -import android.os.Message; - -import acr.browser.lightning.controller.BrowserController; - -public class ClickHandler extends Handler { - - private BrowserController mBrowserController; - - public ClickHandler(Context context) { - try { - mBrowserController = (BrowserController) context; - } catch (ClassCastException e) { - throw new ClassCastException(context + " must implement BrowserController"); - } - } - - @Override - public void handleMessage(Message msg) { - super.handleMessage(msg); - String url = msg.getData().getString("url"); - mBrowserController.longClickPage(url); - } -} diff --git a/app/src/main/java/acr/browser/lightning/view/LightningView.java b/app/src/main/java/acr/browser/lightning/view/LightningView.java index cdce9a3..5b43ffe 100644 --- a/app/src/main/java/acr/browser/lightning/view/LightningView.java +++ b/app/src/main/java/acr/browser/lightning/view/LightningView.java @@ -20,6 +20,7 @@ import android.net.MailTo; import android.net.Uri; import android.net.http.SslError; import android.os.Build; +import android.os.Handler; import android.os.Message; import android.support.annotation.NonNull; import android.support.annotation.Nullable; @@ -63,9 +64,12 @@ import javax.inject.Inject; import acr.browser.lightning.R; import acr.browser.lightning.app.BrowserApp; import acr.browser.lightning.bus.BrowserEvents; +import acr.browser.lightning.bus.TabEvents; import acr.browser.lightning.constant.Constants; +import acr.browser.lightning.constant.HistoryPage; import acr.browser.lightning.constant.StartPage; import acr.browser.lightning.controller.BrowserController; +import acr.browser.lightning.dialog.BookmarksDialogBuilder; import acr.browser.lightning.download.LightningDownloadListener; import acr.browser.lightning.preference.PreferenceManager; import acr.browser.lightning.utils.AdBlock; @@ -87,7 +91,6 @@ public class LightningView { private static String mDefaultUserAgent; // TODO fix so that mWebpageBitmap can be static - static changes the icon when switching from light to dark and then back to light private final Bitmap mWebpageBitmap; - PreferenceManager mPreferences; private final AdBlock mAdBlock; private final IntentUtils mIntentUtils; private final Paint mPaint = new Paint(); @@ -106,13 +109,20 @@ public class LightningView { }; private final PermissionsManager mPermissionsManager; private static final String[] PERMISSIONS = new String[]{Manifest.permission.ACCESS_FINE_LOCATION}; + private final WebViewHandler webViewHandler = new WebViewHandler(); + + @Inject + Bus eventBus; + + @Inject + PreferenceManager mPreferences; - private final Bus eventBus; + @Inject + BookmarksDialogBuilder bookmarksDialogBuilder; @SuppressLint("NewApi") public LightningView(Activity activity, String url, boolean darkTheme, boolean isIncognito) { - eventBus = BrowserApp.getAppComponent().getBus(); - mPreferences = BrowserApp.getAppComponent().getPreferenceManager(); + BrowserApp.getAppComponent().inject(this); mActivity = activity; mWebView = new WebView(activity); mIsIncognitoTab = isIncognito; @@ -613,6 +623,52 @@ public class LightningView { } } + /** + * handles a long click on the page, parameter String url + * is the url that should have been obtained from the WebView touch node + * thingy, if it is null, this method tries to deal with it and find a workaround + */ + private void longClickPage(final String url) { + final WebView.HitTestResult result = mWebView.getHitTestResult(); + String currentUrl = mWebView.getUrl(); + if (currentUrl != null && currentUrl.startsWith(Constants.FILE)) { + if (currentUrl.endsWith(HistoryPage.FILENAME)) { + if (url != null) { + // TODO longPressHistoryLink(url); + } else if (result != null && result.getExtra() != null) { + final String newUrl = result.getExtra(); + // TODO longPressHistoryLink(newUrl); + } + } else if (currentUrl.endsWith(Constants.BOOKMARKS_FILENAME)) { + if (url != null) { + bookmarksDialogBuilder.showLongPressedDialogForUrl(mActivity, url); + } else if (result != null && result.getExtra() != null) { + final String newUrl = result.getExtra(); + bookmarksDialogBuilder.showLongPressedDialogForUrl(mActivity, newUrl); + } + } + } else { + if (url != null) { + if (result != null) { + if (result.getType() == WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE || result.getType() == WebView.HitTestResult.IMAGE_TYPE) { + // TODO longPressImage(url); + } else { + // TODO longPressLink(url); + } + } else { + // TODO longPressLink(url); + } + } else if (result != null && result.getExtra() != null) { + final String newUrl = result.getExtra(); + if (result.getType() == WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE || result.getType() == WebView.HitTestResult.IMAGE_TYPE) { + // TODO longPressImage(newUrl); + } else { + // TODO longPressLink(newUrl); + } + } + } + } + public boolean canGoBack() { return mWebView != null && mWebView.canGoBack(); } @@ -1149,8 +1205,13 @@ public class LightningView { @Override public void onLongPress(MotionEvent e) { - if (mCanTriggerLongPress) - mBrowserController.onLongPress(); + if (mCanTriggerLongPress) { + Message msg = webViewHandler.obtainMessage(); + if (msg != null) { + msg.setTarget(webViewHandler); + mWebView.requestFocusNodeHref(msg); + } + } } /** @@ -1172,4 +1233,13 @@ public class LightningView { mCanTriggerLongPress = true; } } + + private class WebViewHandler extends Handler { + @Override + public void handleMessage(Message msg) { + super.handleMessage(msg); + final String url = msg.getData().getString("url"); + longClickPage(url); + } + } } From 6749ca39b8c005a6e1e54d23e4d532763e9e1971 Mon Sep 17 00:00:00 2001 From: Stefano Pacifici Date: Tue, 22 Sep 2015 16:15:17 +0200 Subject: [PATCH 12/16] Simplified LightningView with externalized XXXClients --- .../lightning/activity/BrowserActivity.java | 196 +------ .../lightning/activity/TabsManager.java | 32 +- .../browser/lightning/app/AppComponent.java | 7 +- .../browser/lightning/bus/BookmarkEvents.java | 22 - .../browser/lightning/bus/BrowserEvents.java | 42 +- .../lightning/constant/HistoryPage.java | 2 +- .../lightning/database/HistoryDatabase.java | 14 +- ...ilder.java => LightningDialogBuilder.java} | 124 +++- .../lightning/fragment/BookmarksFragment.java | 8 +- .../lightning/object/SearchAdapter.java | 19 +- .../acr/browser/lightning/utils/WebUtils.java | 3 +- .../lightning/view/LightningChromeClient.java | 234 ++++++++ .../browser/lightning/view/LightningView.java | 555 ++---------------- .../lightning/view/LightningViewTitle.java | 66 +++ .../lightning/view/LightningWebClient.java | 276 +++++++++ 15 files changed, 833 insertions(+), 767 deletions(-) rename app/src/main/java/acr/browser/lightning/dialog/{BookmarksDialogBuilder.java => LightningDialogBuilder.java} (60%) create mode 100644 app/src/main/java/acr/browser/lightning/view/LightningChromeClient.java create mode 100644 app/src/main/java/acr/browser/lightning/view/LightningViewTitle.java create mode 100644 app/src/main/java/acr/browser/lightning/view/LightningWebClient.java diff --git a/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java b/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java index d42a574..0188bdc 100644 --- a/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java +++ b/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java @@ -18,14 +18,8 @@ import android.content.IntentFilter; import android.database.sqlite.SQLiteException; import android.graphics.Bitmap; import android.graphics.BitmapFactory; -import android.graphics.Canvas; import android.graphics.Color; -import android.graphics.ColorFilter; -import android.graphics.ColorMatrix; -import android.graphics.ColorMatrixColorFilter; -import android.graphics.Paint; import android.graphics.PorterDuff; -import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.media.MediaPlayer; @@ -38,17 +32,13 @@ import android.provider.MediaStore; import android.support.annotation.IdRes; import android.support.annotation.NonNull; import android.support.annotation.Nullable; -import android.support.design.widget.Snackbar; import android.support.v4.view.GravityCompat; -import android.support.v4.view.ViewCompat; import android.support.v4.widget.DrawerLayout; import android.support.v4.widget.DrawerLayout.DrawerListener; import android.support.v7.app.ActionBar; import android.support.v7.app.AlertDialog; import android.support.v7.graphics.Palette; import android.support.v7.graphics.drawable.DrawerArrowDrawable; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; import android.support.v7.widget.Toolbar; import android.util.Log; import android.view.KeyEvent; @@ -76,7 +66,6 @@ import android.webkit.ValueCallback; import android.webkit.WebChromeClient.CustomViewCallback; import android.webkit.WebIconDatabase; import android.webkit.WebView; -import android.webkit.WebView.HitTestResult; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ArrayAdapter; @@ -95,11 +84,7 @@ import com.squareup.otto.Bus; import com.squareup.otto.Subscribe; import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; import java.io.IOException; -import java.util.ArrayList; -import java.util.List; import javax.inject.Inject; @@ -115,7 +100,7 @@ import acr.browser.lightning.constant.HistoryPage; import acr.browser.lightning.controller.BrowserController; import acr.browser.lightning.database.BookmarkManager; import acr.browser.lightning.database.HistoryDatabase; -import acr.browser.lightning.dialog.BookmarksDialogBuilder; +import acr.browser.lightning.dialog.LightningDialogBuilder; import acr.browser.lightning.fragment.TabsFragment; import acr.browser.lightning.object.SearchAdapter; import acr.browser.lightning.preference.PreferenceManager; @@ -166,10 +151,6 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements mCurrentUiColor = Color.BLACK; private String mSearchText, mUntitledTitle, mHomepage, mCameraPhotoPath; - // Storage - private HistoryDatabase mHistoryDatabase; - - // The singleton BookmarkManager @Inject BookmarkManager bookmarkManager; @@ -182,7 +163,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements BookmarkPage bookmarkPage; @Inject - BookmarksDialogBuilder bookmarksDialogBuilder; + LightningDialogBuilder bookmarksDialogBuilder; @Inject TabsManager tabsManager; @@ -190,6 +171,9 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements @Inject PreferenceManager mPreferences; + @Inject + HistoryDatabase mHistoryDatabase; + // Image private Bitmap mWebpageBitmap; private final ColorDrawable mBackground = new ColorDrawable(); @@ -280,8 +264,6 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements mToolbarLayout.removeView(findViewById(R.id.tabs_toolbar_container)); } - mHistoryDatabase = HistoryDatabase.getInstance(); - if (actionBar == null) return; @@ -356,7 +338,9 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements WebIconDatabase.getInstance().open(getDir("icons", MODE_PRIVATE).getPath()); } -// initializeTabs(); + tabsManager.restoreTabs(this, mDarkTheme, isIncognito()); + // At this point we always have at least a tab in the tab manager + showTab(0); mProxyUtils.checkForProxy(this); } @@ -565,45 +549,6 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements } } - /* TODO !!!! THIS MUST BY RESTORED ASAP !!!! - void restoreOrNewTab() { - mIdGenerator = 0; - - String url = null; - if (getIntent() != null) { - url = getIntent().getDataString(); - if (url != null) { - if (url.startsWith(Constants.FILE)) { - Utils.showSnackbar(this, R.string.message_blocked_local); - url = null; - } - } - } - if (mPreferences.getRestoreLostTabsEnabled()) { - String mem = mPreferences.getMemoryUrl(); - mPreferences.setMemoryUrl(""); - String[] array = Utils.getArray(mem); - int count = 0; - for (String urlString : array) { - if (!urlString.isEmpty()) { - if (url != null && url.compareTo(urlString) == 0) { - url = null; - } - newTab(urlString, true); - count++; - } - } - if (url != null) { - newTab(url, true); - } else if (count == 0) { - newTab(null, true); - } - } else { - newTab(url, true); - } - } - */ - private void initializePreferences() { final LightningView currentView = tabsManager.getCurrentTab(); final WebView currentWebView = currentView.getWebView(); @@ -1001,7 +946,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements return false; } mIsNewIntent = false; - LightningView startingTab = tabsManager.newTab(mActivity, url, mDarkTheme, isIncognito(), this); + LightningView startingTab = tabsManager.newTab(this, url, mDarkTheme, isIncognito()); if (mIdGenerator == 0) { startingTab.resumeTimers(); } @@ -1227,7 +1172,6 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements currentTab.resumeTimers(); currentTab.onResume(); } - mHistoryDatabase = HistoryDatabase.getInstance(); initializePreferences(); tabsManager.resume(this); @@ -1366,9 +1310,6 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements @Override public void run() { try { - if (mHistoryDatabase == null) { - mHistoryDatabase = HistoryDatabase.getInstance(); - } mHistoryDatabase.visitHistoryItem(url, title); } catch (IllegalStateException e) { Log.e(Constants.TAG, "IllegalStateException in updateHistory", e); @@ -1848,107 +1789,6 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements } } - private void longPressHistoryLink(final String url) { - DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - final LightningView currentTab = tabsManager.getCurrentTab(); - switch (which) { - case DialogInterface.BUTTON_POSITIVE: - newTab(url, false); - mDrawerLayout.closeDrawers(); - break; - - case DialogInterface.BUTTON_NEGATIVE: - mHistoryDatabase.deleteHistoryItem(url); - openHistory(); - break; - - case DialogInterface.BUTTON_NEUTRAL: - if (currentTab != null) { - loadUrlInCurrentView(url); - } - break; - } - } - }; - - AlertDialog.Builder builder = new AlertDialog.Builder(mActivity); - builder.setTitle(R.string.action_history) - .setMessage(R.string.dialog_history_long_press) - .setCancelable(true) - .setPositiveButton(R.string.action_new_tab, dialogClickListener) - .setNegativeButton(R.string.action_delete, dialogClickListener) - .setNeutralButton(R.string.action_open, dialogClickListener) - .show(); - } - - private void longPressImage(final String url) { - DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - final LightningView currentTab = tabsManager.getCurrentTab(); - switch (which) { - case DialogInterface.BUTTON_POSITIVE: - newTab(url, false); - break; - - case DialogInterface.BUTTON_NEGATIVE: - loadUrlInCurrentView(url); - break; - - case DialogInterface.BUTTON_NEUTRAL: - if (API > 8) { - Utils.downloadFile(mActivity, url, - currentTab.getUserAgent(), "attachment"); - } - break; - } - } - }; - - AlertDialog.Builder builder = new AlertDialog.Builder(mActivity); - builder.setTitle(url.replace(Constants.HTTP, "")) - .setCancelable(true) - .setMessage(R.string.dialog_image) - .setPositiveButton(R.string.action_new_tab, dialogClickListener) - .setNegativeButton(R.string.action_open, dialogClickListener) - .setNeutralButton(R.string.action_download, dialogClickListener) - .show(); - } - - private void longPressLink(final String url) { - DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - switch (which) { - case DialogInterface.BUTTON_POSITIVE: - newTab(url, false); - break; - - case DialogInterface.BUTTON_NEGATIVE: - loadUrlInCurrentView(url); - break; - - case DialogInterface.BUTTON_NEUTRAL: - ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE); - ClipData clip = ClipData.newPlainText("label", url); - clipboard.setPrimaryClip(clip); - break; - } - } - }; - - AlertDialog.Builder builder = new AlertDialog.Builder(mActivity); // dialog - builder.setTitle(url) - .setCancelable(true) - .setMessage(R.string.dialog_link) - .setPositiveButton(R.string.action_new_tab, dialogClickListener) - .setNegativeButton(R.string.action_open, dialogClickListener) - .setNeutralButton(R.string.action_copy, dialogClickListener) - .show(); - } - /** * This method lets the search bar know that the page is currently loading * and that it should display the stop icon to indicate to the user that @@ -2058,13 +1898,14 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements private final Object busEventListener = new Object() { /** - * Load the given bookmark in the current tab, used by the the - * {@link acr.browser.lightning.fragment.BookmarksFragment} + * Load the given url in the current tab, used by the the + * {@link acr.browser.lightning.fragment.BookmarksFragment} and by the + * {@link LightningDialogBuilder} * @param event The event as it comes from the bus */ @Subscribe - public void loadBookmarkInCurrentTab(final BookmarkEvents.Clicked event) { - loadUrlInCurrentView(event.bookmark.getUrl()); + public void loadUrlInCurrentTab(final BrowserEvents.OpenUrlInCurrentTab event) { + loadUrlInCurrentView(event.url); // keep any jank from happening when the drawer is closed after the // URL starts to load final Handler handler = new Handler(); @@ -2077,13 +1918,14 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements } /** - * Load the given bookmark in a new tab, used by the the - * {@link acr.browser.lightning.fragment.BookmarksFragment} + * Load the given url in a new tab, used by the the + * {@link acr.browser.lightning.fragment.BookmarksFragment} and by the + * {@link LightningDialogBuilder} * @param event The event as it comes from the bus */ @Subscribe - public void loadBookmarkInNewTab(final BookmarkEvents.AsNewTab event) { - BrowserActivity.this.newTab(event.bookmark.getUrl(), true); + public void loadUrlInNewTab(final BrowserEvents.OpenUrlInNewTab event) { + BrowserActivity.this.newTab(event.url, true); mDrawerLayout.closeDrawers(); } diff --git a/app/src/main/java/acr/browser/lightning/activity/TabsManager.java b/app/src/main/java/acr/browser/lightning/activity/TabsManager.java index 1510cb7..75d1a1d 100644 --- a/app/src/main/java/acr/browser/lightning/activity/TabsManager.java +++ b/app/src/main/java/acr/browser/lightning/activity/TabsManager.java @@ -13,6 +13,7 @@ import javax.inject.Singleton; import acr.browser.lightning.controller.BrowserController; import acr.browser.lightning.preference.PreferenceManager; +import acr.browser.lightning.utils.Utils; import acr.browser.lightning.view.LightningView; /** @@ -26,7 +27,30 @@ public class TabsManager { private LightningView mCurrentTab; @Inject - public TabsManager(final Context context, final PreferenceManager preferenceManager) { + PreferenceManager mPreferenceManager; + + @Inject + public TabsManager() { + } + + public void restoreTabs(BrowserActivity activity, boolean darkTheme, boolean incognito) { + mWebViewList.clear(); + mCurrentTab = null; + if (!incognito && mPreferenceManager.getRestoreLostTabsEnabled()) { + final String mem = mPreferenceManager.getMemoryUrl(); + mPreferenceManager.setMemoryUrl(""); + String[] array = Utils.getArray(mem); + int count = 0; + for (String urlString : array) { + if (!urlString.isEmpty()) { + newTab(activity, urlString, darkTheme, incognito); + } + } + } + if (mWebViewList.size() == 0) { + newTab(activity, null, darkTheme, incognito); + } + // mCurrentTab = mWebViewList.get(0); } /** @@ -112,13 +136,11 @@ public class TabsManager { * @param url * @param darkTheme * @param isIncognito - * @param controller * @return */ - public synchronized LightningView newTab(final Activity activity, + public synchronized LightningView newTab(final BrowserActivity activity, final String url, final boolean darkTheme, - final boolean isIncognito, - final BrowserController controller) { + final boolean isIncognito) { final LightningView tab = new LightningView(activity, url, darkTheme, isIncognito); mWebViewList.add(tab); return tab; diff --git a/app/src/main/java/acr/browser/lightning/app/AppComponent.java b/app/src/main/java/acr/browser/lightning/app/AppComponent.java index 6b54710..4eea3c7 100644 --- a/app/src/main/java/acr/browser/lightning/app/AppComponent.java +++ b/app/src/main/java/acr/browser/lightning/app/AppComponent.java @@ -8,7 +8,8 @@ import javax.inject.Singleton; import acr.browser.lightning.activity.BrowserActivity; import acr.browser.lightning.constant.BookmarkPage; -import acr.browser.lightning.dialog.BookmarksDialogBuilder; +import acr.browser.lightning.database.HistoryDatabase; +import acr.browser.lightning.dialog.LightningDialogBuilder; import acr.browser.lightning.fragment.BookmarkSettingsFragment; import acr.browser.lightning.fragment.BookmarksFragment; import acr.browser.lightning.fragment.LightningPreferenceFragment; @@ -33,7 +34,7 @@ public interface AppComponent { void inject(SearchAdapter adapter); - void inject(BookmarksDialogBuilder builder); + void inject(LightningDialogBuilder builder); void inject(BookmarkPage bookmarkPage); @@ -47,6 +48,8 @@ public interface AppComponent { Bus getBus(); + HistoryDatabase getHistoryDatabase(); + Context getApplicationContext(); void inject(LightningView lightningView); diff --git a/app/src/main/java/acr/browser/lightning/bus/BookmarkEvents.java b/app/src/main/java/acr/browser/lightning/bus/BookmarkEvents.java index 7b8846d..1bff1cb 100644 --- a/app/src/main/java/acr/browser/lightning/bus/BookmarkEvents.java +++ b/app/src/main/java/acr/browser/lightning/bus/BookmarkEvents.java @@ -11,28 +11,6 @@ public final class BookmarkEvents { // No instances } - /** - * A bookmark was clicked - */ - public final static class Clicked { - public final HistoryItem bookmark; - - public Clicked(final HistoryItem bookmark) { - this.bookmark = bookmark; - } - } - - /** - * The user ask to open the bookmark as new tab - */ - public final static class AsNewTab { - public final HistoryItem bookmark; - - public AsNewTab(final HistoryItem bookmark) { - this.bookmark = bookmark; - } - } - /** * The user ask to delete the selected bookmark */ diff --git a/app/src/main/java/acr/browser/lightning/bus/BrowserEvents.java b/app/src/main/java/acr/browser/lightning/bus/BrowserEvents.java index 06e4d2d..f115149 100644 --- a/app/src/main/java/acr/browser/lightning/bus/BrowserEvents.java +++ b/app/src/main/java/acr/browser/lightning/bus/BrowserEvents.java @@ -1,11 +1,7 @@ package acr.browser.lightning.bus; -import android.support.annotation.IdRes; -import android.support.annotation.Nullable; import android.support.annotation.StringRes; -import acr.browser.lightning.R; - /** * Created by Stefano Pacifici on 26/08/15. */ @@ -21,9 +17,9 @@ public final class BrowserEvents { * result is a new bookmark added. */ public static class AddBookmark { - public final String title, url; + public final java.lang.String title, url; - public AddBookmark(final String title, final String url) { + public AddBookmark(final java.lang.String title, final java.lang.String url) { this.title = title; this.url = url; } @@ -34,9 +30,9 @@ public final class BrowserEvents { * {@link acr.browser.lightning.fragment.BookmarksFragment} interface. */ public static class CurrentPageUrl { - public final String url; + public final java.lang.String url; - public CurrentPageUrl(final String url) { + public CurrentPageUrl(final java.lang.String url) { this.url = url; } } @@ -53,15 +49,19 @@ public final class BrowserEvents { public static class TabsChanged { } + /** + * + */ + /** * Notify the Browser to display a SnackBar in the main activity */ public static class ShowSnackBarMessage { - public final String message; + public final java.lang.String message; @StringRes public final int stringRes; - public ShowSnackBarMessage(final String message) { + public ShowSnackBarMessage(final java.lang.String message) { this.message = message; this.stringRes = -1; } @@ -71,4 +71,26 @@ public final class BrowserEvents { this.stringRes = stringRes; } } + + /** + * The user want to open the given url in the current tab + */ + public final static class OpenUrlInCurrentTab { + public final String url; + + public OpenUrlInCurrentTab(final String url) { + this.url = url; + } + } + + /** + * The user ask to open the given url as new tab + */ + public final static class OpenUrlInNewTab { + public final String url; + + public OpenUrlInNewTab(final String url) { + this.url = url; + } + } } diff --git a/app/src/main/java/acr/browser/lightning/constant/HistoryPage.java b/app/src/main/java/acr/browser/lightning/constant/HistoryPage.java index 41dc907..8e7d936 100644 --- a/app/src/main/java/acr/browser/lightning/constant/HistoryPage.java +++ b/app/src/main/java/acr/browser/lightning/constant/HistoryPage.java @@ -66,7 +66,7 @@ public class HistoryPage { } private static List getWebHistory(Context context) { - HistoryDatabase databaseHandler = HistoryDatabase.getInstance(); + HistoryDatabase databaseHandler = BrowserApp.getAppComponent().getHistoryDatabase(); return databaseHandler.getLastHundredItems(); } } diff --git a/app/src/main/java/acr/browser/lightning/database/HistoryDatabase.java b/app/src/main/java/acr/browser/lightning/database/HistoryDatabase.java index 8d42983..a10a0bb 100644 --- a/app/src/main/java/acr/browser/lightning/database/HistoryDatabase.java +++ b/app/src/main/java/acr/browser/lightning/database/HistoryDatabase.java @@ -12,9 +12,13 @@ import android.database.sqlite.SQLiteOpenHelper; import java.util.ArrayList; import java.util.List; +import javax.inject.Inject; +import javax.inject.Singleton; + import acr.browser.lightning.R; import acr.browser.lightning.app.BrowserApp; +@Singleton public class HistoryDatabase extends SQLiteOpenHelper { // All Static variables @@ -39,14 +43,8 @@ public class HistoryDatabase extends SQLiteOpenHelper { private boolean mLock; - public static HistoryDatabase getInstance() { - if (mInstance == null || mInstance.isClosed()) { - mInstance = new HistoryDatabase(BrowserApp.getAppContext()); - } - return mInstance; - } - - private HistoryDatabase(Context context) { + @Inject + public HistoryDatabase(Context context) { super(context.getApplicationContext(), DATABASE_NAME, null, DATABASE_VERSION); mDatabase = this.getWritableDatabase(); } diff --git a/app/src/main/java/acr/browser/lightning/dialog/BookmarksDialogBuilder.java b/app/src/main/java/acr/browser/lightning/dialog/LightningDialogBuilder.java similarity index 60% rename from app/src/main/java/acr/browser/lightning/dialog/BookmarksDialogBuilder.java rename to app/src/main/java/acr/browser/lightning/dialog/LightningDialogBuilder.java index 79235cc..c7ac9e9 100644 --- a/app/src/main/java/acr/browser/lightning/dialog/BookmarksDialogBuilder.java +++ b/app/src/main/java/acr/browser/lightning/dialog/LightningDialogBuilder.java @@ -1,8 +1,13 @@ package acr.browser.lightning.dialog; +import android.app.Activity; +import android.content.ClipData; +import android.content.ClipboardManager; import android.content.Context; import android.content.DialogInterface; import android.net.Uri; +import android.os.Build; +import android.support.annotation.NonNull; import android.support.v7.app.AlertDialog; import android.view.View; import android.widget.ArrayAdapter; @@ -19,24 +24,32 @@ import javax.inject.Inject; import acr.browser.lightning.R; import acr.browser.lightning.app.BrowserApp; import acr.browser.lightning.bus.BookmarkEvents; +import acr.browser.lightning.bus.BrowserEvents; import acr.browser.lightning.constant.Constants; +import acr.browser.lightning.constant.HistoryPage; import acr.browser.lightning.database.BookmarkManager; +import acr.browser.lightning.database.HistoryDatabase; import acr.browser.lightning.database.HistoryItem; import acr.browser.lightning.utils.Utils; /** + * TODO Rename this class it doesn't build dialogs only for bookmarks + * * Created by Stefano Pacifici on 02/09/15, based on Anthony C. Restaino's code. */ -public class BookmarksDialogBuilder { +public class LightningDialogBuilder { @Inject BookmarkManager bookmarkManager; + @Inject + HistoryDatabase mHistoryDatabase; + @Inject Bus eventBus; @Inject - public BookmarksDialogBuilder() { + public LightningDialogBuilder() { BrowserApp.getAppComponent().inject(this); } @@ -46,7 +59,7 @@ public class BookmarksDialogBuilder { * @param context used to show the dialog * @param url the long pressed url */ - public void showLongPressedDialogForUrl(final Context context, final String url) { + public void showLongPressedDialogForBookmarkUrl(final Context context, final String url) { final HistoryItem item; if (url.startsWith(Constants.FILE) && url.endsWith(Constants.BOOKMARKS_FILENAME)) { // TODO hacky, make a better bookmark mechanism in the future @@ -65,19 +78,19 @@ public class BookmarksDialogBuilder { if (item.isFolder()) { showBookmarkFolderLongPressedDialog(context, item); } else { - showLongPressedDialogForUrl(context, item); + showLongPressedDialogForBookmarkUrl(context, item); } } } - public void showLongPressedDialogForUrl(final Context context, final HistoryItem item) { + public void showLongPressedDialogForBookmarkUrl(final Context context, final HistoryItem item) { final DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { switch (which) { case DialogInterface.BUTTON_POSITIVE: - eventBus.post(new BookmarkEvents.AsNewTab(item)); + eventBus.post(new BrowserEvents.OpenUrlInNewTab(item.getUrl())); break; case DialogInterface.BUTTON_NEGATIVE: if (bookmarkManager.deleteBookmark(item)) { @@ -197,4 +210,103 @@ public class BookmarksDialogBuilder { }); editFolderDialog.show(); } + + public void showLongPressedHistoryLinkDialog(final Context context, final String url) { + DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + switch (which) { + case DialogInterface.BUTTON_POSITIVE: + eventBus.post(new BrowserEvents.OpenUrlInNewTab(url)); + break; + case DialogInterface.BUTTON_NEGATIVE: + mHistoryDatabase.deleteHistoryItem(url); + // openHistory(); + eventBus.post(new BrowserEvents.OpenUrlInCurrentTab(HistoryPage.getHistoryPage(context))); + break; + case DialogInterface.BUTTON_NEUTRAL: + eventBus.post(new BrowserEvents.OpenUrlInCurrentTab(url)); + break; + default: + break; + } + } + }; + + AlertDialog.Builder builder = new AlertDialog.Builder(context); + builder.setTitle(R.string.action_history) + .setMessage(R.string.dialog_history_long_press) + .setCancelable(true) + .setPositiveButton(R.string.action_new_tab, dialogClickListener) + .setNegativeButton(R.string.action_delete, dialogClickListener) + .setNeutralButton(R.string.action_open, dialogClickListener) + .show(); + } + + // TODO There should be a way in which we do not need an activity reference to dowload a file + public void showLongPressImageDialog(@NonNull final Activity activity, @NonNull final String url, + @NonNull final String userAgent) { + DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + switch (which) { + case DialogInterface.BUTTON_POSITIVE: + eventBus.post(new BrowserEvents.OpenUrlInNewTab(url)); + break; + case DialogInterface.BUTTON_NEGATIVE: + eventBus.post(new BrowserEvents.OpenUrlInCurrentTab(url)); + break; + case DialogInterface.BUTTON_NEUTRAL: + if (Build.VERSION.SDK_INT > 8) { + // Should be better to send an event on the bus here + Utils.downloadFile(activity, url, + userAgent, "attachment"); + } + break; + } + } + }; + + AlertDialog.Builder builder = new AlertDialog.Builder(activity); + builder.setTitle(url.replace(Constants.HTTP, "")) + .setCancelable(true) + .setMessage(R.string.dialog_image) + .setPositiveButton(R.string.action_new_tab, dialogClickListener) + .setNegativeButton(R.string.action_open, dialogClickListener) + .setNeutralButton(R.string.action_download, dialogClickListener) + .show(); + } + + public void showLongPressLinkDialog(final Context context, final String url) { + DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + switch (which) { + case DialogInterface.BUTTON_POSITIVE: + eventBus.post(new BrowserEvents.OpenUrlInNewTab(url)); + break; + + case DialogInterface.BUTTON_NEGATIVE: + eventBus.post(new BrowserEvents.OpenUrlInCurrentTab(url)); + break; + + case DialogInterface.BUTTON_NEUTRAL: + ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); + ClipData clip = ClipData.newPlainText("label", url); + clipboard.setPrimaryClip(clip); + break; + } + } + }; + + AlertDialog.Builder builder = new AlertDialog.Builder(context); // dialog + builder.setTitle(url) + .setCancelable(true) + .setMessage(R.string.dialog_link) + .setPositiveButton(R.string.action_new_tab, dialogClickListener) + .setNegativeButton(R.string.action_open, dialogClickListener) + .setNeutralButton(R.string.action_copy, dialogClickListener) + .show(); + } + } diff --git a/app/src/main/java/acr/browser/lightning/fragment/BookmarksFragment.java b/app/src/main/java/acr/browser/lightning/fragment/BookmarksFragment.java index 2c01ac5..18dc308 100644 --- a/app/src/main/java/acr/browser/lightning/fragment/BookmarksFragment.java +++ b/app/src/main/java/acr/browser/lightning/fragment/BookmarksFragment.java @@ -42,7 +42,7 @@ import acr.browser.lightning.bus.BookmarkEvents; import acr.browser.lightning.bus.BrowserEvents; import acr.browser.lightning.database.BookmarkManager; import acr.browser.lightning.database.HistoryItem; -import acr.browser.lightning.dialog.BookmarksDialogBuilder; +import acr.browser.lightning.dialog.LightningDialogBuilder; import acr.browser.lightning.preference.PreferenceManager; import acr.browser.lightning.utils.DownloadImageTask; import acr.browser.lightning.utils.ThemeUtils; @@ -62,7 +62,7 @@ public class BookmarksFragment extends Fragment implements View.OnClickListener, // Dialog builder @Inject - BookmarksDialogBuilder bookmarksDialogBuilder; + LightningDialogBuilder bookmarksDialogBuilder; @Inject PreferenceManager preferenceManager; @@ -109,7 +109,7 @@ public class BookmarksFragment extends Fragment implements View.OnClickListener, setBookmarkDataSet(mBookmarkManager.getBookmarksFromFolder(item.getTitle(), true), true); } else { - eventBus.post(new BookmarkEvents.Clicked(item)); + eventBus.post(new BrowserEvents.OpenUrlInCurrentTab(item.getUrl())); } } }; @@ -293,7 +293,7 @@ public class BookmarksFragment extends Fragment implements View.OnClickListener, if (item.isFolder()) { bookmarksDialogBuilder.showBookmarkFolderLongPressedDialog(getContext(), item); } else { - bookmarksDialogBuilder.showLongPressedDialogForUrl(getContext(), item); + bookmarksDialogBuilder.showLongPressLinkDialog(getContext(), item.getUrl()); } } diff --git a/app/src/main/java/acr/browser/lightning/object/SearchAdapter.java b/app/src/main/java/acr/browser/lightning/object/SearchAdapter.java index f61aabc..87185d6 100644 --- a/app/src/main/java/acr/browser/lightning/object/SearchAdapter.java +++ b/app/src/main/java/acr/browser/lightning/object/SearchAdapter.java @@ -54,14 +54,11 @@ public class SearchAdapter extends BaseAdapter implements Filterable { private final List mFilteredList = new ArrayList<>(); private final List mAllBookmarks = new ArrayList<>(); private final Object mLock = new Object(); - private HistoryDatabase mDatabaseHandler; private final Context mContext; private boolean mUseGoogle = true; private boolean mIsExecuting = false; private final boolean mDarkTheme; private final boolean mIncognito; - @Inject BookmarkManager mBookmarkManager; - @Inject PreferenceManager mPreferenceManager; private static final String CACHE_FILE_TYPE = ".sgg"; private static final String ENCODING = "ISO-8859-1"; private static final long INTERVAL_DAY = 86400000; @@ -73,9 +70,17 @@ public class SearchAdapter extends BaseAdapter implements Filterable { private final Drawable mHistoryDrawable; private final Drawable mBookmarkDrawable; + @Inject + HistoryDatabase mDatabaseHandler; + + @Inject + BookmarkManager mBookmarkManager; + + @Inject + PreferenceManager mPreferenceManager; + public SearchAdapter(Context context, boolean dark, boolean incognito) { BrowserApp.getAppComponent().inject(this); - mDatabaseHandler = HistoryDatabase.getInstance(); mAllBookmarks.addAll(mBookmarkManager.getAllBookmarks(true)); mUseGoogle = mPreferenceManager.getGoogleSearchSuggestionsEnabled(); mContext = context; @@ -125,7 +130,6 @@ public class SearchAdapter extends BaseAdapter implements Filterable { mSuggestions.clear(); } } - mDatabaseHandler = HistoryDatabase.getInstance(); } public void refreshBookmarks() { @@ -240,13 +244,10 @@ public class SearchAdapter extends BaseAdapter implements Filterable { mBookmarks.add(mAllBookmarks.get(n)); counter++; } - } } } - if (mDatabaseHandler == null || mDatabaseHandler.isClosed()) { - mDatabaseHandler = HistoryDatabase.getInstance(); - } + List historyList = mDatabaseHandler.findItemsContaining(constraint.toString()); synchronized (mHistory) { mHistory.clear(); diff --git a/app/src/main/java/acr/browser/lightning/utils/WebUtils.java b/app/src/main/java/acr/browser/lightning/utils/WebUtils.java index 96ce095..e0434fe 100644 --- a/app/src/main/java/acr/browser/lightning/utils/WebUtils.java +++ b/app/src/main/java/acr/browser/lightning/utils/WebUtils.java @@ -10,6 +10,7 @@ import android.webkit.WebStorage; import android.webkit.WebView; import android.webkit.WebViewDatabase; +import acr.browser.lightning.app.BrowserApp; import acr.browser.lightning.database.HistoryDatabase; /** @@ -32,7 +33,7 @@ public class WebUtils { } public static void clearHistory(@NonNull Context context) { - HistoryDatabase.getInstance().deleteHistory(); + BrowserApp.getAppComponent().getHistoryDatabase().deleteHistory(); WebViewDatabase m = WebViewDatabase.getInstance(context); m.clearFormData(); m.clearHttpAuthUsernamePassword(); diff --git a/app/src/main/java/acr/browser/lightning/view/LightningChromeClient.java b/app/src/main/java/acr/browser/lightning/view/LightningChromeClient.java new file mode 100644 index 0000000..747dac2 --- /dev/null +++ b/app/src/main/java/acr/browser/lightning/view/LightningChromeClient.java @@ -0,0 +1,234 @@ +package acr.browser.lightning.view; + +import android.Manifest; +import android.app.Activity; +import android.content.DialogInterface; +import android.graphics.Bitmap; +import android.net.Uri; +import android.os.Message; +import android.support.v7.app.AlertDialog; +import android.util.Log; +import android.view.View; +import android.webkit.GeolocationPermissions; +import android.webkit.ValueCallback; +import android.webkit.WebChromeClient; +import android.webkit.WebView; + +import com.squareup.otto.Bus; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import acr.browser.lightning.R; +import acr.browser.lightning.activity.BrowserActivity; +import acr.browser.lightning.app.BrowserApp; +import acr.browser.lightning.bus.BrowserEvents; +import acr.browser.lightning.constant.Constants; +import acr.browser.lightning.utils.PermissionsManager; +import acr.browser.lightning.utils.Utils; + +/** + * @author Stefano Pacifici based on Anthony C. Restaino code + * @date 2015/09/21 + */ +class LightningChromeClient extends WebChromeClient { + + private static final String[] PERMISSIONS = new String[]{Manifest.permission.ACCESS_FINE_LOCATION}; + + private final BrowserActivity mActivity; + private final LightningView mLightningView; + private final Bus eventBus; + + LightningChromeClient(BrowserActivity activity, LightningView lightningView) { + mActivity = activity; + mLightningView = lightningView; + eventBus = BrowserApp.getAppComponent().getBus(); + } + + @Override + public void onProgressChanged(WebView view, int newProgress) { + if (mLightningView.isShown()) { + mActivity.updateProgress(newProgress); + } + } + + @Override + public void onReceivedIcon(WebView view, Bitmap icon) { + if (icon == null) + return; + mLightningView.mTitle.setFavicon(icon); + eventBus.post(new BrowserEvents.TabsChanged()); ; + cacheFavicon(view.getUrl(), icon); + } + + /** + * Naive caching of the favicon according to the domain name of the URL + * @param icon the icon to cache + */ + private void cacheFavicon(final String url, final Bitmap icon) { + if (icon == null) return; + final Uri uri = Uri.parse(url); + if (uri.getHost() == null) { + return; + } + new Thread(new Runnable() { + @Override + public void run() { + String hash = String.valueOf(uri.getHost().hashCode()); + Log.d(Constants.TAG, "Caching icon for " + uri.getHost()); + FileOutputStream fos = null; + try { + File image = new File(BrowserApp.getAppContext().getCacheDir(), hash + ".png"); + fos = new FileOutputStream(image); + icon.compress(Bitmap.CompressFormat.PNG, 100, fos); + fos.flush(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + Utils.close(fos); + } + } + }).start(); + } + + + @Override + public void onReceivedTitle(WebView view, String title) { + if (title != null && !title.isEmpty()) { + mLightningView.mTitle.setTitle(title); + } else { + mLightningView.mTitle.setTitle(mActivity.getString(R.string.untitled)); + } + eventBus.post(new BrowserEvents.TabsChanged()); + if (view != null) { + mActivity.updateHistory(title, view.getUrl()); + } + } + + @Override + public void onGeolocationPermissionsShowPrompt(final String origin, + final GeolocationPermissions.Callback callback) { + PermissionsManager.getInstance().requestPermissionsIfNecessary(mActivity, PERMISSIONS); + final boolean remember = true; + AlertDialog.Builder builder = new AlertDialog.Builder(mActivity); + builder.setTitle(mActivity.getString(R.string.location)); + String org; + if (origin.length() > 50) { + org = origin.subSequence(0, 50) + "..."; + } else { + org = origin; + } + builder.setMessage(org + mActivity.getString(R.string.message_location)) + .setCancelable(true) + .setPositiveButton(mActivity.getString(R.string.action_allow), + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int id) { + callback.invoke(origin, true, remember); + } + }) + .setNegativeButton(mActivity.getString(R.string.action_dont_allow), + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int id) { + callback.invoke(origin, false, remember); + } + }); + AlertDialog alert = builder.create(); + alert.show(); + + } + + @Override + public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture, + Message resultMsg) { + mActivity.onCreateWindow(resultMsg); + return true; + } + + @Override + public void onCloseWindow(WebView window) { + mActivity.onCloseWindow(mLightningView); + } + + public void openFileChooser(ValueCallback uploadMsg) { + mActivity.openFileChooser(uploadMsg); + } + + public void openFileChooser(ValueCallback uploadMsg, String acceptType) { + mActivity.openFileChooser(uploadMsg); + } + + public void openFileChooser(ValueCallback uploadMsg, String acceptType, String capture) { + mActivity.openFileChooser(uploadMsg); + } + + public boolean onShowFileChooser(WebView webView, ValueCallback filePathCallback, + WebChromeClient.FileChooserParams fileChooserParams) { + mActivity.showFileChooser(filePathCallback); + return true; + } + + @Override + public Bitmap getDefaultVideoPoster() { + // TODO Simplify the method can be moved here + return mActivity.getDefaultVideoPoster(); + } + + @Override + public View getVideoLoadingProgressView() { + // TODO Simplify the method can be moved here + return mActivity.getVideoLoadingProgressView(); + } + + @Override + public void onHideCustomView() { + mActivity.onHideCustomView(); + super.onHideCustomView(); + } + + @Override + public void onShowCustomView(View view, CustomViewCallback callback) { + // While these lines might look like they work, in practice, + // Full-screen videos won't work correctly. I may test this out some + // more + // if (view instanceof FrameLayout) { + // FrameLayout frame = (FrameLayout) view; + // if (frame.getFocusedChild() instanceof VideoView) { + // VideoView video = (VideoView) frame.getFocusedChild(); + // video.stopPlayback(); + // frame.removeView(video); + // video.setVisibility(View.GONE); + // } + // } else { + mActivity.onShowCustomView(view, callback); + + // } + + super.onShowCustomView(view, callback); + } + + @Override + @Deprecated + public void onShowCustomView(View view, int requestedOrientation, + CustomViewCallback callback) { + // While these lines might look like they work, in practice, + // Full-screen videos won't work correctly. I may test this out some + // more + // if (view instanceof FrameLayout) { + // FrameLayout frame = (FrameLayout) view; + // if (frame.getFocusedChild() instanceof VideoView) { + // VideoView video = (VideoView) frame.getFocusedChild(); + // video.stopPlayback(); + // frame.removeView(video); + // video.setVisibility(View.GONE); + // } + // } else { + mActivity.onShowCustomView(view, callback); + + // } + + super.onShowCustomView(view, requestedOrientation, callback); + } +} diff --git a/app/src/main/java/acr/browser/lightning/view/LightningView.java b/app/src/main/java/acr/browser/lightning/view/LightningView.java index 5b43ffe..1920b8a 100644 --- a/app/src/main/java/acr/browser/lightning/view/LightningView.java +++ b/app/src/main/java/acr/browser/lightning/view/LightningView.java @@ -6,27 +6,18 @@ package acr.browser.lightning.view; import android.Manifest; import android.annotation.SuppressLint; -import android.app.Activity; -import android.content.ActivityNotFoundException; import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; import android.graphics.Bitmap; import android.graphics.Color; import android.graphics.ColorMatrix; import android.graphics.ColorMatrixColorFilter; import android.graphics.Paint; -import android.net.MailTo; import android.net.Uri; -import android.net.http.SslError; import android.os.Build; import android.os.Handler; import android.os.Message; import android.support.annotation.NonNull; import android.support.annotation.Nullable; -import android.support.v7.app.AlertDialog; -import android.text.InputType; -import android.text.method.PasswordTransformationMethod; import android.util.Log; import android.view.GestureDetector; import android.view.GestureDetector.SimpleOnGestureListener; @@ -35,45 +26,30 @@ import android.view.View; import android.view.View.OnTouchListener; import android.view.ViewConfiguration; import android.webkit.CookieManager; -import android.webkit.GeolocationPermissions; -import android.webkit.HttpAuthHandler; -import android.webkit.SslErrorHandler; -import android.webkit.ValueCallback; -import android.webkit.WebChromeClient; -import android.webkit.WebResourceRequest; -import android.webkit.WebResourceResponse; import android.webkit.WebSettings; import android.webkit.WebSettings.LayoutAlgorithm; import android.webkit.WebSettings.PluginState; import android.webkit.WebView; -import android.webkit.WebViewClient; -import android.widget.EditText; -import android.widget.LinearLayout; import com.squareup.otto.Bus; -import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; -import java.net.URISyntaxException; import javax.inject.Inject; import acr.browser.lightning.R; +import acr.browser.lightning.activity.BrowserActivity; import acr.browser.lightning.app.BrowserApp; import acr.browser.lightning.bus.BrowserEvents; -import acr.browser.lightning.bus.TabEvents; import acr.browser.lightning.constant.Constants; import acr.browser.lightning.constant.HistoryPage; import acr.browser.lightning.constant.StartPage; -import acr.browser.lightning.controller.BrowserController; -import acr.browser.lightning.dialog.BookmarksDialogBuilder; +import acr.browser.lightning.dialog.LightningDialogBuilder; import acr.browser.lightning.download.LightningDownloadListener; import acr.browser.lightning.preference.PreferenceManager; -import acr.browser.lightning.utils.AdBlock; -import acr.browser.lightning.utils.IntentUtils; import acr.browser.lightning.utils.PermissionsManager; import acr.browser.lightning.utils.ProxyUtils; import acr.browser.lightning.utils.ThemeUtils; @@ -81,21 +57,15 @@ import acr.browser.lightning.utils.Utils; public class LightningView { - private final Title mTitle; + final LightningViewTitle mTitle; private WebView mWebView; - private final boolean mIsIncognitoTab; - private final BrowserController mBrowserController = null; // TODO REMOVE + final boolean mIsIncognitoTab; private final GestureDetector mGestureDetector; - private final Activity mActivity; + private final BrowserActivity mActivity; private static String mHomepage; private static String mDefaultUserAgent; - // TODO fix so that mWebpageBitmap can be static - static changes the icon when switching from light to dark and then back to light - private final Bitmap mWebpageBitmap; - private final AdBlock mAdBlock; - private final IntentUtils mIntentUtils; private final Paint mPaint = new Paint(); private boolean isForegroundTab; - private boolean mTextReflow = false; private boolean mInvertPage = false; private boolean mToggleDesktop = false; private static float mMaxFling; @@ -118,23 +88,20 @@ public class LightningView { PreferenceManager mPreferences; @Inject - BookmarksDialogBuilder bookmarksDialogBuilder; + LightningDialogBuilder bookmarksDialogBuilder; @SuppressLint("NewApi") - public LightningView(Activity activity, String url, boolean darkTheme, boolean isIncognito) { + public LightningView(BrowserActivity activity, String url, boolean darkTheme, boolean isIncognito) { BrowserApp.getAppComponent().inject(this); mActivity = activity; mWebView = new WebView(activity); mIsIncognitoTab = isIncognito; - mTitle = new Title(activity, darkTheme); - mAdBlock = AdBlock.getInstance(activity.getApplicationContext()); + mTitle = new LightningViewTitle(activity, darkTheme); + // mAdBlock = AdBlock.getInstance(activity.getApplicationContext()); mPermissionsManager = PermissionsManager.getInstance(); - mWebpageBitmap = mTitle.mDefaultIcon; - mMaxFling = ViewConfiguration.get(activity).getScaledMaximumFlingVelocity(); - mIntentUtils = new IntentUtils(activity); mWebView.setDrawingCacheBackgroundColor(Color.WHITE); mWebView.setFocusableInTouchMode(true); mWebView.setFocusable(true); @@ -149,8 +116,8 @@ public class LightningView { mWebView.setScrollbarFadingEnabled(true); mWebView.setSaveEnabled(true); mWebView.setNetworkAvailable(true); - mWebView.setWebChromeClient(new LightningChromeClient(activity)); - mWebView.setWebViewClient(new LightningWebClient(activity)); + mWebView.setWebChromeClient(new LightningChromeClient(activity, this)); + mWebView.setWebViewClient(new LightningWebClient(activity, this)); mWebView.setDownloadListener(new LightningDownloadListener(activity)); mGestureDetector = new GestureDetector(activity, new CustomGestureListener()); mWebView.setOnTouchListener(new TouchListener()); @@ -224,7 +191,7 @@ public class LightningView { settings.setDefaultTextEncodingName(mPreferences.getTextEncoding()); mHomepage = mPreferences.getHomepage(); - mAdBlock.updatePreference(); + // mAdBlock.updatePreference(); setColorMode(mPreferences.getRenderingMode()); @@ -275,7 +242,6 @@ public class LightningView { } if (mPreferences.getTextReflowEnabled()) { - mTextReflow = true; settings.setLayoutAlgorithm(LayoutAlgorithm.NARROW_COLUMNS); if (API >= android.os.Build.VERSION_CODES.KITKAT) { try { @@ -287,7 +253,6 @@ public class LightningView { } } } else { - mTextReflow = false; settings.setLayoutAlgorithm(LayoutAlgorithm.NORMAL); } @@ -549,36 +514,6 @@ public class LightningView { } } - /** - * Naive caching of the favicon according to the domain name of the URL - * @param icon the icon to cache - */ - private void cacheFavicon(final Bitmap icon) { - if (icon == null) return; - final Uri uri = Uri.parse(getUrl()); - if (uri.getHost() == null) { - return; - } - new Thread(new Runnable() { - @Override - public void run() { - String hash = String.valueOf(uri.getHost().hashCode()); - Log.d(Constants.TAG, "Caching icon for " + uri.getHost()); - FileOutputStream fos = null; - try { - File image = new File(BrowserApp.getAppContext().getCacheDir(), hash + ".png"); - fos = new FileOutputStream(image); - icon.compress(Bitmap.CompressFormat.PNG, 100, fos); - fos.flush(); - } catch (IOException e) { - e.printStackTrace(); - } finally { - Utils.close(fos); - } - } - }).start(); - } - @SuppressLint("NewApi") public synchronized void find(String text) { if (mWebView != null) { @@ -623,6 +558,14 @@ public class LightningView { } } + /** + * Used by {@link LightningWebClient} + * + * @return true if the page is in inverted mode, false otherwise + */ + public boolean getInvertePage() { + return mInvertPage; + } /** * handles a long click on the page, parameter String url * is the url that should have been obtained from the WebView touch node @@ -634,36 +577,36 @@ public class LightningView { if (currentUrl != null && currentUrl.startsWith(Constants.FILE)) { if (currentUrl.endsWith(HistoryPage.FILENAME)) { if (url != null) { - // TODO longPressHistoryLink(url); + bookmarksDialogBuilder.showLongPressedHistoryLinkDialog(mActivity, url); } else if (result != null && result.getExtra() != null) { final String newUrl = result.getExtra(); - // TODO longPressHistoryLink(newUrl); + bookmarksDialogBuilder.showLongPressedHistoryLinkDialog(mActivity, newUrl); } } else if (currentUrl.endsWith(Constants.BOOKMARKS_FILENAME)) { if (url != null) { - bookmarksDialogBuilder.showLongPressedDialogForUrl(mActivity, url); + bookmarksDialogBuilder.showLongPressLinkDialog(mActivity, url); } else if (result != null && result.getExtra() != null) { final String newUrl = result.getExtra(); - bookmarksDialogBuilder.showLongPressedDialogForUrl(mActivity, newUrl); + bookmarksDialogBuilder.showLongPressLinkDialog(mActivity, newUrl); } } } else { if (url != null) { if (result != null) { if (result.getType() == WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE || result.getType() == WebView.HitTestResult.IMAGE_TYPE) { - // TODO longPressImage(url); + bookmarksDialogBuilder.showLongPressImageDialog(mActivity, url, getUserAgent()); } else { - // TODO longPressLink(url); + bookmarksDialogBuilder.showLongPressLinkDialog(mActivity, url); } } else { - // TODO longPressLink(url); + bookmarksDialogBuilder.showLongPressLinkDialog(mActivity, url); } } else if (result != null && result.getExtra() != null) { final String newUrl = result.getExtra(); if (result.getType() == WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE || result.getType() == WebView.HitTestResult.IMAGE_TYPE) { - // TODO longPressImage(newUrl); + bookmarksDialogBuilder.showLongPressImageDialog(mActivity, newUrl, getUserAgent()); } else { - // TODO longPressLink(newUrl); + bookmarksDialogBuilder.showLongPressLinkDialog(mActivity, newUrl); } } } @@ -716,438 +659,6 @@ public class LightningView { } } - public class LightningWebClient extends WebViewClient { - - final Activity mActivity; - - LightningWebClient(Activity activity) { - mActivity = activity; - } - - @Override - public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - if (mAdBlock.isAd(request.getUrl().toString())) { - ByteArrayInputStream EMPTY = new ByteArrayInputStream("".getBytes()); - return new WebResourceResponse("text/plain", "utf-8", EMPTY); - } - } - return super.shouldInterceptRequest(view, request); - } - - @Override - public WebResourceResponse shouldInterceptRequest(WebView view, String url) { - if (mAdBlock.isAd(url)) { - ByteArrayInputStream EMPTY = new ByteArrayInputStream("".getBytes()); - return new WebResourceResponse("text/plain", "utf-8", EMPTY); - } - return null; - } - - @SuppressLint("NewApi") - @Override - public void onPageFinished(WebView view, String url) { - if (view.isShown()) { - mBrowserController.updateUrl(url, true); - view.postInvalidate(); - } - if (view.getTitle() == null || view.getTitle().isEmpty()) { - mTitle.setTitle(mActivity.getString(R.string.untitled)); - } else { - mTitle.setTitle(view.getTitle()); - } - if (API >= android.os.Build.VERSION_CODES.KITKAT && mInvertPage) { - view.evaluateJavascript(Constants.JAVASCRIPT_INVERT_PAGE, null); - } - eventBus.post(new BrowserEvents.TabsChanged()); - } - - @Override - public void onPageStarted(WebView view, String url, Bitmap favicon) { - if (isShown()) { - mBrowserController.updateUrl(url, false); - mBrowserController.showActionBar(); - } - mTitle.setFavicon(mWebpageBitmap); - eventBus.post(new BrowserEvents.TabsChanged()); - } - - @Override - public void onReceivedHttpAuthRequest(final WebView view, @NonNull final HttpAuthHandler handler, - final String host, final String realm) { - - AlertDialog.Builder builder = new AlertDialog.Builder(mActivity); - final EditText name = new EditText(mActivity); - final EditText password = new EditText(mActivity); - LinearLayout passLayout = new LinearLayout(mActivity); - passLayout.setOrientation(LinearLayout.VERTICAL); - - passLayout.addView(name); - passLayout.addView(password); - - name.setHint(mActivity.getString(R.string.hint_username)); - name.setSingleLine(); - password.setInputType(InputType.TYPE_TEXT_VARIATION_PASSWORD); - password.setSingleLine(); - password.setTransformationMethod(new PasswordTransformationMethod()); - password.setHint(mActivity.getString(R.string.hint_password)); - builder.setTitle(mActivity.getString(R.string.title_sign_in)); - builder.setView(passLayout); - builder.setCancelable(true) - .setPositiveButton(mActivity.getString(R.string.title_sign_in), - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - String user = name.getText().toString(); - String pass = password.getText().toString(); - handler.proceed(user.trim(), pass.trim()); - Log.d(Constants.TAG, "Request Login"); - - } - }) - .setNegativeButton(mActivity.getString(R.string.action_cancel), - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - handler.cancel(); - - } - }); - AlertDialog alert = builder.create(); - alert.show(); - - } - - private boolean mIsRunning = false; - private float mZoomScale = 0.0f; - - @SuppressLint("NewApi") - @Override - public void onScaleChanged(final WebView view, final float oldScale, final float newScale) { - if (view.isShown() && mTextReflow && API >= android.os.Build.VERSION_CODES.KITKAT) { - if (mIsRunning) - return; - if (Math.abs(mZoomScale - newScale) > 0.01f) { - mIsRunning = view.postDelayed(new Runnable() { - - @Override - public void run() { - mZoomScale = newScale; - view.evaluateJavascript(Constants.JAVASCRIPT_TEXT_REFLOW, null); - mIsRunning = false; - } - - }, 100); - } - - } - } - - @Override - public void onReceivedSslError(WebView view, @NonNull final SslErrorHandler handler, SslError error) { - AlertDialog.Builder builder = new AlertDialog.Builder(mActivity); - builder.setTitle(mActivity.getString(R.string.title_warning)); - builder.setMessage(mActivity.getString(R.string.message_untrusted_certificate)) - .setCancelable(true) - .setPositiveButton(mActivity.getString(R.string.action_yes), - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - handler.proceed(); - } - }) - .setNegativeButton(mActivity.getString(R.string.action_no), - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - handler.cancel(); - } - }); - AlertDialog alert = builder.create(); - if (error.getPrimaryError() == SslError.SSL_UNTRUSTED) { - alert.show(); - } else { - handler.proceed(); - } - - } - - @Override - public void onFormResubmission(WebView view, @NonNull final Message dontResend, final Message resend) { - AlertDialog.Builder builder = new AlertDialog.Builder(mActivity); - builder.setTitle(mActivity.getString(R.string.title_form_resubmission)); - builder.setMessage(mActivity.getString(R.string.message_form_resubmission)) - .setCancelable(true) - .setPositiveButton(mActivity.getString(R.string.action_yes), - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - - resend.sendToTarget(); - } - }) - .setNegativeButton(mActivity.getString(R.string.action_no), - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - - dontResend.sendToTarget(); - } - }); - AlertDialog alert = builder.create(); - alert.show(); - } - - @Override - public boolean shouldOverrideUrlLoading(WebView view, String url) { - // Check if configured proxy is available - if (!ProxyUtils.getInstance().isProxyReady()) { - // User has been notified - return true; - } - - if (mIsIncognitoTab) { - return super.shouldOverrideUrlLoading(view, url); - } - if (url.startsWith("about:")) { - return super.shouldOverrideUrlLoading(view, url); - } - if (url.contains("mailto:")) { - MailTo mailTo = MailTo.parse(url); - Intent i = Utils.newEmailIntent(mailTo.getTo(), mailTo.getSubject(), - mailTo.getBody(), mailTo.getCc()); - mActivity.startActivity(i); - view.reload(); - return true; - } else if (url.startsWith("intent://")) { - Intent intent; - try { - intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME); - } catch (URISyntaxException ex) { - return false; - } - if (intent != null) { - try { - mActivity.startActivity(intent); - } catch (ActivityNotFoundException e) { - Log.e(Constants.TAG, "ActivityNotFoundException"); - } - return true; - } - } - return mIntentUtils.startActivityForUrl(mWebView, url); - } - } - - public class LightningChromeClient extends WebChromeClient { - - final Activity mActivity; - - LightningChromeClient(Activity activity) { - mActivity = activity; - } - - @Override - public void onProgressChanged(WebView view, int newProgress) { - if (isShown()) { - mBrowserController.updateProgress(newProgress); - } - } - - @Override - public void onReceivedIcon(WebView view, Bitmap icon) { - if (icon == null) - return; - mTitle.setFavicon(icon); - eventBus.post(new BrowserEvents.TabsChanged()); ; - cacheFavicon(icon); - } - - @Override - public void onReceivedTitle(WebView view, String title) { - if (title != null && !title.isEmpty()) { - mTitle.setTitle(title); - } else { - mTitle.setTitle(mActivity.getString(R.string.untitled)); - } - eventBus.post(new BrowserEvents.TabsChanged()); ; - if (view != null) - mBrowserController.updateHistory(title, view.getUrl()); - } - - @Override - public void onGeolocationPermissionsShowPrompt(final String origin, - final GeolocationPermissions.Callback callback) { - mPermissionsManager.requestPermissionsIfNecessary(mActivity, PERMISSIONS); - final boolean remember = true; - AlertDialog.Builder builder = new AlertDialog.Builder(mActivity); - builder.setTitle(mActivity.getString(R.string.location)); - String org; - if (origin.length() > 50) { - org = origin.subSequence(0, 50) + "..."; - } else { - org = origin; - } - builder.setMessage(org + mActivity.getString(R.string.message_location)) - .setCancelable(true) - .setPositiveButton(mActivity.getString(R.string.action_allow), - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - callback.invoke(origin, true, remember); - } - }) - .setNegativeButton(mActivity.getString(R.string.action_dont_allow), - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - callback.invoke(origin, false, remember); - } - }); - AlertDialog alert = builder.create(); - alert.show(); - - } - - @Override - public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture, - Message resultMsg) { - mBrowserController.onCreateWindow(resultMsg); - return true; - } - - @Override - public void onCloseWindow(WebView window) { - mBrowserController.onCloseWindow(LightningView.this); - } - - public void openFileChooser(ValueCallback uploadMsg) { - mBrowserController.openFileChooser(uploadMsg); - } - - public void openFileChooser(ValueCallback uploadMsg, String acceptType) { - mBrowserController.openFileChooser(uploadMsg); - } - - public void openFileChooser(ValueCallback uploadMsg, String acceptType, String capture) { - mBrowserController.openFileChooser(uploadMsg); - } - - public boolean onShowFileChooser(WebView webView, ValueCallback filePathCallback, - WebChromeClient.FileChooserParams fileChooserParams) { - mBrowserController.showFileChooser(filePathCallback); - return true; - } - - @Override - public Bitmap getDefaultVideoPoster() { - return mBrowserController.getDefaultVideoPoster(); - } - - @Override - public View getVideoLoadingProgressView() { - return mBrowserController.getVideoLoadingProgressView(); - } - - @Override - public void onHideCustomView() { - mBrowserController.onHideCustomView(); - super.onHideCustomView(); - } - - @Override - public void onShowCustomView(View view, CustomViewCallback callback) { - // While these lines might look like they work, in practice, - // Full-screen videos won't work correctly. I may test this out some - // more - // if (view instanceof FrameLayout) { - // FrameLayout frame = (FrameLayout) view; - // if (frame.getFocusedChild() instanceof VideoView) { - // VideoView video = (VideoView) frame.getFocusedChild(); - // video.stopPlayback(); - // frame.removeView(video); - // video.setVisibility(View.GONE); - // } - // } else { - mBrowserController.onShowCustomView(view, callback); - - // } - - super.onShowCustomView(view, callback); - } - - @Override - @Deprecated - public void onShowCustomView(View view, int requestedOrientation, - CustomViewCallback callback) { - // While these lines might look like they work, in practice, - // Full-screen videos won't work correctly. I may test this out some - // more - // if (view instanceof FrameLayout) { - // FrameLayout frame = (FrameLayout) view; - // if (frame.getFocusedChild() instanceof VideoView) { - // VideoView video = (VideoView) frame.getFocusedChild(); - // video.stopPlayback(); - // frame.removeView(video); - // video.setVisibility(View.GONE); - // } - // } else { - mBrowserController.onShowCustomView(view, callback); - - // } - - super.onShowCustomView(view, requestedOrientation, callback); - } - } - - public class Title { - - private Bitmap mFavicon; - private String mTitle; - private final Bitmap mDefaultIcon; - - public Title(Context context, boolean darkTheme) { - mDefaultIcon = ThemeUtils.getThemedBitmap(context, R.drawable.ic_webpage, darkTheme); - mFavicon = mDefaultIcon; - mTitle = mActivity.getString(R.string.action_new_tab); - } - - public void setFavicon(Bitmap favicon) { - if (favicon == null) { - mFavicon = mDefaultIcon; - } else { - mFavicon = Utils.padFavicon(favicon); - } - } - - public void setTitle(String title) { - if (title == null) { - mTitle = ""; - } else { - mTitle = title; - } - } - - public void setTitleAndFavicon(String title, Bitmap favicon) { - mTitle = title; - - if (favicon == null) { - mFavicon = mDefaultIcon; - } else { - mFavicon = Utils.padFavicon(favicon); - } - } - - public String getTitle() { - return mTitle; - } - - public Bitmap getFavicon() { - return mFavicon; - } - - } - private class TouchListener implements OnTouchListener { float mLocation; @@ -1170,9 +681,9 @@ public class LightningView { } else if (mAction == MotionEvent.ACTION_UP) { final float distance = (mY - mLocation); if (distance > SCROLL_UP_THRESHOLD && view.getScrollY() < SCROLL_UP_THRESHOLD) { - mBrowserController.showActionBar(); + mActivity.showActionBar(); } else if (distance < -SCROLL_UP_THRESHOLD) { - mBrowserController.hideActionBar(); + mActivity.hideActionBar(); } mLocation = 0; } @@ -1187,9 +698,9 @@ public class LightningView { public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { int power = (int) (velocityY * 100 / mMaxFling); if (power < -10) { - mBrowserController.hideActionBar(); + mActivity.hideActionBar(); } else if (power > 15) { - mBrowserController.showActionBar(); + mActivity.showActionBar(); } return super.onFling(e1, e2, velocityX, velocityY); } diff --git a/app/src/main/java/acr/browser/lightning/view/LightningViewTitle.java b/app/src/main/java/acr/browser/lightning/view/LightningViewTitle.java new file mode 100644 index 0000000..2452d85 --- /dev/null +++ b/app/src/main/java/acr/browser/lightning/view/LightningViewTitle.java @@ -0,0 +1,66 @@ +package acr.browser.lightning.view; + +import android.content.Context; +import android.graphics.Bitmap; + +import acr.browser.lightning.R; +import acr.browser.lightning.utils.ThemeUtils; +import acr.browser.lightning.utils.Utils; + +/** + * @author Stefano Pacifici base on Anthony C. Restaino's code + * @date 2015/09/21 + */ +class LightningViewTitle { + + private static Bitmap DEFAULT_ICON = null; + + private Bitmap mFavicon; + private String mTitle; + + public LightningViewTitle(Context context, boolean darkTheme) { + if (DEFAULT_ICON == null) { + DEFAULT_ICON = ThemeUtils.getThemedBitmap(context, R.drawable.ic_webpage, darkTheme); + } + mFavicon = DEFAULT_ICON; + mTitle = context.getString(R.string.action_new_tab); + } + + public void setFavicon(Bitmap favicon) { + if (favicon == null) { + mFavicon = DEFAULT_ICON; + } else { + mFavicon = Utils.padFavicon(favicon); + } + } + + public void setTitle(String title) { + if (title == null) { + mTitle = ""; + } else { + mTitle = title; + } + } + + public void setTitleAndFavicon(String title, Bitmap favicon) { + mTitle = title; + + if (favicon == null) { + mFavicon = DEFAULT_ICON; + } else { + mFavicon = Utils.padFavicon(favicon); + } + } + + public String getTitle() { + return mTitle; + } + + public Bitmap getFavicon() { + return mFavicon; + } + + public Bitmap getDefaultIcon() { + return DEFAULT_ICON; + } +} diff --git a/app/src/main/java/acr/browser/lightning/view/LightningWebClient.java b/app/src/main/java/acr/browser/lightning/view/LightningWebClient.java new file mode 100644 index 0000000..b57556e --- /dev/null +++ b/app/src/main/java/acr/browser/lightning/view/LightningWebClient.java @@ -0,0 +1,276 @@ +package acr.browser.lightning.view; + +import android.annotation.SuppressLint; +import android.content.ActivityNotFoundException; +import android.content.DialogInterface; +import android.content.Intent; +import android.graphics.Bitmap; +import android.net.MailTo; +import android.net.http.SslError; +import android.os.Build; +import android.os.Message; +import android.support.annotation.NonNull; +import android.support.v7.app.AlertDialog; +import android.text.InputType; +import android.text.method.PasswordTransformationMethod; +import android.util.Log; +import android.webkit.HttpAuthHandler; +import android.webkit.SslErrorHandler; +import android.webkit.WebResourceRequest; +import android.webkit.WebResourceResponse; +import android.webkit.WebView; +import android.webkit.WebViewClient; +import android.widget.EditText; +import android.widget.LinearLayout; + +import com.squareup.otto.Bus; + +import java.io.ByteArrayInputStream; +import java.net.URISyntaxException; + +import acr.browser.lightning.R; +import acr.browser.lightning.activity.BrowserActivity; +import acr.browser.lightning.app.BrowserApp; +import acr.browser.lightning.bus.BrowserEvents; +import acr.browser.lightning.constant.Constants; +import acr.browser.lightning.utils.AdBlock; +import acr.browser.lightning.utils.IntentUtils; +import acr.browser.lightning.utils.ProxyUtils; +import acr.browser.lightning.utils.Utils; + +/** + * @author Stefano Pacifici based on Anthony C. Restaino's code + * @date 2015/09/22 + */ +public class LightningWebClient extends WebViewClient { + + private final BrowserActivity mActivity; + private final LightningView mLightningView; + private final AdBlock mAdBlock; + private final Bus mEventBus; + private final IntentUtils mIntentUtils; + + LightningWebClient(BrowserActivity activity, LightningView lightningView) { + mActivity = activity; + mLightningView = lightningView; + mAdBlock = AdBlock.getInstance(activity); + mAdBlock.updatePreference(); + mEventBus = BrowserApp.getAppComponent().getBus(); + mIntentUtils = new IntentUtils(activity); + } + + @Override + public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + if (mAdBlock.isAd(request.getUrl().toString())) { + ByteArrayInputStream EMPTY = new ByteArrayInputStream("".getBytes()); + return new WebResourceResponse("text/plain", "utf-8", EMPTY); + } + } + return super.shouldInterceptRequest(view, request); + } + + @Override + public WebResourceResponse shouldInterceptRequest(WebView view, String url) { + if (mAdBlock.isAd(url)) { + ByteArrayInputStream EMPTY = new ByteArrayInputStream("".getBytes()); + return new WebResourceResponse("text/plain", "utf-8", EMPTY); + } + return null; + } + + @SuppressLint("NewApi") + @Override + public void onPageFinished(WebView view, String url) { + if (view.isShown()) { + mActivity.updateUrl(url, true); + view.postInvalidate(); + } + if (view.getTitle() == null || view.getTitle().isEmpty()) { + mLightningView.mTitle.setTitle(mActivity.getString(R.string.untitled)); + } else { + mLightningView.mTitle.setTitle(view.getTitle()); + } + if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT && + mLightningView.getInvertePage()) { + view.evaluateJavascript(Constants.JAVASCRIPT_INVERT_PAGE, null); + } + mEventBus.post(new BrowserEvents.TabsChanged()); + } + + @Override + public void onPageStarted(WebView view, String url, Bitmap favicon) { + if (mLightningView.isShown()) { + mActivity.updateUrl(url, false); + mActivity.showActionBar(); + } + mEventBus.post(new BrowserEvents.TabsChanged()); + } + + @Override + public void onReceivedHttpAuthRequest(final WebView view, @NonNull final HttpAuthHandler handler, + final String host, final String realm) { + + AlertDialog.Builder builder = new AlertDialog.Builder(mActivity); + final EditText name = new EditText(mActivity); + final EditText password = new EditText(mActivity); + LinearLayout passLayout = new LinearLayout(mActivity); + passLayout.setOrientation(LinearLayout.VERTICAL); + + passLayout.addView(name); + passLayout.addView(password); + + name.setHint(mActivity.getString(R.string.hint_username)); + name.setSingleLine(); + password.setInputType(InputType.TYPE_TEXT_VARIATION_PASSWORD); + password.setSingleLine(); + password.setTransformationMethod(new PasswordTransformationMethod()); + password.setHint(mActivity.getString(R.string.hint_password)); + builder.setTitle(mActivity.getString(R.string.title_sign_in)); + builder.setView(passLayout); + builder.setCancelable(true) + .setPositiveButton(mActivity.getString(R.string.title_sign_in), + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int id) { + String user = name.getText().toString(); + String pass = password.getText().toString(); + handler.proceed(user.trim(), pass.trim()); + Log.d(Constants.TAG, "Request Login"); + + } + }) + .setNegativeButton(mActivity.getString(R.string.action_cancel), + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int id) { + handler.cancel(); + + } + }); + AlertDialog alert = builder.create(); + alert.show(); + + } + + private boolean mIsRunning = false; + private float mZoomScale = 0.0f; + + @SuppressLint("NewApi") + @Override + public void onScaleChanged(final WebView view, final float oldScale, final float newScale) { + if (view.isShown() && mLightningView.mPreferences.getTextReflowEnabled() && + Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) { + if (mIsRunning) + return; + if (Math.abs(mZoomScale - newScale) > 0.01f) { + mIsRunning = view.postDelayed(new Runnable() { + + @Override + public void run() { + mZoomScale = newScale; + view.evaluateJavascript(Constants.JAVASCRIPT_TEXT_REFLOW, null); + mIsRunning = false; + } + + }, 100); + } + + } + } + + @Override + public void onReceivedSslError(WebView view, @NonNull final SslErrorHandler handler, SslError error) { + AlertDialog.Builder builder = new AlertDialog.Builder(mActivity); + builder.setTitle(mActivity.getString(R.string.title_warning)); + builder.setMessage(mActivity.getString(R.string.message_untrusted_certificate)) + .setCancelable(true) + .setPositiveButton(mActivity.getString(R.string.action_yes), + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int id) { + handler.proceed(); + } + }) + .setNegativeButton(mActivity.getString(R.string.action_no), + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int id) { + handler.cancel(); + } + }); + AlertDialog alert = builder.create(); + if (error.getPrimaryError() == SslError.SSL_UNTRUSTED) { + alert.show(); + } else { + handler.proceed(); + } + + } + + @Override + public void onFormResubmission(WebView view, @NonNull final Message dontResend, final Message resend) { + AlertDialog.Builder builder = new AlertDialog.Builder(mActivity); + builder.setTitle(mActivity.getString(R.string.title_form_resubmission)); + builder.setMessage(mActivity.getString(R.string.message_form_resubmission)) + .setCancelable(true) + .setPositiveButton(mActivity.getString(R.string.action_yes), + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int id) { + + resend.sendToTarget(); + } + }) + .setNegativeButton(mActivity.getString(R.string.action_no), + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int id) { + + dontResend.sendToTarget(); + } + }); + AlertDialog alert = builder.create(); + alert.show(); + } + + @Override + public boolean shouldOverrideUrlLoading(WebView view, String url) { + // Check if configured proxy is available + if (!ProxyUtils.getInstance().isProxyReady()) { + // User has been notified + return true; + } + + if (mLightningView.mIsIncognitoTab) { + return super.shouldOverrideUrlLoading(view, url); + } + if (url.startsWith("about:")) { + return super.shouldOverrideUrlLoading(view, url); + } + if (url.contains("mailto:")) { + MailTo mailTo = MailTo.parse(url); + Intent i = Utils.newEmailIntent(mailTo.getTo(), mailTo.getSubject(), + mailTo.getBody(), mailTo.getCc()); + mActivity.startActivity(i); + view.reload(); + return true; + } else if (url.startsWith("intent://")) { + Intent intent; + try { + intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME); + } catch (URISyntaxException ex) { + return false; + } + if (intent != null) { + try { + mActivity.startActivity(intent); + } catch (ActivityNotFoundException e) { + Log.e(Constants.TAG, "ActivityNotFoundException"); + } + return true; + } + } + return mIntentUtils.startActivityForUrl(view, url); + } +} From 1f025debd7cbbad7f171870d80ee3683a2c6e285 Mon Sep 17 00:00:00 2001 From: Stefano Pacifici Date: Mon, 28 Sep 2015 15:44:23 +0200 Subject: [PATCH 13/16] Solve problems with colors when tabs are switched --- .../lightning/activity/BrowserActivity.java | 4 +- .../lightning/fragment/TabsFragment.java | 96 ++++++++++++++++--- 2 files changed, 85 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java b/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java index 0188bdc..fa79e74 100644 --- a/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java +++ b/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java @@ -235,7 +235,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); mDrawerRight = (ViewGroup) findViewById(R.id.right_drawer); mDrawerRight.setLayerType(View.LAYER_TYPE_HARDWARE, null); -// TODO Probably should be moved to the TabsFragement +// TODO Please review this // ImageView tabTitleImage = (ImageView) findViewById(R.id.plusIcon); // tabTitleImage.setColorFilter(mIconColor, PorterDuff.Mode.SRC_IN); @@ -253,8 +253,8 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements final TabsFragment tabsFragment = new TabsFragment(); final int containerId = mShowTabsInDrawer ? R.id.left_drawer : R.id.tabs_toolbar_container; final Bundle arguments = new Bundle(); + arguments.putBoolean(TabsFragment.IS_INCOGNITO, isIncognito()); arguments.putBoolean(TabsFragment.VERTICAL_MODE, mShowTabsInDrawer); - arguments.putBoolean(TabsFragment.USE_DARK_THEME, mDarkTheme); tabsFragment.setArguments(arguments); getSupportFragmentManager() .beginTransaction() diff --git a/app/src/main/java/acr/browser/lightning/fragment/TabsFragment.java b/app/src/main/java/acr/browser/lightning/fragment/TabsFragment.java index 678c332..2047453 100644 --- a/app/src/main/java/acr/browser/lightning/fragment/TabsFragment.java +++ b/app/src/main/java/acr/browser/lightning/fragment/TabsFragment.java @@ -1,6 +1,9 @@ package acr.browser.lightning.fragment; +import android.animation.ArgbEvaluator; +import android.animation.ValueAnimator; import android.content.Context; +import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; @@ -10,6 +13,7 @@ import android.graphics.ColorMatrixColorFilter; import android.graphics.Paint; import android.graphics.PorterDuff; import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Bundle; @@ -18,12 +22,14 @@ import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.support.v4.view.ViewCompat; +import android.support.v7.graphics.Palette; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView.LayoutManager; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.view.Window; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; @@ -42,6 +48,7 @@ import acr.browser.lightning.app.BrowserApp; import acr.browser.lightning.bus.BrowserEvents; import acr.browser.lightning.bus.NavigationEvents; import acr.browser.lightning.bus.TabEvents; +import acr.browser.lightning.preference.PreferenceManager; import acr.browser.lightning.utils.ThemeUtils; import acr.browser.lightning.utils.Utils; import acr.browser.lightning.view.LightningView; @@ -59,13 +66,13 @@ public class TabsFragment extends Fragment implements View.OnClickListener, View * If true, the fragment is in the left drawner in the strip otherwise. */ public static final String VERTICAL_MODE = TAG + ".VERTICAL_MODE"; - public static final String USE_DARK_THEME = TAG + ".USE_DARK_THEME"; + public static final String IS_INCOGNITO = TAG + ".IS_INCOGNITO"; - private boolean mDarkTheme; + private boolean mIsIncognito, mDarkTheme; private int mIconColor; - private boolean mColorMode = true; // TODO Only temporary - private boolean isIncognito = false; // TODO Only temporary - private int mCurrentUiColor = 0; // TODO Only temporary + private boolean mColorMode = true; + private boolean mShowInNavigationDrawer; + private int mCurrentUiColor = Color.BLACK; // TODO Only temporary private RecyclerView mRecyclerView; private LightningViewAdapter mTabsAdapter; @@ -76,6 +83,9 @@ public class TabsFragment extends Fragment implements View.OnClickListener, View @Inject Bus bus; + @Inject + PreferenceManager mPreferences; + public TabsFragment() { BrowserApp.getAppComponent().inject(this); } @@ -85,7 +95,11 @@ public class TabsFragment extends Fragment implements View.OnClickListener, View super.onCreate(savedInstanceState); final Bundle arguments = getArguments(); final Context context = getContext(); - mDarkTheme = arguments.getBoolean(USE_DARK_THEME, false); + mIsIncognito = arguments.getBoolean(IS_INCOGNITO, false); + mShowInNavigationDrawer = arguments.getBoolean(VERTICAL_MODE, true); + mDarkTheme = mPreferences.getUseTheme() != 0 || mIsIncognito; + mColorMode = mPreferences.getColorModeEnabled(); + mColorMode &= !mDarkTheme; mIconColor = mDarkTheme ? ThemeUtils.getIconDarkThemeColor(context) : ThemeUtils.getIconLightThemeColor(context); @@ -95,10 +109,9 @@ public class TabsFragment extends Fragment implements View.OnClickListener, View @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { final Bundle arguments = getArguments(); - final boolean vertical = arguments.getBoolean(VERTICAL_MODE, true); final View view; final LayoutManager layoutManager; - if (vertical) { + if (mShowInNavigationDrawer) { view = inflater.inflate(R.layout.tab_drawer, container, false); layoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false); // TODO Handle also long press @@ -112,7 +125,7 @@ public class TabsFragment extends Fragment implements View.OnClickListener, View } mRecyclerView = (RecyclerView) view.findViewById(R.id.tabs_list); mRecyclerView.setLayoutManager(layoutManager); - mTabsAdapter = new LightningViewAdapter(vertical); + mTabsAdapter = new LightningViewAdapter(mShowInNavigationDrawer); mRecyclerView.setAdapter(mTabsAdapter); mRecyclerView.setHasFixedSize(true); return view; @@ -249,7 +262,7 @@ public class TabsFragment extends Fragment implements View.OnClickListener, View Drawable foregroundDrawable; if (!vertical) { foregroundDrawable = new BitmapDrawable(getResources(), mForegroundTabBitmap); - if (!isIncognito && mColorMode) { + if (!mIsIncognito && mColorMode) { foregroundDrawable.setColorFilter(mCurrentUiColor, PorterDuff.Mode.SRC_IN); } } else { @@ -260,9 +273,8 @@ public class TabsFragment extends Fragment implements View.OnClickListener, View } else { holder.layout.setBackgroundDrawable(foregroundDrawable); } - if (!isIncognito && mColorMode) { - // TODO Restore this - // changeToolbarBackground(favicon, foregroundDrawable); + if (!mIsIncognito && mColorMode) { + changeToolbarBackground(favicon, foregroundDrawable); } holder.favicon.setImageBitmap(favicon); } else { @@ -302,6 +314,64 @@ public class TabsFragment extends Fragment implements View.OnClickListener, View return grayscaleBitmap; } + /** + * Animates the color of the toolbar from one color to another. Optionally animates + * the color of the tab background, for use when the tabs are displayed on the top + * of the screen. + * + * @param favicon the Bitmap to extract the color from + * @param tabBackground the optional LinearLayout to color + */ + private void changeToolbarBackground(@NonNull Bitmap favicon, @Nullable final Drawable tabBackground) { + if (mShowInNavigationDrawer) { + return; + } + + final int defaultColor; + final Resources resources = getResources(); + final ColorDrawable mBackground = new ColorDrawable(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + defaultColor = resources.getColor(R.color.primary_color, null); + } else { + defaultColor = resources.getColor(R.color.primary_color); + } + if (mCurrentUiColor == Color.BLACK) { + mCurrentUiColor = defaultColor; + } + Palette.from(favicon).generate(new Palette.PaletteAsyncListener() { + @Override + public void onGenerated(Palette palette) { + + // OR with opaque black to remove transparency glitches + int color = 0xff000000 | palette.getVibrantColor(defaultColor); + + int finalColor = Utils.mixTwoColors(defaultColor, color, 0.25f); + + ValueAnimator anim = ValueAnimator.ofInt(mCurrentUiColor, finalColor); + anim.setEvaluator(new ArgbEvaluator()); + // final Window window = getWindow(); + // TODO Check this + // if (!mShowInNavigationDrawer) { + // window.setBackgroundDrawable(new ColorDrawable(Color.BLACK)); + // } + anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + + @Override + public void onAnimationUpdate(ValueAnimator animation) { + final int color = (Integer) animation.getAnimatedValue(); + if (tabBackground != null) { + tabBackground.setColorFilter(color, PorterDuff.Mode.SRC_IN); + } + mCurrentUiColor = color; + } + + }); + anim.setDuration(300); + anim.start(); + } + }); + } + public class LightningViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener { public LightningViewHolder(View view) { From b0c1bcc0282e62c3d9d4d4228a41caf7e72dfdf1 Mon Sep 17 00:00:00 2001 From: Stefano Pacifici Date: Wed, 9 Sep 2015 09:52:11 +0200 Subject: [PATCH 14/16] iml files removed. They are generated during gradle sync by Android Studio. --- .gitignore | 2 + app/app.iml | 139 ---------------------------------------------------- 2 files changed, 2 insertions(+), 139 deletions(-) delete mode 100644 app/app.iml diff --git a/.gitignore b/.gitignore index 7f036ba..39bb026 100644 --- a/.gitignore +++ b/.gitignore @@ -50,3 +50,5 @@ out # Source: # https://raw.githubusercontent.com/github/gitignore/master/Android.gitignore # https://gitlab.com/fdroid/fdroidclient/raw/master/.gitignore + +*.iml diff --git a/app/app.iml b/app/app.iml deleted file mode 100644 index d6f1ddb..0000000 --- a/app/app.iml +++ /dev/null @@ -1,139 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file From 61b57cd992decfa502492cc127cf3066f1feff72 Mon Sep 17 00:00:00 2001 From: Stefano Pacifici Date: Tue, 29 Sep 2015 14:39:05 +0200 Subject: [PATCH 15/16] Restore activity restart when tab mode changes --- .../lightning/activity/BrowserActivity.java | 3 +-- .../activity/ThemableBrowserActivity.java | 15 +++++++++++---- .../acr/browser/lightning/app/AppComponent.java | 3 +++ .../acr/browser/lightning/bus/BrowserEvents.java | 12 ++++++------ 4 files changed, 21 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java b/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java index 609476a..2638622 100644 --- a/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java +++ b/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java @@ -191,8 +191,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements @Inject TabsManager tabsManager; - @Inject - PreferenceManager mPreferences; + // Preference manager was moved on ThemeableBrowserActivity @Inject HistoryDatabase mHistoryDatabase; diff --git a/app/src/main/java/acr/browser/lightning/activity/ThemableBrowserActivity.java b/app/src/main/java/acr/browser/lightning/activity/ThemableBrowserActivity.java index b84d798..13f210e 100644 --- a/app/src/main/java/acr/browser/lightning/activity/ThemableBrowserActivity.java +++ b/app/src/main/java/acr/browser/lightning/activity/ThemableBrowserActivity.java @@ -5,18 +5,25 @@ import android.content.res.Configuration; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; +import javax.inject.Inject; + import acr.browser.lightning.R; +import acr.browser.lightning.app.BrowserApp; import acr.browser.lightning.preference.PreferenceManager; public abstract class ThemableBrowserActivity extends AppCompatActivity { + @Inject + PreferenceManager mPreferences; + private int mTheme; private boolean mShowTabsInDrawer; @Override protected void onCreate(Bundle savedInstanceState) { - mTheme = 0; //PreferenceManager.getInstance().getUseTheme(); - mShowTabsInDrawer = false; // PreferenceManager.getInstance().getShowTabsInDrawer(!isTablet()); + BrowserApp.getAppComponent().inject(this); + mTheme = mPreferences.getUseTheme(); + mShowTabsInDrawer = mPreferences.getShowTabsInDrawer(!isTablet()); // set the theme if (mTheme == 1) { @@ -30,8 +37,8 @@ public abstract class ThemableBrowserActivity extends AppCompatActivity { @Override protected void onResume() { super.onResume(); - int theme = 0; // PreferenceManager.getInstance().getUseTheme(); - boolean drawerTabs = false; // PreferenceManager.getInstance().getShowTabsInDrawer(!isTablet()); + int theme = mPreferences.getUseTheme(); + boolean drawerTabs = mPreferences.getShowTabsInDrawer(!isTablet()); if (theme != mTheme || mShowTabsInDrawer != drawerTabs) { restart(); } diff --git a/app/src/main/java/acr/browser/lightning/app/AppComponent.java b/app/src/main/java/acr/browser/lightning/app/AppComponent.java index 4eea3c7..6be83ca 100644 --- a/app/src/main/java/acr/browser/lightning/app/AppComponent.java +++ b/app/src/main/java/acr/browser/lightning/app/AppComponent.java @@ -7,6 +7,7 @@ import com.squareup.otto.Bus; import javax.inject.Singleton; import acr.browser.lightning.activity.BrowserActivity; +import acr.browser.lightning.activity.ThemableBrowserActivity; import acr.browser.lightning.constant.BookmarkPage; import acr.browser.lightning.database.HistoryDatabase; import acr.browser.lightning.dialog.LightningDialogBuilder; @@ -53,4 +54,6 @@ public interface AppComponent { Context getApplicationContext(); void inject(LightningView lightningView); + + void inject(ThemableBrowserActivity activity); } diff --git a/app/src/main/java/acr/browser/lightning/bus/BrowserEvents.java b/app/src/main/java/acr/browser/lightning/bus/BrowserEvents.java index f115149..478dbce 100644 --- a/app/src/main/java/acr/browser/lightning/bus/BrowserEvents.java +++ b/app/src/main/java/acr/browser/lightning/bus/BrowserEvents.java @@ -17,9 +17,9 @@ public final class BrowserEvents { * result is a new bookmark added. */ public static class AddBookmark { - public final java.lang.String title, url; + public final String title, url; - public AddBookmark(final java.lang.String title, final java.lang.String url) { + public AddBookmark(final String title, final String url) { this.title = title; this.url = url; } @@ -30,9 +30,9 @@ public final class BrowserEvents { * {@link acr.browser.lightning.fragment.BookmarksFragment} interface. */ public static class CurrentPageUrl { - public final java.lang.String url; + public final String url; - public CurrentPageUrl(final java.lang.String url) { + public CurrentPageUrl(final String url) { this.url = url; } } @@ -57,11 +57,11 @@ public final class BrowserEvents { * Notify the Browser to display a SnackBar in the main activity */ public static class ShowSnackBarMessage { - public final java.lang.String message; + public final String message; @StringRes public final int stringRes; - public ShowSnackBarMessage(final java.lang.String message) { + public ShowSnackBarMessage(final String message) { this.message = message; this.stringRes = -1; } From a3f3fbd401d85654c9a5e0d27672ff480aa842b3 Mon Sep 17 00:00:00 2001 From: Stefano Pacifici Date: Wed, 7 Oct 2015 11:07:41 +0200 Subject: [PATCH 16/16] Improving the #296 pull request --- .../lightning/activity/BrowserActivity.java | 55 +++++----------- .../lightning/activity/TabsManager.java | 13 +--- .../controller/BrowserController.java | 4 -- .../lightning/database/HistoryDatabase.java | 2 +- .../lightning/download/DownloadHandler.java | 66 +++++++++---------- .../lightning/download/FetchUrlMimeType.java | 16 +++-- .../download/LightningDownloadListener.java | 18 ++--- .../lightning/fragment/BookmarksFragment.java | 28 ++++---- .../lightning/fragment/TabsFragment.java | 1 - .../browser/lightning/utils/IntentUtils.java | 10 ++- .../lightning/view/LightningChromeClient.java | 24 +++++-- .../browser/lightning/view/LightningView.java | 3 - app/src/main/res/layout/activity_main.xml | 10 +-- 13 files changed, 112 insertions(+), 138 deletions(-) diff --git a/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java b/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java index 2638622..2a00326 100644 --- a/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java +++ b/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java @@ -11,6 +11,7 @@ import android.animation.ValueAnimator.AnimatorUpdateListener; import android.app.Activity; import android.content.ClipData; import android.content.ClipboardManager; +import android.content.ComponentName; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; @@ -32,6 +33,7 @@ import android.provider.MediaStore; import android.support.annotation.IdRes; import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import android.support.v4.app.FragmentManager; import android.support.v4.content.ContextCompat; import android.support.v4.view.GravityCompat; import android.support.v4.widget.DrawerLayout; @@ -104,6 +106,7 @@ import acr.browser.lightning.controller.BrowserController; import acr.browser.lightning.database.BookmarkManager; import acr.browser.lightning.database.HistoryDatabase; import acr.browser.lightning.dialog.LightningDialogBuilder; +import acr.browser.lightning.fragment.BookmarksFragment; import acr.browser.lightning.fragment.TabsFragment; import acr.browser.lightning.object.SearchAdapter; import acr.browser.lightning.preference.PreferenceManager; @@ -267,13 +270,21 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements final TabsFragment tabsFragment = new TabsFragment(); final int containerId = mShowTabsInDrawer ? R.id.left_drawer : R.id.tabs_toolbar_container; - final Bundle arguments = new Bundle(); - arguments.putBoolean(TabsFragment.IS_INCOGNITO, isIncognito()); - arguments.putBoolean(TabsFragment.VERTICAL_MODE, mShowTabsInDrawer); - tabsFragment.setArguments(arguments); - getSupportFragmentManager() + final Bundle tabsFragmentArguments = new Bundle(); + tabsFragmentArguments.putBoolean(TabsFragment.IS_INCOGNITO, isIncognito()); + tabsFragmentArguments.putBoolean(TabsFragment.VERTICAL_MODE, mShowTabsInDrawer); + tabsFragment.setArguments(tabsFragmentArguments); + + final BookmarksFragment bookmarksFragment = new BookmarksFragment(); + final Bundle bookmarksFragmentArguments = new Bundle(); + bookmarksFragmentArguments.putBoolean(BookmarksFragment.INCOGNITO_MODE, isIncognito()); + bookmarksFragment.setArguments(bookmarksFragmentArguments); + + final FragmentManager fragmentManager = getSupportFragmentManager(); + fragmentManager .beginTransaction() .add(containerId, tabsFragment) + .add(R.id.right_drawer, bookmarksFragment) .commit(); if (mShowTabsInDrawer) { mToolbarLayout.removeView(findViewById(R.id.tabs_toolbar_container)); @@ -981,7 +992,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements } // What? - int current = tabsManager.getPositionForTab(currentTab); + int current = tabsManager.positionOf(currentTab); if (current < 0) { return; } @@ -996,7 +1007,6 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements tabsManager.deleteTab(position); showTab(current - 1); mEventBus.post(new BrowserEvents.TabsChanged()); - tabToDelete.onDestroy(); } else if (tabsManager.size() > position + 1) { if (current == position) { showTab(position + 1); @@ -1006,8 +1016,6 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements } else { tabsManager.deleteTab(position); } - - tabToDelete.onDestroy(); } else if (tabsManager.size() > 1) { if (current == position) { showTab(position - 1); @@ -1016,8 +1024,6 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements mEventBus.post(new BrowserEvents.TabsChanged()); } else { } - - tabToDelete.onDestroy(); } else { if (currentTab.getUrl().startsWith(Constants.FILE) || currentTab.getUrl().equals(mHomepage)) { closeActivity(); @@ -1025,7 +1031,6 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements tabsManager.deleteTab(position); performExitCleanUp(); tabToDelete.pauseTimers(); - tabToDelete.onDestroy(); mEventBus.post(new BrowserEvents.TabsChanged()); finish(); } @@ -1626,32 +1631,6 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements } } - /** - * This interface method is used by the LightningView to obtain an - * image that is displayed as a placeholder on a video until the video - * has initialized and can begin loading. - * - * @return a Bitmap that can be used as a place holder for videos. - */ - @Override - public Bitmap getDefaultVideoPoster() { - return BitmapFactory.decodeResource(getResources(), android.R.drawable.spinner_background); - } - - /** - * An interface method so that we can inflate a view to send to - * a LightningView when it needs to display a video and has to - * show a loading dialog. Inflates a progress view and returns it. - * - * @return A view that should be used to display the state - * of a video's loading progress. - */ - @Override - public View getVideoLoadingProgressView() { - LayoutInflater inflater = LayoutInflater.from(this); - return inflater.inflate(R.layout.video_loading_progress, null); - } - /** * This method handles the JavaScript callback to create a new tab. * Basically this handles the event that JavaScript needs to create diff --git a/app/src/main/java/acr/browser/lightning/activity/TabsManager.java b/app/src/main/java/acr/browser/lightning/activity/TabsManager.java index 75d1a1d..19f159b 100644 --- a/app/src/main/java/acr/browser/lightning/activity/TabsManager.java +++ b/app/src/main/java/acr/browser/lightning/activity/TabsManager.java @@ -158,13 +158,11 @@ public class TabsManager { return null; } final LightningView tab = mWebViewList.remove(position); - // TODO This should not be done outside this call - // tab.onDestroy(); + tab.onDestroy(); return tab; } /** - * TODO I think it should be removed * Return the position of the given tab * @param tab * @return @@ -187,15 +185,6 @@ public class TabsManager { return builder.toString(); } - /** - * TODO Remove this, temporary workaround - * @param tab - * @return - */ - public int getPositionForTab(final LightningView tab) { - return mWebViewList.indexOf(tab); - } - /** * Return the {@link WebView} associated to the current tab, or null if there is no current tab * @return a {@link WebView} or null diff --git a/app/src/main/java/acr/browser/lightning/controller/BrowserController.java b/app/src/main/java/acr/browser/lightning/controller/BrowserController.java index 2a55663..a454386 100644 --- a/app/src/main/java/acr/browser/lightning/controller/BrowserController.java +++ b/app/src/main/java/acr/browser/lightning/controller/BrowserController.java @@ -29,10 +29,6 @@ public interface BrowserController { void onHideCustomView(); - Bitmap getDefaultVideoPoster(); - - View getVideoLoadingProgressView(); - void onCreateWindow(Message resultMsg); void onCloseWindow(LightningView view); diff --git a/app/src/main/java/acr/browser/lightning/database/HistoryDatabase.java b/app/src/main/java/acr/browser/lightning/database/HistoryDatabase.java index 45a98af..36498fb 100644 --- a/app/src/main/java/acr/browser/lightning/database/HistoryDatabase.java +++ b/app/src/main/java/acr/browser/lightning/database/HistoryDatabase.java @@ -89,7 +89,7 @@ public class HistoryDatabase extends SQLiteOpenHelper { } private void openIfNecessary() { - if (mDatabase == null) { + if (isClosed()) { mDatabase = this.getWritableDatabase(); } } diff --git a/app/src/main/java/acr/browser/lightning/download/DownloadHandler.java b/app/src/main/java/acr/browser/lightning/download/DownloadHandler.java index 3dd5a4e..e182811 100644 --- a/app/src/main/java/acr/browser/lightning/download/DownloadHandler.java +++ b/app/src/main/java/acr/browser/lightning/download/DownloadHandler.java @@ -3,10 +3,8 @@ */ package acr.browser.lightning.download; -import android.app.Activity; import android.app.DownloadManager; import android.content.ActivityNotFoundException; -import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; @@ -19,14 +17,17 @@ import android.util.Log; import android.webkit.CookieManager; import android.webkit.URLUtil; +import com.squareup.otto.Bus; + import java.io.File; import java.io.IOException; +import acr.browser.lightning.BuildConfig; import acr.browser.lightning.R; +import acr.browser.lightning.activity.MainActivity; import acr.browser.lightning.app.BrowserApp; +import acr.browser.lightning.bus.BrowserEvents; import acr.browser.lightning.constant.Constants; -import acr.browser.lightning.preference.PreferenceManager; -import acr.browser.lightning.utils.Utils; /** * Handle download requests @@ -45,13 +46,13 @@ public class DownloadHandler { * Notify the host application a download should be done, or that the data * should be streamed if a streaming viewer is available. * - * @param activity Activity requesting the download. - * @param url The full url to the content that should be downloaded - * @param userAgent User agent of the downloading application. - * @param contentDisposition Content-disposition http header, if present. - * @param mimetype The mimetype of the content reported by the server + * @param context The context in which the download was requested. + * @param url The full url to the content that should be downloaded + * @param userAgent User agent of the downloading application. + * @param contentDisposition Content-disposition http header, if present. + * @param mimetype The mimetype of the content reported by the server */ - public static void onDownloadStart(Activity activity, String url, String userAgent, + public static void onDownloadStart(Context context, String url, String userAgent, String contentDisposition, String mimetype) { // if we're dealing wih A/V content that's not explicitly marked // for download, check if it's streamable. @@ -62,18 +63,17 @@ public class DownloadHandler { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setDataAndType(Uri.parse(url), mimetype); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - ResolveInfo info = activity.getPackageManager().resolveActivity(intent, + ResolveInfo info = context.getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY); if (info != null) { - ComponentName myName = activity.getComponentName(); // If we resolved to ourselves, we don't want to attempt to // load the url only to try and download it again. - if (!myName.getPackageName().equals(info.activityInfo.packageName) - || !myName.getClassName().equals(info.activityInfo.name)) { + if (BuildConfig.APPLICATION_ID.equals(info.activityInfo.packageName) + || MainActivity.class.getName().equals(info.activityInfo.name)) { // someone (other than us) knows how to handle this mime // type with this scheme, don't download. try { - activity.startActivity(intent); + context.startActivity(intent); return; } catch (ActivityNotFoundException ex) { // Best behavior is to fall back to a download in this @@ -82,8 +82,7 @@ public class DownloadHandler { } } } - onDownloadStartNoStream(activity, url, userAgent, contentDisposition, mimetype - ); + onDownloadStartNoStream(context, url, userAgent, contentDisposition, mimetype); } // This is to work around the fact that java.net.URI throws Exceptions @@ -120,17 +119,17 @@ public class DownloadHandler { * Notify the host application a download should be done, even if there is a * streaming viewer available for thise type. * - * @param activity Activity requesting the download. + * @param context The context in which the download is requested. * @param url The full url to the content that should be downloaded * @param userAgent User agent of the downloading application. * @param contentDisposition Content-disposition http header, if present. * @param mimetype The mimetype of the content reported by the server */ /* package */ - private static void onDownloadStartNoStream(final Activity activity, String url, String userAgent, + private static void onDownloadStartNoStream(final Context context, String url, String userAgent, String contentDisposition, String mimetype) { - - String filename = URLUtil.guessFileName(url, contentDisposition, mimetype); + final Bus eventBus = BrowserApp.getAppComponent().getBus(); + final String filename = URLUtil.guessFileName(url, contentDisposition, mimetype); // Check to see if we have an SDCard String status = Environment.getExternalStorageState(); @@ -140,14 +139,14 @@ public class DownloadHandler { // Check to see if the SDCard is busy, same as the music app if (status.equals(Environment.MEDIA_SHARED)) { - msg = activity.getString(R.string.download_sdcard_busy_dlg_msg); + msg = context.getString(R.string.download_sdcard_busy_dlg_msg); title = R.string.download_sdcard_busy_dlg_title; } else { - msg = activity.getString(R.string.download_no_sdcard_dlg_msg, filename); + msg = context.getString(R.string.download_no_sdcard_dlg_msg, filename); title = R.string.download_no_sdcard_dlg_title; } - new AlertDialog.Builder(activity).setTitle(title) + new AlertDialog.Builder(context).setTitle(title) .setIcon(android.R.drawable.ic_dialog_alert).setMessage(msg) .setPositiveButton(R.string.action_ok, null).show(); return; @@ -163,7 +162,7 @@ public class DownloadHandler { // This only happens for very bad urls, we want to catch the // exception here Log.e(TAG, "Exception while trying to parse url '" + url + '\'', e); - Utils.showSnackbar(activity, R.string.problem_download); + eventBus.post(new BrowserEvents.ShowSnackBarMessage(R.string.problem_download)); return; } @@ -173,7 +172,7 @@ public class DownloadHandler { try { request = new DownloadManager.Request(uri); } catch (IllegalArgumentException e) { - Utils.showSnackbar(activity, R.string.cannot_download); + eventBus.post(new BrowserEvents.ShowSnackBarMessage(R.string.cannot_download)); return; } request.setMimeType(mimetype); @@ -195,12 +194,12 @@ public class DownloadHandler { File dir = new File(downloadFolder.getPath()); if (!dir.isDirectory() && !dir.mkdirs()) { // Cannot make the directory - Utils.showSnackbar(activity, R.string.problem_location_download); + eventBus.post(new BrowserEvents.ShowSnackBarMessage(R.string.problem_location_download)); return; } if (!isWriteAccessAvailable(downloadFolder)) { - Utils.showSnackbar(activity, R.string.problem_location_download); + eventBus.post(new BrowserEvents.ShowSnackBarMessage(R.string.problem_location_download)); return; } request.setDestinationUri(Uri.parse(Constants.FILE + location + filename)); @@ -220,9 +219,9 @@ public class DownloadHandler { } // We must have long pressed on a link or image to download it. We // are not sure of the mimetype in this case, so do a head request - new FetchUrlMimeType(activity, request, addressString, cookies, userAgent).start(); + new FetchUrlMimeType(context, request, addressString, cookies, userAgent).start(); } else { - final DownloadManager manager = (DownloadManager) activity + final DownloadManager manager = (DownloadManager) context .getSystemService(Context.DOWNLOAD_SERVICE); new Thread() { @Override @@ -232,15 +231,16 @@ public class DownloadHandler { } catch (IllegalArgumentException e) { // Probably got a bad URL or something e.printStackTrace(); - Utils.showSnackbar(activity, R.string.cannot_download); + eventBus.post(new BrowserEvents.ShowSnackBarMessage(R.string.cannot_download)); } catch (SecurityException e) { // TODO write a download utility that downloads files rather than rely on the system // because the system can only handle Environment.getExternal... as a path - Utils.showSnackbar(activity, R.string.problem_location_download); + eventBus.post(new BrowserEvents.ShowSnackBarMessage(R.string.problem_location_download)); } } }.start(); - Utils.showSnackbar(activity, activity.getString(R.string.download_pending) + ' ' + filename); + eventBus.post(new BrowserEvents.ShowSnackBarMessage( + context.getString(R.string.download_pending) + ' ' + filename)); } } diff --git a/app/src/main/java/acr/browser/lightning/download/FetchUrlMimeType.java b/app/src/main/java/acr/browser/lightning/download/FetchUrlMimeType.java index 39da66f..80d5995 100644 --- a/app/src/main/java/acr/browser/lightning/download/FetchUrlMimeType.java +++ b/app/src/main/java/acr/browser/lightning/download/FetchUrlMimeType.java @@ -3,18 +3,21 @@ */ package acr.browser.lightning.download; -import android.app.Activity; import android.app.DownloadManager; import android.content.Context; import android.os.Environment; import android.webkit.MimeTypeMap; import android.webkit.URLUtil; +import com.squareup.otto.Bus; + import java.io.IOException; import java.net.HttpURLConnection; import java.net.URL; import acr.browser.lightning.R; +import acr.browser.lightning.app.BrowserApp; +import acr.browser.lightning.bus.BrowserEvents; import acr.browser.lightning.utils.Utils; /** @@ -27,7 +30,7 @@ import acr.browser.lightning.utils.Utils; */ class FetchUrlMimeType extends Thread { - private final Activity mActivity; + private final Context mContext; private final DownloadManager.Request mRequest; @@ -37,9 +40,9 @@ class FetchUrlMimeType extends Thread { private final String mUserAgent; - public FetchUrlMimeType(Activity activity, DownloadManager.Request request, String uri, + public FetchUrlMimeType(Context context, DownloadManager.Request request, String uri, String cookies, String userAgent) { - mActivity = activity; + mContext = context; mRequest = request; mUri = uri; mCookies = cookies; @@ -50,6 +53,7 @@ class FetchUrlMimeType extends Thread { public void run() { // User agent is likely to be null, though the AndroidHttpClient // seems ok with that. + final Bus evenBus = BrowserApp.getAppComponent().getBus(); String mimeType = null; String contentDisposition = null; HttpURLConnection connection = null; @@ -101,9 +105,9 @@ class FetchUrlMimeType extends Thread { } // Start the download - DownloadManager manager = (DownloadManager) mActivity + DownloadManager manager = (DownloadManager) mContext .getSystemService(Context.DOWNLOAD_SERVICE); manager.enqueue(mRequest); - Utils.showSnackbar(mActivity, mActivity.getString(R.string.download_pending) + ' ' + filename); + evenBus.post(new BrowserEvents.ShowSnackBarMessage(mContext.getString(R.string.download_pending) + ' ' + filename)); } } diff --git a/app/src/main/java/acr/browser/lightning/download/LightningDownloadListener.java b/app/src/main/java/acr/browser/lightning/download/LightningDownloadListener.java index 72f3ab8..6d6b7a1 100644 --- a/app/src/main/java/acr/browser/lightning/download/LightningDownloadListener.java +++ b/app/src/main/java/acr/browser/lightning/download/LightningDownloadListener.java @@ -3,7 +3,7 @@ */ package acr.browser.lightning.download; -import android.app.Activity; +import android.content.Context; import android.content.DialogInterface; import android.support.v7.app.AlertDialog; import android.util.Log; @@ -15,10 +15,10 @@ import acr.browser.lightning.constant.Constants; public class LightningDownloadListener implements DownloadListener { - private final Activity mActivity; + private final Context mContext; - public LightningDownloadListener(Activity activity) { - mActivity = activity; + public LightningDownloadListener(Context context) { + mContext = context; } @Override @@ -30,7 +30,7 @@ public class LightningDownloadListener implements DownloadListener { public void onClick(DialogInterface dialog, int which) { switch (which) { case DialogInterface.BUTTON_POSITIVE: - DownloadHandler.onDownloadStart(mActivity, url, userAgent, + DownloadHandler.onDownloadStart(mContext, url, userAgent, contentDisposition, mimetype); break; @@ -40,12 +40,12 @@ public class LightningDownloadListener implements DownloadListener { } }; - AlertDialog.Builder builder = new AlertDialog.Builder(mActivity); // dialog + AlertDialog.Builder builder = new AlertDialog.Builder(mContext); // dialog builder.setTitle(fileName) - .setMessage(mActivity.getResources().getString(R.string.dialog_download)) - .setPositiveButton(mActivity.getResources().getString(R.string.action_download), + .setMessage(mContext.getResources().getString(R.string.dialog_download)) + .setPositiveButton(mContext.getResources().getString(R.string.action_download), dialogClickListener) - .setNegativeButton(mActivity.getResources().getString(R.string.action_cancel), + .setNegativeButton(mContext.getResources().getString(R.string.action_cancel), dialogClickListener).show(); Log.i(Constants.TAG, "Downloading" + fileName); diff --git a/app/src/main/java/acr/browser/lightning/fragment/BookmarksFragment.java b/app/src/main/java/acr/browser/lightning/fragment/BookmarksFragment.java index a0b8202..28f9a4f 100644 --- a/app/src/main/java/acr/browser/lightning/fragment/BookmarksFragment.java +++ b/app/src/main/java/acr/browser/lightning/fragment/BookmarksFragment.java @@ -52,6 +52,10 @@ import acr.browser.lightning.utils.ThemeUtils; */ public class BookmarksFragment extends Fragment implements View.OnClickListener, View.OnLongClickListener { + private final static String TAG = BookmarksFragment.class.getSimpleName(); + + public final static String INCOGNITO_MODE = TAG + ".INCOGNITO_MODE"; + // Managers @Inject BookmarkManager mBookmarkManager; @@ -83,6 +87,8 @@ public class BookmarksFragment extends Fragment implements View.OnClickListener, // Colors private int mIconColor, mScrollIndex; + private boolean mIsIncognito; + // Init asynchronously the bookmark manager private final Runnable mInitBookmarkManager = new Runnable() { @Override @@ -98,6 +104,14 @@ public class BookmarksFragment extends Fragment implements View.OnClickListener, public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); BrowserApp.getAppComponent().inject(this); + final Bundle arguments = getArguments(); + final Context context = getContext(); + mIsIncognito = arguments.getBoolean(INCOGNITO_MODE, false); + boolean darkTheme = mPreferenceManager.getUseTheme() != 0 || mIsIncognito; + mWebpageBitmap = ThemeUtils.getThemedBitmap(context, R.drawable.ic_webpage, darkTheme); + mFolderBitmap = ThemeUtils.getThemedBitmap(context, R.drawable.ic_folder, darkTheme); + mIconColor = darkTheme ? ThemeUtils.getIconDarkThemeColor(context) : + ThemeUtils.getIconLightThemeColor(context); } // Handle bookmark click @@ -137,6 +151,7 @@ public class BookmarksFragment extends Fragment implements View.OnClickListener, mBookmarksListView.setOnItemClickListener(mItemClickListener); mBookmarksListView.setOnItemLongClickListener(mItemLongClickListener); mBookmarkTitleImage = (ImageView) view.findViewById(R.id.starIcon); + mBookmarkTitleImage.setColorFilter(mIconColor, PorterDuff.Mode.SRC_IN); mBookmarkImage = (ImageView) view.findViewById(R.id.icon_star); final View backView = view.findViewById(R.id.bookmark_back_button); backView.setOnClickListener(new View.OnClickListener() { @@ -156,19 +171,6 @@ public class BookmarksFragment extends Fragment implements View.OnClickListener, return view; } - @Override - public void onActivityCreated(@Nullable Bundle savedInstanceState) { - // TODO remove dependency on BrowserActivity - super.onActivityCreated(savedInstanceState); - final BrowserActivity activity = (BrowserActivity) getActivity(); - boolean darkTheme = mPreferenceManager.getUseTheme() != 0 || ((BrowserActivity) activity).isIncognito(); - mWebpageBitmap = ThemeUtils.getThemedBitmap(activity, R.drawable.ic_webpage, darkTheme); - mFolderBitmap = ThemeUtils.getThemedBitmap(activity, R.drawable.ic_folder, darkTheme); - mIconColor = darkTheme ? ThemeUtils.getIconDarkThemeColor(activity) : - ThemeUtils.getIconLightThemeColor(activity); - mBookmarkTitleImage.setColorFilter(mIconColor, PorterDuff.Mode.SRC_IN); - } - @Override public void onStart() { super.onStart(); diff --git a/app/src/main/java/acr/browser/lightning/fragment/TabsFragment.java b/app/src/main/java/acr/browser/lightning/fragment/TabsFragment.java index 2047453..e964ec3 100644 --- a/app/src/main/java/acr/browser/lightning/fragment/TabsFragment.java +++ b/app/src/main/java/acr/browser/lightning/fragment/TabsFragment.java @@ -114,7 +114,6 @@ public class TabsFragment extends Fragment implements View.OnClickListener, View if (mShowInNavigationDrawer) { view = inflater.inflate(R.layout.tab_drawer, container, false); layoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false); - // TODO Handle also long press setupFrameLayoutButton(view, R.id.new_tab_button, R.id.icon_plus); setupFrameLayoutButton(view, R.id.action_back, R.id.icon_back); setupFrameLayoutButton(view, R.id.action_forward, R.id.icon_forward); diff --git a/app/src/main/java/acr/browser/lightning/utils/IntentUtils.java b/app/src/main/java/acr/browser/lightning/utils/IntentUtils.java index ea5bcf2..dcb9d6b 100644 --- a/app/src/main/java/acr/browser/lightning/utils/IntentUtils.java +++ b/app/src/main/java/acr/browser/lightning/utils/IntentUtils.java @@ -18,7 +18,7 @@ import java.util.regex.Pattern; public class IntentUtils { - private final Context mActivity; + private final Activity mActivity; private static final Pattern ACCEPTED_URI_SCHEMA = Pattern.compile("(?i)" + // switch on case insensitive matching @@ -63,11 +63,9 @@ public class IntentUtils { return false; } try { - // TODO Restore this -// if (mActivity.startActivityIfNeeded(intent, -1)) { -// return true; -// } - mActivity.startActivity(intent); + if (mActivity.startActivityIfNeeded(intent, -1)) { + return true; + } } catch (ActivityNotFoundException ex) { ex.printStackTrace(); } diff --git a/app/src/main/java/acr/browser/lightning/view/LightningChromeClient.java b/app/src/main/java/acr/browser/lightning/view/LightningChromeClient.java index 747dac2..7167582 100644 --- a/app/src/main/java/acr/browser/lightning/view/LightningChromeClient.java +++ b/app/src/main/java/acr/browser/lightning/view/LightningChromeClient.java @@ -3,11 +3,14 @@ package acr.browser.lightning.view; import android.Manifest; import android.app.Activity; import android.content.DialogInterface; +import android.content.res.Resources; import android.graphics.Bitmap; +import android.graphics.BitmapFactory; import android.net.Uri; import android.os.Message; import android.support.v7.app.AlertDialog; import android.util.Log; +import android.view.LayoutInflater; import android.view.View; import android.webkit.GeolocationPermissions; import android.webkit.ValueCallback; @@ -170,16 +173,29 @@ class LightningChromeClient extends WebChromeClient { return true; } + /** + * Obtain an image that is displayed as a placeholder on a video until the video has initialized + * and can begin loading. + * + * @return a Bitmap that can be used as a place holder for videos. + */ @Override public Bitmap getDefaultVideoPoster() { - // TODO Simplify the method can be moved here - return mActivity.getDefaultVideoPoster(); + final Resources resources = mActivity.getResources(); + return BitmapFactory.decodeResource(resources, android.R.drawable.spinner_background); } + /** + * Inflate a view to send to a LightningView when it needs to display a video and has to + * show a loading dialog. Inflates a progress view and returns it. + * + * @return A view that should be used to display the state + * of a video's loading progress. + */ @Override public View getVideoLoadingProgressView() { - // TODO Simplify the method can be moved here - return mActivity.getVideoLoadingProgressView(); + LayoutInflater inflater = LayoutInflater.from(mActivity); + return inflater.inflate(R.layout.video_loading_progress, null); } @Override diff --git a/app/src/main/java/acr/browser/lightning/view/LightningView.java b/app/src/main/java/acr/browser/lightning/view/LightningView.java index f541c74..964e897 100644 --- a/app/src/main/java/acr/browser/lightning/view/LightningView.java +++ b/app/src/main/java/acr/browser/lightning/view/LightningView.java @@ -99,7 +99,6 @@ public class LightningView { mWebView = new WebView(activity); mIsIncognitoTab = isIncognito; mTitle = new LightningViewTitle(activity, darkTheme); - // mAdBlock = AdBlock.getInstance(activity.getApplicationContext()); mPermissionsManager = PermissionsManager.getInstance(); mMaxFling = ViewConfiguration.get(activity).getScaledMaximumFlingVelocity(); @@ -195,8 +194,6 @@ public class LightningView { settings.setDefaultTextEncodingName(mPreferences.getTextEncoding()); mHomepage = mPreferences.getHomepage(); - // mAdBlock.updatePreference(); - setColorMode(mPreferences.getRenderingMode()); if (!mIsIncognitoTab) { diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 5f87668..eae84d4 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -41,14 +41,8 @@ android:id="@+id/right_drawer" android:background="?attr/drawerBackground" android:layout_width="@dimen/navigation_width" - android:layout_height="match_parent"> - - - + android:layout_height="match_parent" /> + \ No newline at end of file