Browse Source

New Full-screen mode works better and doesn't hide the top of the WebView, +other

* Now using material alertdialog on all versions
* cleaned up some code
* fixed lint issues and other inspection related problems
* Attempted to fix bugs found
master
Anthony Restaino 10 years ago
parent
commit
969cab81e7
  1. 2
      Lightning-Browser.iml
  2. 20
      app/app.iml
  3. 5
      app/build.gradle
  4. 2
      app/src/LightningPlus/java/acr/browser/lightning/utils/ProxyUtils.java
  5. 2
      app/src/main/java/acr/browser/lightning/activity/AppCompatPreferenceActivity.java
  6. 317
      app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java
  7. 7
      app/src/main/java/acr/browser/lightning/activity/IncognitoActivity.java
  8. 6
      app/src/main/java/acr/browser/lightning/activity/MainActivity.java
  9. 6
      app/src/main/java/acr/browser/lightning/activity/ReadingActivity.java
  10. 2
      app/src/main/java/acr/browser/lightning/activity/SettingsActivity.java
  11. 4
      app/src/main/java/acr/browser/lightning/activity/ThemableActivity.java
  12. 9
      app/src/main/java/acr/browser/lightning/activity/ThemableSettingsActivity.java
  13. 4
      app/src/main/java/acr/browser/lightning/controller/BrowserController.java
  14. 98
      app/src/main/java/acr/browser/lightning/database/BookmarkManager.java
  15. 4
      app/src/main/java/acr/browser/lightning/database/HistoryDatabase.java
  16. 53
      app/src/main/java/acr/browser/lightning/download/DownloadHandler.java
  17. 5
      app/src/main/java/acr/browser/lightning/download/LightningDownloadListener.java
  18. 2
      app/src/main/java/acr/browser/lightning/fragment/AdvancedSettingsFragment.java
  19. 32
      app/src/main/java/acr/browser/lightning/fragment/BookmarkSettingsFragment.java
  20. 13
      app/src/main/java/acr/browser/lightning/fragment/DisplaySettingsFragment.java
  21. 14
      app/src/main/java/acr/browser/lightning/fragment/GeneralSettingsFragment.java
  22. 9
      app/src/main/java/acr/browser/lightning/fragment/PrivacySettingsFragment.java
  23. 121
      app/src/main/java/acr/browser/lightning/object/SearchAdapter.java
  24. 2
      app/src/main/java/acr/browser/lightning/preference/PreferenceManager.java
  25. 5
      app/src/main/java/acr/browser/lightning/reading/ArticleTextExtractor.java
  26. 2
      app/src/main/java/acr/browser/lightning/reading/Converter.java
  27. 2
      app/src/main/java/acr/browser/lightning/reading/HtmlFetcher.java
  28. 9
      app/src/main/java/acr/browser/lightning/reading/SHelper.java
  29. 2
      app/src/main/java/acr/browser/lightning/utils/IntentUtils.java
  30. 34
      app/src/main/java/acr/browser/lightning/utils/ThemeUtils.java
  31. 25
      app/src/main/java/acr/browser/lightning/utils/Utils.java
  32. 93
      app/src/main/java/acr/browser/lightning/view/LightningView.java
  33. 2
      app/src/main/res/layout/picker_manual_proxy.xml
  34. 2
      app/src/main/res/layout/toolbar_content.xml
  35. 7
      app/src/main/res/layout/two_line_autocomplete.xml
  36. 3
      app/src/main/res/values-v21/styles.xml
  37. 5
      app/src/main/res/values/styles.xml

2
Lightning-Browser.iml

@ -8,7 +8,7 @@
</configuration> </configuration>
</facet> </facet>
</component> </component>
<component name="NewModuleRootManager" inherit-compiler-output="true"> <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="true">
<exclude-output /> <exclude-output />
<content url="file://$MODULE_DIR$"> <content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.gradle" /> <excludeFolder url="file://$MODULE_DIR$/.gradle" />

20
app/app.iml

@ -12,10 +12,12 @@
<option name="SELECTED_TEST_ARTIFACT" value="_android_test_" /> <option name="SELECTED_TEST_ARTIFACT" value="_android_test_" />
<option name="ASSEMBLE_TASK_NAME" value="assembleLightningPlusDebug" /> <option name="ASSEMBLE_TASK_NAME" value="assembleLightningPlusDebug" />
<option name="COMPILE_JAVA_TASK_NAME" value="compileLightningPlusDebugSources" /> <option name="COMPILE_JAVA_TASK_NAME" value="compileLightningPlusDebugSources" />
<option name="SOURCE_GEN_TASK_NAME" value="generateLightningPlusDebugSources" />
<option name="ASSEMBLE_TEST_TASK_NAME" value="assembleLightningPlusDebugAndroidTest" /> <option name="ASSEMBLE_TEST_TASK_NAME" value="assembleLightningPlusDebugAndroidTest" />
<option name="COMPILE_JAVA_TEST_TASK_NAME" value="compileLightningPlusDebugAndroidTestSources" /> <option name="COMPILE_JAVA_TEST_TASK_NAME" value="compileLightningPlusDebugAndroidTestSources" />
<option name="TEST_SOURCE_GEN_TASK_NAME" value="generateLightningPlusDebugAndroidTestSources" /> <afterSyncTasks>
<task>generateLightningPlusDebugAndroidTestSources</task>
<task>generateLightningPlusDebugSources</task>
</afterSyncTasks>
<option name="ALLOW_USER_CONFIGURATION" value="false" /> <option name="ALLOW_USER_CONFIGURATION" value="false" />
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" /> <option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
<option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" /> <option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
@ -24,7 +26,7 @@
</configuration> </configuration>
</facet> </facet>
</component> </component>
<component name="NewModuleRootManager" inherit-compiler-output="false"> <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="false">
<output url="file://$MODULE_DIR$/build/intermediates/classes/lightningPlus/debug" /> <output url="file://$MODULE_DIR$/build/intermediates/classes/lightningPlus/debug" />
<output-test url="file://$MODULE_DIR$/build/intermediates/classes/androidTest/lightningPlus/debug" /> <output-test url="file://$MODULE_DIR$/build/intermediates/classes/androidTest/lightningPlus/debug" />
<exclude-output /> <exclude-output />
@ -48,13 +50,13 @@
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/androidTest/lightningPlus/debug" isTestSource="true" generated="true" /> <sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/androidTest/lightningPlus/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/lightningPlus/debug" type="java-test-resource" /> <sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/lightningPlus/debug" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/generated/androidTest/lightningPlus/debug" type="java-test-resource" /> <sourceFolder url="file://$MODULE_DIR$/build/generated/res/generated/androidTest/lightningPlus/debug" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/LightningPlus/res" type="java-resource" /> <sourceFolder url="file://$MODULE_DIR$/src/lightningPlus/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/LightningPlus/resources" type="java-resource" /> <sourceFolder url="file://$MODULE_DIR$/src/lightningPlus/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/lightningPlus/assets" type="java-resource" /> <sourceFolder url="file://$MODULE_DIR$/src/lightningPlus/assets" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/LightningPlus/aidl" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/lightningPlus/aidl" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/lightningPlus/java" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/lightningPlus/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/LightningPlus/jni" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/lightningPlus/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/LightningPlus/rs" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/lightningPlus/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTestLightningPlus/res" type="java-test-resource" /> <sourceFolder url="file://$MODULE_DIR$/src/androidTestLightningPlus/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTestLightningPlus/resources" type="java-test-resource" /> <sourceFolder url="file://$MODULE_DIR$/src/androidTestLightningPlus/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTestLightningPlus/assets" type="java-test-resource" /> <sourceFolder url="file://$MODULE_DIR$/src/androidTestLightningPlus/assets" type="java-test-resource" />
@ -109,7 +111,7 @@
<excludeFolder url="file://$MODULE_DIR$/build/outputs" /> <excludeFolder url="file://$MODULE_DIR$/build/outputs" />
<excludeFolder url="file://$MODULE_DIR$/build/tmp" /> <excludeFolder url="file://$MODULE_DIR$/build/tmp" />
</content> </content>
<orderEntry type="jdk" jdkName="Android API 22 Platform" jdkType="Android SDK" /> <orderEntry type="jdk" jdkName="Android API 22 Platform (1)" jdkType="Android SDK" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" exported="" name="client-0.7" level="project" /> <orderEntry type="library" exported="" name="client-0.7" level="project" />
<orderEntry type="library" exported="" name="palette-v7-22.2.0" level="project" /> <orderEntry type="library" exported="" name="palette-v7-22.2.0" level="project" />

5
app/build.gradle

@ -12,8 +12,8 @@ android {
buildTypes { buildTypes {
debug { debug {
minifyEnabled true minifyEnabled false
shrinkResources true shrinkResources false
proguardFiles 'proguard-project.txt' proguardFiles 'proguard-project.txt'
} }
@ -48,6 +48,7 @@ dependencies {
compile 'com.android.support:appcompat-v7:22.2.0' compile 'com.android.support:appcompat-v7:22.2.0'
compile 'org.jsoup:jsoup:1.8.1' compile 'org.jsoup:jsoup:1.8.1'
// Only Lightning Plus needs the proxy libraries
lightningPlusCompile 'net.i2p.android:client:0.7' lightningPlusCompile 'net.i2p.android:client:0.7'
lightningPlusCompile(project(':libnetcipher')) lightningPlusCompile(project(':libnetcipher'))
} }

2
app/src/LightningPlus/java/acr/browser/lightning/utils/ProxyUtils.java

@ -1,9 +1,9 @@
package acr.browser.lightning.utils; package acr.browser.lightning.utils;
import android.app.Activity; import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.support.v7.app.AlertDialog;
import android.util.Log; import android.util.Log;
import net.i2p.android.ui.I2PAndroidHelper; import net.i2p.android.ui.I2PAndroidHelper;

2
app/src/main/java/acr/browser/lightning/activity/AppCompatPreferenceActivity.java

@ -4,6 +4,7 @@ import android.content.res.Configuration;
import android.os.Bundle; import android.os.Bundle;
import android.preference.PreferenceActivity; import android.preference.PreferenceActivity;
import android.support.annotation.LayoutRes; import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.v7.app.ActionBar; import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatDelegate; import android.support.v7.app.AppCompatDelegate;
@ -44,6 +45,7 @@ public abstract class AppCompatPreferenceActivity extends PreferenceActivity {
getDelegate().setSupportActionBar(toolbar); getDelegate().setSupportActionBar(toolbar);
} }
@NonNull
@Override @Override
public MenuInflater getMenuInflater() { public MenuInflater getMenuInflater() {
return getDelegate().getMenuInflater(); return getDelegate().getMenuInflater();

317
app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java

@ -5,11 +5,11 @@
package acr.browser.lightning.activity; package acr.browser.lightning.activity;
import android.animation.ArgbEvaluator; import android.animation.ArgbEvaluator;
import android.animation.LayoutTransition;
import android.animation.ValueAnimator; import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener; import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.app.Activity; import android.app.Activity;
import android.app.AlertDialog;
import android.content.ClipData; import android.content.ClipData;
import android.content.ClipboardManager; import android.content.ClipboardManager;
import android.content.Context; import android.content.Context;
@ -36,11 +36,13 @@ import android.os.Handler;
import android.os.Message; import android.os.Message;
import android.provider.Browser; import android.provider.Browser;
import android.provider.MediaStore; import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.v4.view.GravityCompat; import android.support.v4.view.GravityCompat;
import android.support.v4.view.ViewCompat; import android.support.v4.view.ViewCompat;
import android.support.v4.widget.DrawerLayout; import android.support.v4.widget.DrawerLayout;
import android.support.v4.widget.DrawerLayout.DrawerListener; import android.support.v4.widget.DrawerLayout.DrawerListener;
import android.support.v7.app.ActionBar; import android.support.v7.app.ActionBar;
import android.support.v7.app.AlertDialog;
import android.support.v7.graphics.Palette; import android.support.v7.graphics.Palette;
import android.support.v7.widget.Toolbar; import android.support.v7.widget.Toolbar;
import android.text.TextUtils; import android.text.TextUtils;
@ -62,7 +64,6 @@ import android.view.Window;
import android.view.WindowManager; import android.view.WindowManager;
import android.view.animation.Animation; import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener; import android.view.animation.Animation.AnimationListener;
import android.view.animation.AnimationUtils;
import android.view.animation.DecelerateInterpolator; import android.view.animation.DecelerateInterpolator;
import android.view.animation.Transformation; import android.view.animation.Transformation;
import android.view.inputmethod.EditorInfo; import android.view.inputmethod.EditorInfo;
@ -138,9 +139,10 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
private RelativeLayout mSearchBar; private RelativeLayout mSearchBar;
// List // List
private final List<LightningView> mWebViews = new ArrayList<>(); private final List<LightningView> mWebViewList = new ArrayList<>();
private List<HistoryItem> mBookmarkList; private List<HistoryItem> mBookmarkList;
private LightningView mCurrentView; private LightningView mCurrentView;
private WebView mWebView;
private AnimatedProgressBar mProgressBar; private AnimatedProgressBar mProgressBar;
private AutoCompleteTextView mSearch; private AutoCompleteTextView mSearch;
@ -207,7 +209,7 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
//TODO make sure dark theme flag gets set correctly //TODO make sure dark theme flag gets set correctly
mDarkTheme = mPreferences.getUseTheme() != 0 || isIncognito(); mDarkTheme = mPreferences.getUseTheme() != 0 || isIncognito();
mActivity = this; mActivity = this;
mWebViews.clear(); mWebViewList.clear();
mClickHandler = new ClickHandler(this); mClickHandler = new ClickHandler(this);
mBrowserFrame = (FrameLayout) findViewById(R.id.content_frame); mBrowserFrame = (FrameLayout) findViewById(R.id.content_frame);
@ -234,7 +236,7 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
mHomepage = mPreferences.getHomepage(); mHomepage = mPreferences.getHomepage();
mTitleAdapter = new LightningViewAdapter(this, R.layout.tab_list_item, mWebViews); mTitleAdapter = new LightningViewAdapter(this, R.layout.tab_list_item, mWebViewList);
mDrawerListLeft.setAdapter(mTitleAdapter); mDrawerListLeft.setAdapter(mTitleAdapter);
mDrawerListLeft.setOnItemClickListener(new DrawerItemClickListener()); mDrawerListLeft.setOnItemClickListener(new DrawerItemClickListener());
mDrawerListLeft.setOnItemLongClickListener(new DrawerItemLongClickListener()); mDrawerListLeft.setOnItemLongClickListener(new DrawerItemLongClickListener());
@ -244,6 +246,9 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
mHistoryDatabase = HistoryDatabase.getInstance(getApplicationContext()); mHistoryDatabase = HistoryDatabase.getInstance(getApplicationContext());
if (actionBar == null)
return;
// set display options of the ActionBar // set display options of the ActionBar
actionBar.setDisplayShowTitleEnabled(false); actionBar.setDisplayShowTitleEnabled(false);
actionBar.setDisplayShowHomeEnabled(false); actionBar.setDisplayShowHomeEnabled(false);
@ -410,7 +415,7 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
updateUrl(mCurrentView.getUrl(), true); updateUrl(mCurrentView.getUrl(), true);
} else if (hasFocus) { } else if (hasFocus) {
String url = mCurrentView.getUrl(); String url = mCurrentView.getUrl();
if (url == null || url.startsWith(Constants.FILE)) { if (url.startsWith(Constants.FILE)) {
mSearch.setText(""); mSearch.setText("");
} else { } else {
mSearch.setText(url); mSearch.setText(url);
@ -578,11 +583,11 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
/* /*
* Override this class * Override this class
*/ */
public synchronized void initializeTabs() { synchronized void initializeTabs() {
} }
public void restoreOrNewTab() { void restoreOrNewTab() {
mIdGenerator = 0; mIdGenerator = 0;
String url = null; String url = null;
@ -633,14 +638,31 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
changeToolbarBackground(mCurrentView.getFavicon()); changeToolbarBackground(mCurrentView.getFavicon());
} }
if (mFullScreen && mBrowserFrame.findViewById(R.id.toolbar_layout) == null) { if (mFullScreen) {
mToolbarLayout.setTranslationY(0);
int height = mToolbarLayout.getHeight();
if (height == 0) {
mToolbarLayout.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
height = mToolbarLayout.getMeasuredHeight();
}
if (mWebView != null)
mWebView.setTranslationY(height);
mBrowserFrame.setLayoutTransition(null);
if (mBrowserFrame.findViewById(R.id.toolbar_layout) == null) {
mUiLayout.removeView(mToolbarLayout); mUiLayout.removeView(mToolbarLayout);
mBrowserFrame.addView(mToolbarLayout); mBrowserFrame.addView(mToolbarLayout);
mToolbarLayout.bringToFront(); mToolbarLayout.bringToFront();
} else if (mBrowserFrame.findViewById(R.id.toolbar_layout) != null) { }
} else {
mToolbarLayout.setTranslationY(0);
if (mBrowserFrame.findViewById(R.id.toolbar_layout) != null) {
mBrowserFrame.removeView(mToolbarLayout); mBrowserFrame.removeView(mToolbarLayout);
mUiLayout.addView(mToolbarLayout, 0); mUiLayout.addView(mToolbarLayout, 0);
} }
mBrowserFrame.setLayoutTransition(new LayoutTransition());
if (mWebView != null)
mWebView.setTranslationY(0);
}
if (mPreferences.getHideStatusBarEnabled()) { if (mPreferences.getHideStatusBarEnabled()) {
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN); WindowManager.LayoutParams.FLAG_FULLSCREEN);
@ -695,7 +717,7 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
/* /*
* Override this if class overrides BrowserActivity * Override this if class overrides BrowserActivity
*/ */
public void updateCookiePreference() { void updateCookiePreference() {
} }
@ -714,7 +736,7 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
} }
@Override @Override
public boolean onKeyUp(int keyCode, KeyEvent event) { public boolean onKeyUp(int keyCode, @NonNull KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_MENU) && (Build.VERSION.SDK_INT <= 16) if ((keyCode == KeyEvent.KEYCODE_MENU) && (Build.VERSION.SDK_INT <= 16)
&& (Build.MANUFACTURER.compareTo("LGE") == 0)) { && (Build.MANUFACTURER.compareTo("LGE") == 0)) {
// Workaround for stupid LG devices that crash // Workaround for stupid LG devices that crash
@ -739,18 +761,14 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
} }
return true; return true;
case R.id.action_back: case R.id.action_back:
if (mCurrentView != null) { if (mCurrentView != null && mCurrentView.canGoBack()) {
if (mCurrentView.canGoBack()) {
mCurrentView.goBack(); mCurrentView.goBack();
} }
}
return true; return true;
case R.id.action_forward: case R.id.action_forward:
if (mCurrentView != null) { if (mCurrentView != null && mCurrentView.canGoForward()) {
if (mCurrentView.canGoForward()) {
mCurrentView.goForward(); mCurrentView.goForward();
} }
}
return true; return true;
case R.id.action_new_tab: case R.id.action_new_tab:
newTab(null, true); newTab(null, true);
@ -759,7 +777,7 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
startActivity(new Intent(this, IncognitoActivity.class)); startActivity(new Intent(this, IncognitoActivity.class));
return true; return true;
case R.id.action_share: case R.id.action_share:
if (!mCurrentView.getUrl().startsWith(Constants.FILE)) { if (mCurrentView != null && !mCurrentView.getUrl().startsWith(Constants.FILE)) {
Intent shareIntent = new Intent(android.content.Intent.ACTION_SEND); Intent shareIntent = new Intent(android.content.Intent.ACTION_SEND);
shareIntent.setType("text/plain"); shareIntent.setType("text/plain");
shareIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, shareIntent.putExtra(android.content.Intent.EXTRA_SUBJECT,
@ -774,15 +792,13 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
openBookmarks(); openBookmarks();
return true; return true;
case R.id.action_copy: case R.id.action_copy:
if (mCurrentView != null) { if (mCurrentView != null && !mCurrentView.getUrl().startsWith(Constants.FILE)) {
if (!mCurrentView.getUrl().startsWith(Constants.FILE)) {
ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE); ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("label", mCurrentView.getUrl()); ClipData clip = ClipData.newPlainText("label", mCurrentView.getUrl());
clipboard.setPrimaryClip(clip); clipboard.setPrimaryClip(clip);
Utils.showToast(mActivity, Utils.showToast(mActivity,
mActivity.getResources().getString(R.string.message_link_copied)); mActivity.getResources().getString(R.string.message_link_copied));
} }
}
return true; return true;
case R.id.action_settings: case R.id.action_settings:
startActivity(new Intent(this, SettingsActivity.class)); startActivity(new Intent(this, SettingsActivity.class));
@ -791,10 +807,10 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
openHistory(); openHistory();
return true; return true;
case R.id.action_add_bookmark: case R.id.action_add_bookmark:
if (!mCurrentView.getUrl().startsWith(Constants.FILE)) { if (mCurrentView != null && !mCurrentView.getUrl().startsWith(Constants.FILE)) {
HistoryItem bookmark = new HistoryItem(mCurrentView.getUrl(), HistoryItem bookmark = new HistoryItem(mCurrentView.getUrl(),
mCurrentView.getTitle()); mCurrentView.getTitle());
if (mBookmarkManager.addBookmark(bookmark)) { if (mBookmarkManager.addBookmark(bookmark) && mBookmarkList != null) {
mBookmarkList.add(bookmark); mBookmarkList.add(bookmark);
Collections.sort(mBookmarkList, new SortIgnoreCase()); Collections.sort(mBookmarkList, new SortIgnoreCase());
notifyBookmarkDataSetChanged(); notifyBookmarkDataSetChanged();
@ -901,7 +917,7 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
@Override @Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) { public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
mIsNewIntent = false; mIsNewIntent = false;
showTab(mWebViews.get(position)); showTab(mWebViewList.get(position));
} }
} }
@ -985,8 +1001,7 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
* Takes in the id of which bookmark was selected and shows a dialog that * Takes in the id of which bookmark was selected and shows a dialog that
* allows the user to rename and change the url of the bookmark * allows the user to rename and change the url of the bookmark
* *
* @param id * @param id which id in the list was chosen
* which id in the list was chosen
*/ */
private synchronized void editBookmark(final int id) { private synchronized void editBookmark(final int id) {
final AlertDialog.Builder homePicker = new AlertDialog.Builder(mActivity); final AlertDialog.Builder homePicker = new AlertDialog.Builder(mActivity);
@ -1014,11 +1029,9 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
mBookmarkManager.overwriteBookmarks(mBookmarkList); mBookmarkManager.overwriteBookmarks(mBookmarkList);
Collections.sort(mBookmarkList, new SortIgnoreCase()); Collections.sort(mBookmarkList, new SortIgnoreCase());
notifyBookmarkDataSetChanged(); notifyBookmarkDataSetChanged();
if (mCurrentView != null) { if (mCurrentView != null && mCurrentView.getUrl().startsWith(Constants.FILE)
if (mCurrentView.getUrl().startsWith(Constants.FILE)
&& mCurrentView.getUrl().endsWith("bookmarks.html")) { && mCurrentView.getUrl().endsWith("bookmarks.html")) {
openBookmarkPage(mCurrentView.getWebView()); openBookmarkPage(mWebView);
}
} }
} }
}); });
@ -1029,8 +1042,7 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
* displays the WebView contained in the LightningView Also handles the * displays the WebView contained in the LightningView Also handles the
* removal of previous views * removal of previous views
* *
* @param view * @param view the LightningView to show
* the LightningView to show
*/ */
private synchronized void showTab(LightningView view) { private synchronized void showTab(LightningView view) {
// Set the background color so the color mode color doesn't show through // Set the background color so the color mode color doesn't show through
@ -1038,14 +1050,16 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
if (view == null) { if (view == null) {
return; return;
} }
final float translation = mToolbarLayout.getTranslationY();
mBrowserFrame.removeAllViews(); mBrowserFrame.removeAllViews();
if (mCurrentView != null) { if (mCurrentView != null) {
mCurrentView.setForegroundTab(false); mCurrentView.setForegroundTab(false);
mCurrentView.onPause(); mCurrentView.onPause();
} }
mCurrentView = view; mCurrentView = view;
mWebView = view.getWebView();
mCurrentView.setForegroundTab(true); mCurrentView.setForegroundTab(true);
if (mCurrentView.getWebView() != null) { if (mWebView != null) {
updateUrl(mCurrentView.getUrl(), true); updateUrl(mCurrentView.getUrl(), true);
updateProgress(mCurrentView.getProgress()); updateProgress(mCurrentView.getProgress());
} else { } else {
@ -1053,22 +1067,48 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
updateProgress(0); updateProgress(0);
} }
mBrowserFrame.addView(mCurrentView.getWebView(), MATCH_PARENT); mBrowserFrame.addView(mWebView, MATCH_PARENT);
// Remove browser frame background to reduce overdraw
mBrowserFrame.setBackgroundColor(0);
mCurrentView.requestFocus(); mCurrentView.requestFocus();
mCurrentView.onResume(); mCurrentView.onResume();
if (mFullScreen) {
// mToolbarLayout has already been removed
mBrowserFrame.addView(mToolbarLayout);
mToolbarLayout.bringToFront();
Log.d(Constants.TAG, "Move view to browser frame");
int height = mToolbarLayout.getHeight();
if (height == 0) {
mToolbarLayout.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
height = mToolbarLayout.getMeasuredHeight();
}
mWebView.setTranslationY(translation + height);
mToolbarLayout.setTranslationY(translation);
} else {
mWebView.setTranslationY(0);
}
showActionBar();
// Use a delayed handler to make the transition smooth // Use a delayed handler to make the transition smooth
// otherwise it will get caught up with the showTab code // otherwise it will get caught up with the showTab code
// and cause a janky motion // and cause a janky motion
final Handler handler = new Handler(); new Handler().postDelayed(new Runnable() {
handler.postDelayed(new Runnable() {
@Override @Override
public void run() { public void run() {
mDrawerLayout.closeDrawers(); mDrawerLayout.closeDrawers();
} }
}, 150); }, 150);
// new Handler().postDelayed(new Runnable() {
// @Override
// public void run() {
// // Remove browser frame background to reduce overdraw
// //TODO evaluate performance
// mBrowserFrame.setBackgroundColor(0);
// }
// }, 300);
} }
/** /**
@ -1079,7 +1119,7 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
super.onNewIntent(intent); super.onNewIntent(intent);
} }
public void handleNewIntent(Intent intent) { void handleNewIntent(Intent intent) {
String url = null; String url = null;
if (intent != null) { if (intent != null) {
@ -1103,7 +1143,7 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
@Override @Override
public void closeEmptyTab() { public void closeEmptyTab() {
if (mCurrentView != null && mCurrentView.getWebView().copyBackForwardList().getSize() == 0) { if (mWebView != null && mWebView.copyBackForwardList().getSize() == 0) {
closeCurrentTab(); closeCurrentTab();
} }
} }
@ -1117,15 +1157,15 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
public void onTrimMemory(int level) { public void onTrimMemory(int level) {
if (level > TRIM_MEMORY_MODERATE && Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { if (level > TRIM_MEMORY_MODERATE && Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
Log.d(Constants.TAG, "Low Memory, Free Memory"); Log.d(Constants.TAG, "Low Memory, Free Memory");
for (LightningView view : mWebViews) { for (int n = 0; n < mWebViewList.size(); n++) {
view.getWebView().freeMemory(); mWebViewList.get(n).freeMemory();
} }
} }
} }
protected synchronized boolean newTab(String url, boolean show) { synchronized boolean newTab(String url, boolean show) {
// Limit number of tabs for limited version of app // Limit number of tabs for limited version of app
if (!Constants.FULL_VERSION && mWebViews.size() >= 10) { if (!Constants.FULL_VERSION && mWebViewList.size() >= 10) {
Utils.showToast(this, this.getString(R.string.max_tabs)); Utils.showToast(this, this.getString(R.string.max_tabs));
return false; return false;
} }
@ -1135,28 +1175,27 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
startingTab.resumeTimers(); startingTab.resumeTimers();
} }
mIdGenerator++; mIdGenerator++;
mWebViews.add(startingTab); mWebViewList.add(startingTab);
mTitleAdapter.notifyDataSetChanged(); mTitleAdapter.notifyDataSetChanged();
if (show) { if (show) {
mDrawerListLeft.setItemChecked(mWebViews.size() - 1, true); mDrawerListLeft.setItemChecked(mWebViewList.size() - 1, true);
showTab(startingTab); showTab(startingTab);
} }
return true; return true;
} }
private synchronized void deleteTab(int position) { private synchronized void deleteTab(int position) {
if (position >= mWebViews.size()) { if (position >= mWebViewList.size()) {
return; return;
} }
int current = mDrawerListLeft.getCheckedItemPosition(); int current = mDrawerListLeft.getCheckedItemPosition();
LightningView reference = mWebViews.get(position); LightningView reference = mWebViewList.get(position);
if (reference == null) { if (reference == null) {
return; return;
} }
if (reference.getUrl() != null && !reference.getUrl().startsWith(Constants.FILE) if (!reference.getUrl().startsWith(Constants.FILE) && !isIncognito()) {
&& !isIncognito()) {
mPreferences.setSavedUrl(reference.getUrl()); mPreferences.setSavedUrl(reference.getUrl());
} }
boolean isShown = reference.isShown(); boolean isShown = reference.isShown();
@ -1164,35 +1203,34 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
mBrowserFrame.setBackgroundColor(mBackgroundColor); mBrowserFrame.setBackgroundColor(mBackgroundColor);
} }
if (current > position) { if (current > position) {
mWebViews.remove(position); mWebViewList.remove(position);
mDrawerListLeft.setItemChecked(current - 1, true); mDrawerListLeft.setItemChecked(current - 1, true);
reference.onDestroy(); reference.onDestroy();
} else if (mWebViews.size() > position + 1) { } else if (mWebViewList.size() > position + 1) {
if (current == position) { if (current == position) {
showTab(mWebViews.get(position + 1)); showTab(mWebViewList.get(position + 1));
mWebViews.remove(position); mWebViewList.remove(position);
mDrawerListLeft.setItemChecked(position, true); mDrawerListLeft.setItemChecked(position, true);
} else { } else {
mWebViews.remove(position); mWebViewList.remove(position);
} }
reference.onDestroy(); reference.onDestroy();
} else if (mWebViews.size() > 1) { } else if (mWebViewList.size() > 1) {
if (current == position) { if (current == position) {
showTab(mWebViews.get(position - 1)); showTab(mWebViewList.get(position - 1));
mWebViews.remove(position); mWebViewList.remove(position);
mDrawerListLeft.setItemChecked(position - 1, true); mDrawerListLeft.setItemChecked(position - 1, true);
} else { } else {
mWebViews.remove(position); mWebViewList.remove(position);
} }
reference.onDestroy(); reference.onDestroy();
} else { } else {
if (mCurrentView.getUrl() == null || mCurrentView.getUrl().startsWith(Constants.FILE) if (mCurrentView.getUrl().startsWith(Constants.FILE) || mCurrentView.getUrl().equals(mHomepage)) {
|| mCurrentView.getUrl().equals(mHomepage)) {
closeActivity(); closeActivity();
} else { } else {
mWebViews.remove(position); mWebViewList.remove(position);
if (mPreferences.getClearCacheExit() && mCurrentView != null && !isIncognito()) { if (mPreferences.getClearCacheExit() && mCurrentView != null && !isIncognito()) {
mCurrentView.clearCache(true); mCurrentView.clearCache(true);
Log.d(Constants.TAG, "Cache Cleared"); Log.d(Constants.TAG, "Cache Cleared");
@ -1211,6 +1249,7 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
reference.pauseTimers(); reference.pauseTimers();
reference.onDestroy(); reference.onDestroy();
mCurrentView = null; mCurrentView = null;
mWebView = null;
mTitleAdapter.notifyDataSetChanged(); mTitleAdapter.notifyDataSetChanged();
finish(); finish();
@ -1252,12 +1291,13 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
} }
mCurrentView = null; mCurrentView = null;
for (int n = 0; n < mWebViews.size(); n++) { mWebView = null;
if (mWebViews.get(n) != null) { for (int n = 0; n < mWebViewList.size(); n++) {
mWebViews.get(n).onDestroy(); if (mWebViewList.get(n) != null) {
mWebViewList.get(n).onDestroy();
} }
} }
mWebViews.clear(); mWebViewList.clear();
mTitleAdapter.notifyDataSetChanged(); mTitleAdapter.notifyDataSetChanged();
finish(); finish();
} }
@ -1334,12 +1374,12 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
} }
} }
public void saveOpenTabs() { void saveOpenTabs() {
if (mPreferences.getRestoreLostTabsEnabled()) { if (mPreferences.getRestoreLostTabsEnabled()) {
String s = ""; String s = "";
for (int n = 0; n < mWebViews.size(); n++) { for (int n = 0; n < mWebViewList.size(); n++) {
if (mWebViews.get(n).getUrl() != null) { if (mWebViewList.get(n).getUrl().length() > 0) {
s = s + mWebViews.get(n).getUrl() + "|$|SEPARATOR|$|"; s = s + mWebViewList.get(n).getUrl() + "|$|SEPARATOR|$|";
} }
} }
mPreferences.setMemoryUrl(s); mPreferences.setMemoryUrl(s);
@ -1384,12 +1424,12 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
notifyBookmarkDataSetChanged(); notifyBookmarkDataSetChanged();
} }
initializePreferences(); initializePreferences();
if (mWebViews != null) { if (mWebViewList != null) {
for (int n = 0; n < mWebViews.size(); n++) { for (int n = 0; n < mWebViewList.size(); n++) {
if (mWebViews.get(n) != null) { if (mWebViewList.get(n) != null) {
mWebViews.get(n).initializePreferences(this); mWebViewList.get(n).initializePreferences(this);
} else { } else {
mWebViews.remove(n); mWebViewList.remove(n);
} }
} }
} }
@ -1773,7 +1813,7 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
} }
public void addItemToHistory(final String title, final String url) { void addItemToHistory(final String title, final String url) {
Runnable update = new Runnable() { Runnable update = new Runnable() {
@Override @Override
public void run() { public void run() {
@ -1908,7 +1948,7 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
mDrawerLayout.openDrawer(mDrawerRight); mDrawerLayout.openDrawer(mDrawerRight);
} }
public void closeDrawers() { void closeDrawers() {
mDrawerLayout.closeDrawers(); mDrawerLayout.closeDrawers();
} }
@ -2066,12 +2106,12 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
Message click = mClickHandler.obtainMessage(); Message click = mClickHandler.obtainMessage();
if (click != null) { if (click != null) {
click.setTarget(mClickHandler); click.setTarget(mClickHandler);
mCurrentView.getWebView().requestFocusNodeHref(click); mWebView.requestFocusNodeHref(click);
} }
} }
@Override @Override
public void onShowCustomView(View view, int requestedOrientation, CustomViewCallback callback) { public void onShowCustomView(View view, CustomViewCallback callback) {
if (view == null) { if (view == null) {
return; return;
} }
@ -2155,8 +2195,7 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
/** /**
* turns on fullscreen mode in the app * turns on fullscreen mode in the app
* *
* @param enabled * @param enabled whether to enable fullscreen or not
* whether to enable fullscreen or not
*/ */
private void setFullscreen(boolean enabled) { private void setFullscreen(boolean enabled) {
Window win = getWindow(); Window win = getWindow();
@ -2187,7 +2226,7 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
@SuppressLint("ClickableViewAccessibility") @SuppressLint("ClickableViewAccessibility")
@Override @Override
public boolean onTouchEvent(MotionEvent evt) { public boolean onTouchEvent(@NonNull MotionEvent evt) {
return true; return true;
} }
@ -2223,13 +2262,13 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
/** /**
* handles javascript requests to create a new window in the browser * handles javascript requests to create a new window in the browser
*/ */
public void onCreateWindow(boolean isUserGesture, Message resultMsg) { public void onCreateWindow(Message resultMsg) {
if (resultMsg == null) { if (resultMsg == null) {
return; return;
} }
if (newTab("", true)) { if (newTab("", true)) {
WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj; WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj;
transport.setWebView(mCurrentView.getWebView()); transport.setWebView(mWebView);
resultMsg.sendToTarget(); resultMsg.sendToTarget();
} }
} }
@ -2243,6 +2282,10 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
return mActivity; return mActivity;
} }
private boolean isToolbarVisible() {
return mToolbarLayout.getTranslationY() > -0.01f;
}
/** /**
* it hides the action bar, seriously what else were you expecting * it hides the action bar, seriously what else were you expecting
*/ */
@ -2254,28 +2297,28 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
mBrowserFrame.addView(mToolbarLayout); mBrowserFrame.addView(mToolbarLayout);
mToolbarLayout.bringToFront(); mToolbarLayout.bringToFront();
Log.d(Constants.TAG, "Move view to browser frame"); Log.d(Constants.TAG, "Move view to browser frame");
mToolbarLayout.setTranslationY(0);
mWebView.setTranslationY(mToolbarLayout.getHeight());
} }
if (mToolbarLayout.getVisibility() != View.GONE) { if (mToolbarLayout == null || mCurrentView == null)
return;
Animation hide = AnimationUtils.loadAnimation(mActivity, R.anim.slide_up);
hide.setAnimationListener(new AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
mToolbarLayout.setVisibility(View.GONE);
}
final int height = mToolbarLayout.getHeight();
final WebView view = mWebView;
if (mToolbarLayout.getTranslationY() > -0.01f) {
Animation show = new Animation() {
@Override @Override
public void onAnimationRepeat(Animation animation) { protected void applyTransformation(float interpolatedTime, Transformation t) {
float trans = (1.0f - interpolatedTime) * height;
mToolbarLayout.setTranslationY(trans - height);
if (view != null)
view.setTranslationY(trans);
} }
};
}); show.setDuration(250);
mToolbarLayout.startAnimation(hide); show.setInterpolator(new DecelerateInterpolator());
Log.d(Constants.TAG, "Hide"); // show.setFillAfter(true);
mWebView.startAnimation(show);
} }
} }
} }
@ -2283,7 +2326,7 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
@Override @Override
public void toggleActionBar() { public void toggleActionBar() {
if (mFullScreen) { if (mFullScreen) {
if (mToolbarLayout.getVisibility() != View.VISIBLE) { if (!isToolbarVisible()) {
showActionBar(); showActionBar();
} else { } else {
hideActionBar(); hideActionBar();
@ -2297,36 +2340,46 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
*/ */
public void showActionBar() { public void showActionBar() {
if (mFullScreen) { if (mFullScreen) {
if (mToolbarLayout == null)
return;
int height = mToolbarLayout.getHeight();
if (height == 0) {
mToolbarLayout.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
height = mToolbarLayout.getMeasuredHeight();
}
if (mBrowserFrame.findViewById(R.id.toolbar_layout) == null) { if (mBrowserFrame.findViewById(R.id.toolbar_layout) == null) {
mUiLayout.removeView(mToolbarLayout); mUiLayout.removeView(mToolbarLayout);
mBrowserFrame.addView(mToolbarLayout); mBrowserFrame.addView(mToolbarLayout);
mToolbarLayout.bringToFront(); mToolbarLayout.bringToFront();
Log.d(Constants.TAG, "Move view to browser frame"); Log.d(Constants.TAG, "Move view to browser frame");
mToolbarLayout.setTranslationY(0);
mWebView.setTranslationY(height);
} }
if (mToolbarLayout.getVisibility() != View.VISIBLE) { if (mCurrentView == null)
Animation show = AnimationUtils.loadAnimation(mActivity, R.anim.slide_down); return;
show.setAnimationListener(new AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
mToolbarLayout.setVisibility(View.VISIBLE);
}
final WebView view = mWebView;
final int totalHeight = height;
if (mToolbarLayout.getTranslationY() < -(height - 0.01f)) {
Animation show = new Animation() {
@Override @Override
public void onAnimationRepeat(Animation animation) { protected void applyTransformation(float interpolatedTime, Transformation t) {
float trans = interpolatedTime * totalHeight;
mToolbarLayout.setTranslationY(trans - totalHeight);
// null pointer here on close
if (view != null)
view.setTranslationY(trans);
} }
};
}); show.setDuration(250);
mToolbarLayout.startAnimation(show); show.setInterpolator(new DecelerateInterpolator());
Log.d(Constants.TAG, "Show"); // show.setFillAfter(true);
mWebView.startAnimation(show);
} }
} }
} }
@Override @Override
@ -2337,8 +2390,8 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
*/ */
public void longClickPage(final String url) { public void longClickPage(final String url) {
HitTestResult result = null; HitTestResult result = null;
if (mCurrentView.getWebView() != null) { if (mWebView != null) {
result = mCurrentView.getWebView().getHitTestResult(); result = mWebView.getHitTestResult();
} }
if (url != null) { if (url != null) {
if (result != null) { if (result != null) {
@ -2359,7 +2412,7 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
case DialogInterface.BUTTON_NEUTRAL: case DialogInterface.BUTTON_NEUTRAL:
if (API > 8) { if (API > 8) {
Utils.downloadFile(mActivity, url, Utils.downloadFile(mActivity, url,
mCurrentView.getUserAgent(), "attachment", false); mCurrentView.getUserAgent(), "attachment");
} }
break; break;
} }
@ -2461,7 +2514,7 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
case DialogInterface.BUTTON_NEUTRAL: case DialogInterface.BUTTON_NEUTRAL:
if (API > 8) { if (API > 8) {
Utils.downloadFile(mActivity, newUrl, Utils.downloadFile(mActivity, newUrl,
mCurrentView.getUserAgent(), "attachment", false); mCurrentView.getUserAgent(), "attachment");
} }
break; break;
} }
@ -2544,7 +2597,7 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
/** /**
* handle presses on the refresh icon in the search bar, if the page is * handle presses on the refresh icon in the search bar, if the page is
* loading, stop the page, if it is done loading refresh the page. * loading, stop the page, if it is done loading refresh the page.
* * <p/>
* See setIsFinishedLoading and setIsLoading for displaying the correct icon * See setIsFinishedLoading and setIsLoading for displaying the correct icon
*/ */
private void refreshOrStop() { private void refreshOrStop() {
@ -2558,7 +2611,7 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
} }
// Override this, use finish() for Incognito, moveTaskToBack for Main // Override this, use finish() for Incognito, moveTaskToBack for Main
public void closeActivity() { void closeActivity() {
finish(); finish();
} }
@ -2606,13 +2659,13 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
newTab(null, true); newTab(null, true);
break; break;
case R.id.button_next: case R.id.button_next:
mCurrentView.getWebView().findNext(false); mWebView.findNext(false);
break; break;
case R.id.button_back: case R.id.button_back:
mCurrentView.getWebView().findNext(true); mWebView.findNext(true);
break; break;
case R.id.button_quit: case R.id.button_quit:
mCurrentView.getWebView().clearMatches(); mWebView.clearMatches();
mSearchBar.setVisibility(View.GONE); mSearchBar.setVisibility(View.GONE);
break; break;
} }

7
app/src/main/java/acr/browser/lightning/activity/IncognitoActivity.java

@ -13,8 +13,6 @@ import acr.browser.lightning.R;
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
public class IncognitoActivity extends BrowserActivity { public class IncognitoActivity extends BrowserActivity {
private CookieManager mCookieManager;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@ -22,12 +20,11 @@ public class IncognitoActivity extends BrowserActivity {
@Override @Override
public void updateCookiePreference() { public void updateCookiePreference() {
mCookieManager = CookieManager.getInstance(); CookieManager cookieManager = CookieManager.getInstance();
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
CookieSyncManager.createInstance(this); CookieSyncManager.createInstance(this);
} }
mCookieManager cookieManager.setAcceptCookie(PreferenceManager.getInstance().getIncognitoCookiesEnabled());
.setAcceptCookie(PreferenceManager.getInstance().getIncognitoCookiesEnabled());
super.updateCookiePreference(); super.updateCookiePreference();
} }

6
app/src/main/java/acr/browser/lightning/activity/MainActivity.java

@ -13,8 +13,6 @@ import acr.browser.lightning.R;
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
public class MainActivity extends BrowserActivity { public class MainActivity extends BrowserActivity {
private CookieManager mCookieManager;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@ -22,11 +20,11 @@ public class MainActivity extends BrowserActivity {
@Override @Override
public void updateCookiePreference() { public void updateCookiePreference() {
mCookieManager = CookieManager.getInstance(); CookieManager cookieManager = CookieManager.getInstance();
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
CookieSyncManager.createInstance(this); CookieSyncManager.createInstance(this);
} }
mCookieManager.setAcceptCookie(PreferenceManager.getInstance().getCookiesEnabled()); cookieManager.setAcceptCookie(PreferenceManager.getInstance().getCookiesEnabled());
super.updateCookiePreference(); super.updateCookiePreference();
} }

6
app/src/main/java/acr/browser/lightning/activity/ReadingActivity.java

@ -1,7 +1,6 @@
package acr.browser.lightning.activity; package acr.browser.lightning.activity;
import android.animation.ObjectAnimator; import android.animation.ObjectAnimator;
import android.app.AlertDialog;
import android.app.ProgressDialog; import android.app.ProgressDialog;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
@ -9,6 +8,7 @@ import android.content.DialogInterface.OnClickListener;
import android.content.Intent; import android.content.Intent;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity; import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar; import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@ -56,6 +56,7 @@ public class ReadingActivity extends AppCompatActivity {
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar); setSupportActionBar(toolbar);
if (getSupportActionBar() != null)
getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setDisplayHomeAsUpEnabled(true);
mTitle = (TextView) findViewById(R.id.textViewTitle); mTitle = (TextView) findViewById(R.id.textViewTitle);
@ -100,7 +101,7 @@ public class ReadingActivity extends AppCompatActivity {
return super.onCreateOptionsMenu(menu); return super.onCreateOptionsMenu(menu);
} }
protected boolean loadPage(Intent intent) { private boolean loadPage(Intent intent) {
if (intent == null) { if (intent == null) {
return false; return false;
} }
@ -108,6 +109,7 @@ public class ReadingActivity extends AppCompatActivity {
if (mUrl == null) { if (mUrl == null) {
return false; return false;
} }
if (getSupportActionBar() != null)
getSupportActionBar().setTitle(Utils.getDomainName(mUrl)); getSupportActionBar().setTitle(Utils.getDomainName(mUrl));
new PageLoader(this).execute(mUrl); new PageLoader(this).execute(mUrl);
return true; return true;

2
app/src/main/java/acr/browser/lightning/activity/SettingsActivity.java

@ -17,7 +17,7 @@ import acr.browser.lightning.R;
public class SettingsActivity extends ThemableSettingsActivity { public class SettingsActivity extends ThemableSettingsActivity {
private static List<String> fragments = new ArrayList<>(); private static final List<String> fragments = new ArrayList<>();
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {

4
app/src/main/java/acr/browser/lightning/activity/ThemableActivity.java

@ -33,9 +33,7 @@ public abstract class ThemableActivity extends AppCompatActivity {
} }
protected void restart() { protected void restart() {
final Bundle outState = new Bundle(); Intent intent = getIntent();
onSaveInstanceState(outState);
final Intent intent = new Intent(this, getClass());
finish(); finish();
overridePendingTransition(0, 0); overridePendingTransition(0, 0);
startActivity(intent); startActivity(intent);

9
app/src/main/java/acr/browser/lightning/activity/ThemableSettingsActivity.java

@ -6,6 +6,7 @@ import android.os.Bundle;
import acr.browser.lightning.R; import acr.browser.lightning.R;
import acr.browser.lightning.preference.PreferenceManager; import acr.browser.lightning.preference.PreferenceManager;
import acr.browser.lightning.utils.ThemeUtils;
public abstract class ThemableSettingsActivity extends AppCompatPreferenceActivity { public abstract class ThemableSettingsActivity extends AppCompatPreferenceActivity {
@ -16,11 +17,15 @@ public abstract class ThemableSettingsActivity extends AppCompatPreferenceActivi
mTheme = PreferenceManager.getInstance().getUseTheme(); mTheme = PreferenceManager.getInstance().getUseTheme();
// set the theme // set the theme
if (mTheme == 1) { if (mTheme == 0) {
setTheme(R.style.Theme_SettingsTheme);
this.getWindow().setBackgroundDrawable(new ColorDrawable(ThemeUtils.getPrimaryColor(this)));
} else if (mTheme == 1) {
setTheme(R.style.Theme_SettingsTheme_Dark); setTheme(R.style.Theme_SettingsTheme_Dark);
this.getWindow().setBackgroundDrawable(new ColorDrawable(ThemeUtils.getPrimaryColorDark(this)));
} else if (mTheme == 2) { } else if (mTheme == 2) {
setTheme(R.style.Theme_SettingsTheme_Black); setTheme(R.style.Theme_SettingsTheme_Black);
this.getWindow().setBackgroundDrawable(new ColorDrawable(this.getResources().getColor(R.color.black))); this.getWindow().setBackgroundDrawable(new ColorDrawable(ThemeUtils.getPrimaryColorDark(this)));
} }
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
} }

4
app/src/main/java/acr/browser/lightning/controller/BrowserController.java

@ -26,7 +26,7 @@ public interface BrowserController {
void onLongPress(); void onLongPress();
void onShowCustomView(View view, int requestedOrientation, CustomViewCallback callback); void onShowCustomView(View view, CustomViewCallback callback);
void onHideCustomView(); void onHideCustomView();
@ -34,7 +34,7 @@ public interface BrowserController {
View getVideoLoadingProgressView(); View getVideoLoadingProgressView();
void onCreateWindow(boolean isUserGesture, Message resultMsg); void onCreateWindow(Message resultMsg);
Activity getActivity(); Activity getActivity();

98
app/src/main/java/acr/browser/lightning/database/BookmarkManager.java

@ -55,15 +55,16 @@ public class BookmarkManager {
/** /**
* This method adds the the HistoryItem item to permanent bookmark storage * This method adds the the HistoryItem item to permanent bookmark storage
* *
* @param item * @param item the item to add
*/ */
public synchronized boolean addBookmark(HistoryItem item) { public synchronized boolean addBookmark(HistoryItem item) {
File bookmarksFile = new File(mContext.getFilesDir(), FILE_BOOKMARKS); File bookmarksFile = new File(mContext.getFilesDir(), FILE_BOOKMARKS);
if (item.getUrl() == null || mBookmarkMap.containsKey(item.getUrl())) { if (item.getUrl() == null || mBookmarkMap.containsKey(item.getUrl())) {
return false; return false;
} }
BufferedWriter bookmarkWriter = null;
try { try {
BufferedWriter bookmarkWriter = new BufferedWriter(new FileWriter(bookmarksFile, true)); bookmarkWriter = new BufferedWriter(new FileWriter(bookmarksFile, true));
JSONObject object = new JSONObject(); JSONObject object = new JSONObject();
object.put(TITLE, item.getTitle()); object.put(TITLE, item.getTitle());
object.put(URL, item.getUrl()); object.put(URL, item.getUrl());
@ -75,6 +76,8 @@ public class BookmarkManager {
mBookmarkMap.put(item.getUrl(), 1); mBookmarkMap.put(item.getUrl(), 1);
} catch (IOException | JSONException e) { } catch (IOException | JSONException e) {
e.printStackTrace(); e.printStackTrace();
} finally {
Utils.close(bookmarkWriter);
} }
return true; return true;
} }
@ -82,15 +85,16 @@ public class BookmarkManager {
/** /**
* This method adds the list of HistoryItems to permanent bookmark storage * This method adds the list of HistoryItems to permanent bookmark storage
* *
* @param list * @param list the list of HistoryItems to add to bookmarks
*/ */
public synchronized void addBookmarkList(List<HistoryItem> list) { private synchronized void addBookmarkList(List<HistoryItem> list) {
File bookmarksFile = new File(mContext.getFilesDir(), FILE_BOOKMARKS); File bookmarksFile = new File(mContext.getFilesDir(), FILE_BOOKMARKS);
BufferedWriter bookmarkWriter = null;
try { try {
BufferedWriter bookmarkWriter = new BufferedWriter(new FileWriter(bookmarksFile, true)); bookmarkWriter = new BufferedWriter(new FileWriter(bookmarksFile, true));
JSONObject object = new JSONObject();
for (HistoryItem item : list) { for (HistoryItem item : list) {
if (item.getUrl() != null && !mBookmarkMap.containsKey(item.getUrl())) { if (item.getUrl() != null && !mBookmarkMap.containsKey(item.getUrl())) {
JSONObject object = new JSONObject();
object.put(TITLE, item.getTitle()); object.put(TITLE, item.getTitle());
object.put(URL, item.getUrl()); object.put(URL, item.getUrl());
object.put(FOLDER, item.getFolder()); object.put(FOLDER, item.getFolder());
@ -100,16 +104,17 @@ public class BookmarkManager {
mBookmarkMap.put(item.getUrl(), 1); mBookmarkMap.put(item.getUrl(), 1);
} }
} }
bookmarkWriter.close();
} catch (IOException | JSONException e) { } catch (IOException | JSONException e) {
e.printStackTrace(); e.printStackTrace();
} finally {
Utils.close(bookmarkWriter);
} }
} }
/** /**
* This method deletes the bookmark with the given url * This method deletes the bookmark with the given url
* *
* @param url * @param url the url of the bookmark to delete
*/ */
public synchronized boolean deleteBookmark(String url) { public synchronized boolean deleteBookmark(String url) {
List<HistoryItem> list; List<HistoryItem> list;
@ -120,11 +125,12 @@ public class BookmarkManager {
list = getBookmarks(false); list = getBookmarks(false);
File bookmarksFile = new File(mContext.getFilesDir(), FILE_BOOKMARKS); File bookmarksFile = new File(mContext.getFilesDir(), FILE_BOOKMARKS);
boolean bookmarkDeleted = false; boolean bookmarkDeleted = false;
BufferedWriter fileWriter = null;
try { try {
BufferedWriter fileWriter = new BufferedWriter(new FileWriter(bookmarksFile, false)); fileWriter = new BufferedWriter(new FileWriter(bookmarksFile, false));
JSONObject object = new JSONObject();
for (HistoryItem item : list) { for (HistoryItem item : list) {
if (!item.getUrl().equalsIgnoreCase(url)) { if (!item.getUrl().equalsIgnoreCase(url)) {
JSONObject object = new JSONObject();
object.put(TITLE, item.getTitle()); object.put(TITLE, item.getTitle());
object.put(URL, item.getUrl()); object.put(URL, item.getUrl());
object.put(FOLDER, item.getFolder()); object.put(FOLDER, item.getFolder());
@ -135,9 +141,10 @@ public class BookmarkManager {
bookmarkDeleted = true; bookmarkDeleted = true;
} }
} }
fileWriter.close();
} catch (IOException | JSONException e) { } catch (IOException | JSONException e) {
e.printStackTrace(); e.printStackTrace();
} finally {
Utils.close(fileWriter);
} }
return bookmarkDeleted; return bookmarkDeleted;
} }
@ -158,11 +165,12 @@ public class BookmarkManager {
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),
"BookmarksExport-" + counter + ".txt"); "BookmarksExport-" + counter + ".txt");
} }
BufferedWriter bookmarkWriter = null;
try { try {
BufferedWriter bookmarkWriter = new BufferedWriter(new FileWriter(bookmarksExport, bookmarkWriter = new BufferedWriter(new FileWriter(bookmarksExport,
false)); false));
for (HistoryItem item : bookmarkList) {
JSONObject object = new JSONObject(); JSONObject object = new JSONObject();
for (HistoryItem item : bookmarkList) {
object.put(TITLE, item.getTitle()); object.put(TITLE, item.getTitle());
object.put(URL, item.getUrl()); object.put(URL, item.getUrl());
object.put(FOLDER, item.getFolder()); object.put(FOLDER, item.getFolder());
@ -170,13 +178,15 @@ public class BookmarkManager {
bookmarkWriter.write(object.toString()); bookmarkWriter.write(object.toString());
bookmarkWriter.newLine(); bookmarkWriter.newLine();
} }
bookmarkWriter.close(); if (mContext != null)
Toast.makeText( Toast.makeText(
mContext, mContext,
mContext.getString(R.string.bookmark_export_path) + " " mContext.getString(R.string.bookmark_export_path) + ' '
+ bookmarksExport.getPath(), Toast.LENGTH_SHORT).show(); + bookmarksExport.getPath(), Toast.LENGTH_SHORT).show();
} catch (IOException | JSONException e) { } catch (IOException | JSONException e) {
e.printStackTrace(); e.printStackTrace();
} finally {
Utils.close(bookmarkWriter);
} }
} }
@ -184,13 +194,14 @@ public class BookmarkManager {
/** /**
* This method returns a list of all stored bookmarks * This method returns a list of all stored bookmarks
* *
* @return * @return returns a list of bookmarks that can be sorted
*/ */
public synchronized List<HistoryItem> getBookmarks(boolean sort) { public synchronized List<HistoryItem> getBookmarks(boolean sort) {
List<HistoryItem> bookmarks = new ArrayList<>(); List<HistoryItem> bookmarks = new ArrayList<>();
File bookmarksFile = new File(mContext.getFilesDir(), FILE_BOOKMARKS); File bookmarksFile = new File(mContext.getFilesDir(), FILE_BOOKMARKS);
BufferedReader bookmarksReader = null;
try { try {
BufferedReader bookmarksReader = new BufferedReader(new FileReader(bookmarksFile)); bookmarksReader = new BufferedReader(new FileReader(bookmarksFile));
String line; String line;
while ((line = bookmarksReader.readLine()) != null) { while ((line = bookmarksReader.readLine()) != null) {
JSONObject object = new JSONObject(line); JSONObject object = new JSONObject(line);
@ -202,9 +213,10 @@ public class BookmarkManager {
item.setImageId(R.drawable.ic_bookmark); item.setImageId(R.drawable.ic_bookmark);
bookmarks.add(item); bookmarks.add(item);
} }
bookmarksReader.close();
} catch (IOException | JSONException e) { } catch (IOException | JSONException e) {
e.printStackTrace(); e.printStackTrace();
} finally {
Utils.close(bookmarksReader);
} }
if (sort) { if (sort) {
Collections.sort(bookmarks, new SortIgnoreCase()); Collections.sort(bookmarks, new SortIgnoreCase());
@ -215,14 +227,15 @@ public class BookmarkManager {
/** /**
* This method returns a list of bookmarks located in the specified folder * This method returns a list of bookmarks located in the specified folder
* *
* @param folder * @param folder the name of the folder to retrieve bookmarks from
* @return * @return a list of bookmarks found in that folder
*/ */
public synchronized List<HistoryItem> getBookmarksFromFolder(String folder) { public synchronized List<HistoryItem> getBookmarksFromFolder(String folder) {
List<HistoryItem> bookmarks = new ArrayList<>(); List<HistoryItem> bookmarks = new ArrayList<>();
File bookmarksFile = new File(mContext.getFilesDir(), FILE_BOOKMARKS); File bookmarksFile = new File(mContext.getFilesDir(), FILE_BOOKMARKS);
BufferedReader bookmarksReader = null;
try { try {
BufferedReader bookmarksReader = new BufferedReader(new FileReader(bookmarksFile)); bookmarksReader = new BufferedReader(new FileReader(bookmarksFile));
String line; String line;
while ((line = bookmarksReader.readLine()) != null) { while ((line = bookmarksReader.readLine()) != null) {
JSONObject object = new JSONObject(line); JSONObject object = new JSONObject(line);
@ -239,6 +252,8 @@ public class BookmarkManager {
bookmarksReader.close(); bookmarksReader.close();
} catch (IOException | JSONException e) { } catch (IOException | JSONException e) {
e.printStackTrace(); e.printStackTrace();
} finally {
Utils.close(bookmarksReader);
} }
return bookmarks; return bookmarks;
} }
@ -246,13 +261,14 @@ public class BookmarkManager {
/** /**
* Method is used internally for searching the bookmarks * Method is used internally for searching the bookmarks
* *
* @return * @return a sorted map of all bookmarks, useful for seeing if a bookmark exists
*/ */
private synchronized SortedMap<String, Integer> getBookmarkUrls() { private synchronized SortedMap<String, Integer> getBookmarkUrls() {
SortedMap<String, Integer> map = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); SortedMap<String, Integer> map = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
File bookmarksFile = new File(mContext.getFilesDir(), FILE_BOOKMARKS); File bookmarksFile = new File(mContext.getFilesDir(), FILE_BOOKMARKS);
BufferedReader bookmarksReader = null;
try { try {
BufferedReader bookmarksReader = new BufferedReader(new FileReader(bookmarksFile)); bookmarksReader = new BufferedReader(new FileReader(bookmarksFile));
String line; String line;
while ((line = bookmarksReader.readLine()) != null) { while ((line = bookmarksReader.readLine()) != null) {
JSONObject object = new JSONObject(line); JSONObject object = new JSONObject(line);
@ -261,6 +277,8 @@ public class BookmarkManager {
bookmarksReader.close(); bookmarksReader.close();
} catch (JSONException | IOException e) { } catch (JSONException | IOException e) {
e.printStackTrace(); e.printStackTrace();
} finally {
Utils.close(bookmarksReader);
} }
return map; return map;
} }
@ -268,15 +286,16 @@ public class BookmarkManager {
/** /**
* This method returns a list of all folders * This method returns a list of all folders
* *
* @return * @return a list of all folders
*/ */
public synchronized List<HistoryItem> getFolders() { public synchronized List<HistoryItem> getFolders() {
List<HistoryItem> folders = new ArrayList<>(); List<HistoryItem> folders = new ArrayList<>();
SortedMap<String, Integer> folderMap = new TreeMap<>( SortedMap<String, Integer> folderMap = new TreeMap<>(
String.CASE_INSENSITIVE_ORDER); String.CASE_INSENSITIVE_ORDER);
File bookmarksFile = new File(mContext.getFilesDir(), FILE_BOOKMARKS); File bookmarksFile = new File(mContext.getFilesDir(), FILE_BOOKMARKS);
BufferedReader bookmarksReader = null;
try { try {
BufferedReader bookmarksReader = new BufferedReader(new FileReader(bookmarksFile)); bookmarksReader = new BufferedReader(new FileReader(bookmarksFile));
String line; String line;
while ((line = bookmarksReader.readLine()) != null) { while ((line = bookmarksReader.readLine()) != null) {
JSONObject object = new JSONObject(line); JSONObject object = new JSONObject(line);
@ -289,9 +308,10 @@ public class BookmarkManager {
folders.add(item); folders.add(item);
} }
} }
bookmarksReader.close();
} catch (IOException | JSONException e) { } catch (IOException | JSONException e) {
e.printStackTrace(); e.printStackTrace();
} finally {
Utils.close(bookmarksReader);
} }
return folders; return folders;
} }
@ -309,7 +329,8 @@ public class BookmarkManager {
String selection = Browser.BookmarkColumns.BOOKMARK + " = 1"; String selection = Browser.BookmarkColumns.BOOKMARK + " = 1";
Cursor cursor = mContext.getContentResolver().query(Browser.BOOKMARKS_URI, columns, Cursor cursor = mContext.getContentResolver().query(Browser.BOOKMARKS_URI, columns,
selection, null, null); selection, null, null);
if (cursor == null)
return;
String title, url; String title, url;
int number = 0; int number = 0;
if (cursor.moveToFirst()) { if (cursor.moveToFirst()) {
@ -327,7 +348,7 @@ public class BookmarkManager {
cursor.close(); cursor.close();
addBookmarkList(bookmarkList); addBookmarkList(bookmarkList);
Utils.showToast(mContext, Utils.showToast(context,
number + " " + mContext.getResources().getString(R.string.message_import)); number + " " + mContext.getResources().getString(R.string.message_import));
} else { } else {
Utils.createInformativeDialog(context, Utils.createInformativeDialog(context,
@ -340,16 +361,16 @@ public class BookmarkManager {
* This method imports the bookmarks from a backup file that is located on * This method imports the bookmarks from a backup file that is located on
* external storage * external storage
* *
* @param dir * @param file the file to attempt to import bookmarks from
* @param file
*/ */
public synchronized void importBookmarksFromFile(File file, Context context) { public synchronized void importBookmarksFromFile(File file, Context context) {
if (file == null) { if (file == null) {
return; return;
} }
List<HistoryItem> list = new ArrayList<>(); List<HistoryItem> list = new ArrayList<>();
BufferedReader bookmarksReader = null;
try { try {
BufferedReader bookmarksReader = new BufferedReader(new FileReader(file)); bookmarksReader = new BufferedReader(new FileReader(file));
String line; String line;
int number = 0; int number = 0;
while ((line = bookmarksReader.readLine()) != null) { while ((line = bookmarksReader.readLine()) != null) {
@ -362,15 +383,16 @@ public class BookmarkManager {
list.add(item); list.add(item);
number++; number++;
} }
bookmarksReader.close();
addBookmarkList(list); addBookmarkList(list);
Utils.showToast(mContext, Utils.showToast(context,
number + " " + mContext.getResources().getString(R.string.message_import)); number + " " + mContext.getResources().getString(R.string.message_import));
} catch (IOException | JSONException e) { } catch (IOException | JSONException e) {
e.printStackTrace(); e.printStackTrace();
Utils.createInformativeDialog(context, Utils.createInformativeDialog(context,
mContext.getResources().getString(R.string.title_error), mContext mContext.getResources().getString(R.string.title_error), mContext
.getResources().getString(R.string.import_bookmark_error)); .getResources().getString(R.string.import_bookmark_error));
} finally {
Utils.close(bookmarksReader);
} }
} }
@ -379,14 +401,15 @@ public class BookmarkManager {
* bookmarks. This is useful when an edit has been made to one or more * bookmarks. This is useful when an edit has been made to one or more
* bookmarks in the list * bookmarks in the list
* *
* @param list * @param list the list of bookmarks to overwrite the old ones with
*/ */
public synchronized void overwriteBookmarks(List<HistoryItem> list) { public synchronized void overwriteBookmarks(List<HistoryItem> list) {
File bookmarksFile = new File(mContext.getFilesDir(), FILE_BOOKMARKS); File bookmarksFile = new File(mContext.getFilesDir(), FILE_BOOKMARKS);
BufferedWriter bookmarkWriter = null;
try { try {
BufferedWriter bookmarkWriter = new BufferedWriter(new FileWriter(bookmarksFile, false)); bookmarkWriter = new BufferedWriter(new FileWriter(bookmarksFile, false));
for (HistoryItem item : list) {
JSONObject object = new JSONObject(); JSONObject object = new JSONObject();
for (HistoryItem item : list) {
object.put(TITLE, item.getTitle()); object.put(TITLE, item.getTitle());
object.put(URL, item.getUrl()); object.put(URL, item.getUrl());
object.put(FOLDER, item.getFolder()); object.put(FOLDER, item.getFolder());
@ -394,9 +417,10 @@ public class BookmarkManager {
bookmarkWriter.write(object.toString()); bookmarkWriter.write(object.toString());
bookmarkWriter.newLine(); bookmarkWriter.newLine();
} }
bookmarkWriter.close();
} catch (IOException | JSONException e) { } catch (IOException | JSONException e) {
e.printStackTrace(); e.printStackTrace();
} finally {
Utils.close(bookmarkWriter);
} }
} }

4
app/src/main/java/acr/browser/lightning/database/HistoryDatabase.java

@ -65,7 +65,7 @@ public class HistoryDatabase extends SQLiteOpenHelper {
onCreate(db); onCreate(db);
} }
public boolean isClosed() { private boolean isClosed() {
return mDatabase == null || !mDatabase.isOpen(); return mDatabase == null || !mDatabase.isOpen();
} }
@ -95,7 +95,7 @@ public class HistoryDatabase extends SQLiteOpenHelper {
q.close(); q.close();
} }
public synchronized void addHistoryItem(HistoryItem item) { private synchronized void addHistoryItem(HistoryItem item) {
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();
values.put(KEY_URL, item.getUrl()); values.put(KEY_URL, item.getUrl());
values.put(KEY_TITLE, item.getTitle()); values.put(KEY_TITLE, item.getTitle());

53
app/src/main/java/acr/browser/lightning/download/DownloadHandler.java

@ -4,7 +4,6 @@
package acr.browser.lightning.download; package acr.browser.lightning.download;
import android.app.Activity; import android.app.Activity;
import android.app.AlertDialog;
import android.app.DownloadManager; import android.app.DownloadManager;
import android.content.ActivityNotFoundException; import android.content.ActivityNotFoundException;
import android.content.ComponentName; import android.content.ComponentName;
@ -14,6 +13,7 @@ import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo; import android.content.pm.ResolveInfo;
import android.net.Uri; import android.net.Uri;
import android.os.Environment; import android.os.Environment;
import android.support.v7.app.AlertDialog;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import android.webkit.CookieManager; import android.webkit.CookieManager;
@ -22,6 +22,7 @@ import android.widget.Toast;
import acr.browser.lightning.R; import acr.browser.lightning.R;
import acr.browser.lightning.preference.PreferenceManager; import acr.browser.lightning.preference.PreferenceManager;
import acr.browser.lightning.utils.Utils;
/** /**
* Handle download requests * Handle download requests
@ -35,21 +36,14 @@ public class DownloadHandler {
* Notify the host application a download should be done, or that the data * Notify the host application a download should be done, or that the data
* should be streamed if a streaming viewer is available. * should be streamed if a streaming viewer is available.
* *
* @param activity * @param activity Activity requesting the download.
* Activity requesting the download. * @param url The full url to the content that should be downloaded
* @param url * @param userAgent User agent of the downloading application.
* The full url to the content that should be downloaded * @param contentDisposition Content-disposition http header, if present.
* @param userAgent * @param mimetype The mimetype of the content reported by the server
* 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 privateBrowsing
* If the request is coming from a private browsing tab.
*/ */
public static void onDownloadStart(Activity activity, String url, String userAgent, public static void onDownloadStart(Activity activity, String url, String userAgent,
String contentDisposition, String mimetype, boolean privateBrowsing) { String contentDisposition, String mimetype) {
// if we're dealing wih A/V content that's not explicitly marked // if we're dealing wih A/V content that's not explicitly marked
// for download, check if it's streamable. // for download, check if it's streamable.
if (contentDisposition == null if (contentDisposition == null
@ -79,8 +73,8 @@ public class DownloadHandler {
} }
} }
} }
onDownloadStartNoStream(activity, url, userAgent, contentDisposition, mimetype, onDownloadStartNoStream(activity, url, userAgent, contentDisposition, mimetype
privateBrowsing); );
} }
// This is to work around the fact that java.net.URI throws Exceptions // This is to work around the fact that java.net.URI throws Exceptions
@ -117,22 +111,15 @@ public class DownloadHandler {
* Notify the host application a download should be done, even if there is a * Notify the host application a download should be done, even if there is a
* streaming viewer available for thise type. * streaming viewer available for thise type.
* *
* @param activity * @param activity Activity requesting the download.
* Activity requesting the download. * @param url The full url to the content that should be downloaded
* @param url * @param userAgent User agent of the downloading application.
* The full url to the content that should be downloaded * @param contentDisposition Content-disposition http header, if present.
* @param userAgent * @param mimetype The mimetype of the content reported by the server
* 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 privateBrowsing
* If the request is coming from a private browsing tab.
*/ */
/* package */ /* package */
private static void onDownloadStartNoStream(Activity activity, String url, String userAgent, private static void onDownloadStartNoStream(final Activity activity, String url, String userAgent,
String contentDisposition, String mimetype, boolean privateBrowsing) { String contentDisposition, String mimetype) {
String filename = URLUtil.guessFileName(url, contentDisposition, mimetype); String filename = URLUtil.guessFileName(url, contentDisposition, mimetype);
@ -208,7 +195,13 @@ public class DownloadHandler {
new Thread("Browser download") { new Thread("Browser download") {
@Override @Override
public void run() { public void run() {
try {
manager.enqueue(request); manager.enqueue(request);
} catch (IllegalArgumentException e) {
// Probably got a bad URL or something
e.printStackTrace();
Utils.showToast(activity, R.string.cannot_download);
}
} }
}.start(); }.start();
Toast.makeText(activity, R.string.download_pending, Toast.LENGTH_SHORT).show(); Toast.makeText(activity, R.string.download_pending, Toast.LENGTH_SHORT).show();

5
app/src/main/java/acr/browser/lightning/download/LightningDownloadListener.java

@ -4,15 +4,14 @@
package acr.browser.lightning.download; package acr.browser.lightning.download;
import android.app.Activity; import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.support.v7.app.AlertDialog;
import android.util.Log; import android.util.Log;
import android.webkit.DownloadListener; import android.webkit.DownloadListener;
import android.webkit.URLUtil; import android.webkit.URLUtil;
import acr.browser.lightning.R; import acr.browser.lightning.R;
import acr.browser.lightning.constant.Constants; import acr.browser.lightning.constant.Constants;
import acr.browser.lightning.download.DownloadHandler;
public class LightningDownloadListener implements DownloadListener { public class LightningDownloadListener implements DownloadListener {
@ -32,7 +31,7 @@ public class LightningDownloadListener implements DownloadListener {
switch (which) { switch (which) {
case DialogInterface.BUTTON_POSITIVE: case DialogInterface.BUTTON_POSITIVE:
DownloadHandler.onDownloadStart(mActivity, url, userAgent, DownloadHandler.onDownloadStart(mActivity, url, userAgent,
contentDisposition, mimetype, false); contentDisposition, mimetype);
break; break;
case DialogInterface.BUTTON_NEGATIVE: case DialogInterface.BUTTON_NEGATIVE:

2
app/src/main/java/acr/browser/lightning/fragment/AdvancedSettingsFragment.java

@ -4,12 +4,12 @@
package acr.browser.lightning.fragment; package acr.browser.lightning.fragment;
import android.app.Activity; import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.os.Bundle; import android.os.Bundle;
import android.preference.CheckBoxPreference; import android.preference.CheckBoxPreference;
import android.preference.Preference; import android.preference.Preference;
import android.preference.PreferenceFragment; import android.preference.PreferenceFragment;
import android.support.v7.app.AlertDialog;
import acr.browser.lightning.R; import acr.browser.lightning.R;
import acr.browser.lightning.preference.PreferenceManager; import acr.browser.lightning.preference.PreferenceManager;

32
app/src/main/java/acr/browser/lightning/fragment/BookmarkSettingsFragment.java

@ -4,13 +4,12 @@
package acr.browser.lightning.fragment; package acr.browser.lightning.fragment;
import android.app.Activity; import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.os.Bundle; import android.os.Bundle;
import android.os.Environment; import android.os.Environment;
import android.preference.Preference; import android.preference.Preference;
import android.preference.PreferenceFragment; import android.preference.PreferenceFragment;
import android.support.v7.app.AlertDialog;
import java.io.File; import java.io.File;
import java.util.Arrays; import java.util.Arrays;
@ -27,12 +26,10 @@ public class BookmarkSettingsFragment extends PreferenceFragment implements Pref
private static final String SETTINGS_BROWSER_IMPORT = "import_browser_bookmark"; private static final String SETTINGS_BROWSER_IMPORT = "import_browser_bookmark";
private Activity mActivity; private Activity mActivity;
private PreferenceManager mPreferences;
private BookmarkManager mBookmarkManager; private BookmarkManager mBookmarkManager;
private File[] mFileList; private File[] mFileList;
private String[] mFileNameList; private String[] mFileNameList;
private static final File mPath = new File(Environment.getExternalStorageDirectory().toString()); private static final File mPath = new File(Environment.getExternalStorageDirectory().toString());
private static final int DIALOG_LOAD_FILE = 1000;
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
@ -42,14 +39,14 @@ public class BookmarkSettingsFragment extends PreferenceFragment implements Pref
mActivity = getActivity(); mActivity = getActivity();
mBookmarkManager = BookmarkManager.getInstance(mActivity); mBookmarkManager = BookmarkManager.getInstance(mActivity.getApplicationContext());
initPrefs(); initPrefs();
} }
private void initPrefs() { private void initPrefs() {
// mPreferences storage // mPreferences storage
mPreferences = PreferenceManager.getInstance(); PreferenceManager mPreferences = PreferenceManager.getInstance();
Preference exportpref = findPreference(SETTINGS_EXPORT); Preference exportpref = findPreference(SETTINGS_EXPORT);
Preference importpref = findPreference(SETTINGS_IMPORT); Preference importpref = findPreference(SETTINGS_IMPORT);
@ -74,10 +71,10 @@ public class BookmarkSettingsFragment extends PreferenceFragment implements Pref
return true; return true;
case SETTINGS_IMPORT: case SETTINGS_IMPORT:
loadFileList(null); loadFileList(null);
onCreateDialog(DIALOG_LOAD_FILE); createDialog();
return true; return true;
case SETTINGS_BROWSER_IMPORT: case SETTINGS_BROWSER_IMPORT:
mBookmarkManager.importBookmarksFromBrowser(mActivity); mBookmarkManager.importBookmarksFromBrowser(getActivity());
return true; return true;
default: default:
return false; return false;
@ -135,34 +132,29 @@ public class BookmarkSettingsFragment extends PreferenceFragment implements Pref
} }
} }
protected Dialog onCreateDialog(int id) { protected void createDialog() {
Dialog dialog;
final AlertDialog.Builder builder = new AlertDialog.Builder(mActivity); final AlertDialog.Builder builder = new AlertDialog.Builder(mActivity);
switch (id) { final String title = getString(R.string.title_chooser);
case DIALOG_LOAD_FILE: builder.setTitle(title + ": " + Environment.getExternalStorageDirectory());
builder.setTitle(R.string.title_chooser);
if (mFileList == null) { if (mFileList == null) {
dialog = builder.create(); builder.show();
return dialog;
} }
builder.setItems(mFileNameList, new DialogInterface.OnClickListener() { builder.setItems(mFileNameList, new DialogInterface.OnClickListener() {
@Override @Override
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
if (mFileList[which].isDirectory()) { if (mFileList[which].isDirectory()) {
builder.setTitle(title + ": " + mFileList[which]);
loadFileList(mFileList[which]); loadFileList(mFileList[which]);
builder.setItems(mFileNameList, this); builder.setItems(mFileNameList, this);
builder.show(); builder.show();
} else { } else {
mBookmarkManager.importBookmarksFromFile(mFileList[which], mActivity); mBookmarkManager.importBookmarksFromFile(mFileList[which], getActivity());
} }
} }
}); });
break; builder.show();
}
dialog = builder.show();
return dialog;
} }
} }

13
app/src/main/java/acr/browser/lightning/fragment/DisplaySettingsFragment.java

@ -4,15 +4,14 @@
package acr.browser.lightning.fragment; package acr.browser.lightning.fragment;
import android.app.Activity; import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.os.Bundle; import android.os.Bundle;
import android.preference.CheckBoxPreference; import android.preference.CheckBoxPreference;
import android.preference.Preference; import android.preference.Preference;
import android.preference.PreferenceFragment; import android.preference.PreferenceFragment;
import android.support.v7.app.AlertDialog;
import acr.browser.lightning.R; import acr.browser.lightning.R;
import acr.browser.lightning.activity.SettingsActivity;
import acr.browser.lightning.preference.PreferenceManager; import acr.browser.lightning.preference.PreferenceManager;
public class DisplaySettingsFragment extends PreferenceFragment implements Preference.OnPreferenceClickListener, Preference.OnPreferenceChangeListener { public class DisplaySettingsFragment extends PreferenceFragment implements Preference.OnPreferenceClickListener, Preference.OnPreferenceChangeListener {
@ -28,7 +27,7 @@ public class DisplaySettingsFragment extends PreferenceFragment implements Prefe
private Activity mActivity; private Activity mActivity;
private PreferenceManager mPreferences; private PreferenceManager mPreferences;
private CheckBoxPreference cbstatus, cbfullscreen, cbviewport, cboverview, cbreflow; private CheckBoxPreference cbstatus, cbfullscreen, cbviewport, cboverview, cbreflow;
private Preference theme, textsize; private Preference theme;
private String[] mThemeOptions; private String[] mThemeOptions;
private int mCurrentTheme; private int mCurrentTheme;
@ -50,7 +49,7 @@ public class DisplaySettingsFragment extends PreferenceFragment implements Prefe
mCurrentTheme = mPreferences.getUseTheme(); mCurrentTheme = mPreferences.getUseTheme();
theme = findPreference(SETTINGS_THEME); theme = findPreference(SETTINGS_THEME);
textsize = findPreference(SETTINGS_TEXTSIZE); Preference textsize = findPreference(SETTINGS_TEXTSIZE);
cbstatus = (CheckBoxPreference) findPreference(SETTINGS_HIDESTATUSBAR); cbstatus = (CheckBoxPreference) findPreference(SETTINGS_HIDESTATUSBAR);
cbfullscreen = (CheckBoxPreference) findPreference(SETTINGS_FULLSCREEN); cbfullscreen = (CheckBoxPreference) findPreference(SETTINGS_FULLSCREEN);
cbviewport = (CheckBoxPreference) findPreference(SETTINGS_VIEWPORT); cbviewport = (CheckBoxPreference) findPreference(SETTINGS_VIEWPORT);
@ -163,7 +162,8 @@ public class DisplaySettingsFragment extends PreferenceFragment implements Prefe
@Override @Override
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
if (mCurrentTheme != mPreferences.getUseTheme()) { if (mCurrentTheme != mPreferences.getUseTheme()) {
((SettingsActivity) getActivity()).restart(); // ((SettingsActivity) getActivity()).restart();
getActivity().onBackPressed();
} }
} }
}); });
@ -171,7 +171,8 @@ public class DisplaySettingsFragment extends PreferenceFragment implements Prefe
@Override @Override
public void onCancel(DialogInterface dialog) { public void onCancel(DialogInterface dialog) {
if (mCurrentTheme != mPreferences.getUseTheme()) { if (mCurrentTheme != mPreferences.getUseTheme()) {
((SettingsActivity) getActivity()).restart(); // ((SettingsActivity) getActivity()).restart();
getActivity().onBackPressed();
} }
} }
}); });

14
app/src/main/java/acr/browser/lightning/fragment/GeneralSettingsFragment.java

@ -4,14 +4,16 @@
package acr.browser.lightning.fragment; package acr.browser.lightning.fragment;
import android.app.Activity; import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.Environment; import android.os.Environment;
import android.preference.CheckBoxPreference; import android.preference.CheckBoxPreference;
import android.preference.Preference; import android.preference.Preference;
import android.preference.PreferenceFragment; import android.preference.PreferenceFragment;
import android.support.v7.app.AlertDialog;
import android.util.Log; import android.util.Log;
import android.util.TypedValue; import android.util.TypedValue;
import android.view.View; import android.view.View;
@ -468,10 +470,16 @@ public class GeneralSettingsFragment extends PreferenceFragment implements Prefe
v.setPadding(padding, padding, 0, padding); v.setPadding(padding, padding, 0, padding);
layout.addView(v); layout.addView(v);
layout.addView(getDownload); layout.addView(getDownload);
if (API < 16) { if (API < Build.VERSION_CODES.JELLY_BEAN) {
layout.setBackgroundDrawable(getResources().getDrawable(android.R.drawable.edit_text)); layout.setBackgroundDrawable(getResources().getDrawable(android.R.drawable.edit_text));
} else { } else {
layout.setBackground(getResources().getDrawable(android.R.drawable.edit_text)); Drawable drawable;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
drawable = getResources().getDrawable(android.R.drawable.edit_text, getActivity().getTheme());
} else {
drawable = getResources().getDrawable(android.R.drawable.edit_text);
}
layout.setBackground(drawable);
} }
downLocationPicker.setView(layout); downLocationPicker.setView(layout);
downLocationPicker.setPositiveButton(getResources().getString(R.string.action_ok), downLocationPicker.setPositiveButton(getResources().getString(R.string.action_ok),

9
app/src/main/java/acr/browser/lightning/fragment/PrivacySettingsFragment.java

@ -4,7 +4,6 @@
package acr.browser.lightning.fragment; package acr.browser.lightning.fragment;
import android.app.Activity; import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.os.Build; import android.os.Build;
@ -15,6 +14,7 @@ import android.preference.CheckBoxPreference;
import android.preference.Preference; import android.preference.Preference;
import android.preference.PreferenceFragment; import android.preference.PreferenceFragment;
import android.provider.Browser; import android.provider.Browser;
import android.support.v7.app.AlertDialog;
import android.webkit.CookieManager; import android.webkit.CookieManager;
import android.webkit.CookieSyncManager; import android.webkit.CookieSyncManager;
import android.webkit.WebIconDatabase; import android.webkit.WebIconDatabase;
@ -45,7 +45,6 @@ public class PrivacySettingsFragment extends PreferenceFragment implements Prefe
private PreferenceManager mPreferences; private PreferenceManager mPreferences;
private CheckBoxPreference cblocation, cb3cookies, cbsavepasswords, cbcacheexit, cbhistoryexit, private CheckBoxPreference cblocation, cb3cookies, cbsavepasswords, cbcacheexit, cbhistoryexit,
cbcookiesexit, cbsynchistory; cbcookiesexit, cbsynchistory;
private Preference clearcache, clearhistory, clearcookies;
private boolean mSystemBrowser; private boolean mSystemBrowser;
private Handler messageHandler; private Handler messageHandler;
@ -65,9 +64,9 @@ public class PrivacySettingsFragment extends PreferenceFragment implements Prefe
mPreferences = PreferenceManager.getInstance(); mPreferences = PreferenceManager.getInstance();
mSystemBrowser = mPreferences.getSystemBrowserPresent(); mSystemBrowser = mPreferences.getSystemBrowserPresent();
clearcache = findPreference(SETTINGS_CLEARCACHE); Preference clearcache = findPreference(SETTINGS_CLEARCACHE);
clearhistory = findPreference(SETTINGS_CLEARHISTORY); Preference clearhistory = findPreference(SETTINGS_CLEARHISTORY);
clearcookies = findPreference(SETTINGS_CLEARCOOKIES); Preference clearcookies = findPreference(SETTINGS_CLEARCOOKIES);
cblocation = (CheckBoxPreference) findPreference(SETTINGS_LOCATION); cblocation = (CheckBoxPreference) findPreference(SETTINGS_LOCATION);
cb3cookies = (CheckBoxPreference) findPreference(SETTINGS_THIRDPCOOKIES); cb3cookies = (CheckBoxPreference) findPreference(SETTINGS_THIRDPCOOKIES);
cbsavepasswords = (CheckBoxPreference) findPreference(SETTINGS_SAVEPASSWORD); cbsavepasswords = (CheckBoxPreference) findPreference(SETTINGS_SAVEPASSWORD);

121
app/src/main/java/acr/browser/lightning/object/SearchAdapter.java

@ -1,23 +1,5 @@
package acr.browser.lightning.object; package acr.browser.lightning.object;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.app.Activity; import android.app.Activity;
import android.content.Context; import android.content.Context;
@ -36,19 +18,37 @@ import android.widget.Filterable;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import acr.browser.lightning.R; import acr.browser.lightning.R;
import acr.browser.lightning.database.BookmarkManager; import acr.browser.lightning.database.BookmarkManager;
import acr.browser.lightning.database.HistoryDatabase; import acr.browser.lightning.database.HistoryDatabase;
import acr.browser.lightning.database.HistoryItem; import acr.browser.lightning.database.HistoryItem;
import acr.browser.lightning.preference.PreferenceManager; import acr.browser.lightning.preference.PreferenceManager;
import acr.browser.lightning.utils.Utils;
public class SearchAdapter extends BaseAdapter implements Filterable { public class SearchAdapter extends BaseAdapter implements Filterable {
private List<HistoryItem> mHistory; private final List<HistoryItem> mHistory = new ArrayList<>();
private List<HistoryItem> mBookmarks; private final List<HistoryItem> mBookmarks = new ArrayList<>();
private List<HistoryItem> mSuggestions; private final List<HistoryItem> mSuggestions = new ArrayList<>();
private List<HistoryItem> mFilteredList; private final List<HistoryItem> mFilteredList = new ArrayList<>();
private List<HistoryItem> mAllBookmarks; private final List<HistoryItem> mAllBookmarks = new ArrayList<>();
private HistoryDatabase mDatabaseHandler; private HistoryDatabase mDatabaseHandler;
private final Context mContext; private final Context mContext;
private boolean mUseGoogle = true; private boolean mUseGoogle = true;
@ -66,12 +66,8 @@ public class SearchAdapter extends BaseAdapter implements Filterable {
public SearchAdapter(Context context, boolean dark, boolean incognito) { public SearchAdapter(Context context, boolean dark, boolean incognito) {
mDatabaseHandler = HistoryDatabase.getInstance(context.getApplicationContext()); mDatabaseHandler = HistoryDatabase.getInstance(context.getApplicationContext());
mTheme = context.getTheme(); mTheme = context.getTheme();
mFilteredList = new ArrayList<>();
mHistory = new ArrayList<>();
mBookmarks = new ArrayList<>();
mSuggestions = new ArrayList<>();
mBookmarkManager = BookmarkManager.getInstance(context.getApplicationContext()); mBookmarkManager = BookmarkManager.getInstance(context.getApplicationContext());
mAllBookmarks = mBookmarkManager.getBookmarks(true); mAllBookmarks.addAll(mBookmarkManager.getBookmarks(true));
mUseGoogle = PreferenceManager.getInstance().getGoogleSearchSuggestionsEnabled(); mUseGoogle = PreferenceManager.getInstance().getGoogleSearchSuggestionsEnabled();
mContext = context; mContext = context;
mSearchSubtitle = mContext.getString(R.string.suggestion); mSearchSubtitle = mContext.getString(R.string.suggestion);
@ -113,23 +109,20 @@ public class SearchAdapter extends BaseAdapter implements Filterable {
public void refreshPreferences() { public void refreshPreferences() {
mUseGoogle = PreferenceManager.getInstance().getGoogleSearchSuggestionsEnabled(); mUseGoogle = PreferenceManager.getInstance().getGoogleSearchSuggestionsEnabled();
if (!mUseGoogle && mSuggestions != null) { if (!mUseGoogle) {
mSuggestions.clear(); mSuggestions.clear();
} }
mDatabaseHandler = HistoryDatabase.getInstance(mContext.getApplicationContext()); mDatabaseHandler = HistoryDatabase.getInstance(mContext.getApplicationContext());
} }
public void refreshBookmarks() { public void refreshBookmarks() {
mAllBookmarks = mBookmarkManager.getBookmarks(true); mAllBookmarks.clear();
mAllBookmarks.addAll(mBookmarkManager.getBookmarks(true));
} }
@Override @Override
public int getCount() { public int getCount() {
if (mFilteredList != null) {
return mFilteredList.size(); return mFilteredList.size();
} else {
return 0;
}
} }
@Override @Override
@ -146,23 +139,22 @@ public class SearchAdapter extends BaseAdapter implements Filterable {
@SuppressLint("NewApi") @SuppressLint("NewApi")
@Override @Override
public View getView(int position, View convertView, ViewGroup parent) { public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
SuggestionHolder holder; SuggestionHolder holder;
if (row == null) { if (convertView == null) {
LayoutInflater inflater = ((Activity) mContext).getLayoutInflater(); LayoutInflater inflater = ((Activity) mContext).getLayoutInflater();
row = inflater.inflate(R.layout.two_line_autocomplete, parent, false); convertView = inflater.inflate(R.layout.two_line_autocomplete, parent, false);
holder = new SuggestionHolder(); holder = new SuggestionHolder();
holder.mTitle = (TextView) row.findViewById(R.id.title); holder.mTitle = (TextView) convertView.findViewById(R.id.title);
holder.mUrl = (TextView) row.findViewById(R.id.url); holder.mUrl = (TextView) convertView.findViewById(R.id.url);
holder.mImage = (ImageView) row.findViewById(R.id.suggestionIcon); holder.mImage = (ImageView) convertView.findViewById(R.id.suggestionIcon);
row.setTag(holder); convertView.setTag(holder);
} else { } else {
holder = (SuggestionHolder) row.getTag(); holder = (SuggestionHolder) convertView.getTag();
} }
HistoryItem web;
HistoryItem web = mFilteredList.get(position); web = mFilteredList.get(position);
holder.mTitle.setText(web.getTitle()); holder.mTitle.setText(web.getTitle());
holder.mUrl.setText(web.getUrl()); holder.mUrl.setText(web.getUrl());
@ -203,16 +195,12 @@ public class SearchAdapter extends BaseAdapter implements Filterable {
holder.mImage.setImageDrawable(mContext.getResources().getDrawable(imageId, mTheme)); holder.mImage.setImageDrawable(mContext.getResources().getDrawable(imageId, mTheme));
} }
return row; return convertView;
} }
public void setContents(List<HistoryItem> list) { public void setContents(List<HistoryItem> list) {
if (mFilteredList != null) {
mFilteredList.clear(); mFilteredList.clear();
mFilteredList.addAll(list); mFilteredList.addAll(list);
} else {
mFilteredList = list;
}
notifyDataSetChanged(); notifyDataSetChanged();
} }
@ -238,7 +226,7 @@ public class SearchAdapter extends BaseAdapter implements Filterable {
} }
int counter = 0; int counter = 0;
mBookmarks = new ArrayList<>(); mBookmarks.clear();
for (int n = 0; n < mAllBookmarks.size(); n++) { for (int n = 0; n < mAllBookmarks.size(); n++) {
if (counter >= 5) { if (counter >= 5) {
break; break;
@ -256,8 +244,9 @@ public class SearchAdapter extends BaseAdapter implements Filterable {
if (mDatabaseHandler == null) { if (mDatabaseHandler == null) {
mDatabaseHandler = HistoryDatabase.getInstance(mContext.getApplicationContext()); mDatabaseHandler = HistoryDatabase.getInstance(mContext.getApplicationContext());
} }
mHistory = mDatabaseHandler.findItemsContaining(constraint.toString()); List<HistoryItem> historyList = mDatabaseHandler.findItemsContaining(constraint.toString());
mHistory.clear();
mHistory.addAll(historyList);
results.count = 1; results.count = 1;
return results; return results;
} }
@ -269,7 +258,8 @@ public class SearchAdapter extends BaseAdapter implements Filterable {
@Override @Override
protected void publishResults(CharSequence constraint, FilterResults results) { protected void publishResults(CharSequence constraint, FilterResults results) {
mFilteredList = getSuggestions(); mFilteredList.clear();
mFilteredList.addAll(getSuggestions());
notifyDataSetChanged(); notifyDataSetChanged();
} }
@ -330,21 +320,17 @@ public class SearchAdapter extends BaseAdapter implements Filterable {
} catch (Exception e) { } catch (Exception e) {
return filter; return filter;
} finally { } finally {
if (fileInput != null) { Utils.close(fileInput);
try {
fileInput.close();
} catch (IOException e) {
e.printStackTrace();
}
}
} }
return filter; return filter;
} }
@Override @Override
protected void onPostExecute(List<HistoryItem> result) { protected void onPostExecute(List<HistoryItem> result) {
mSuggestions = result; mSuggestions.clear();
mFilteredList = getSuggestions(); mSuggestions.addAll(result);
mFilteredList.clear();
mFilteredList.addAll(getSuggestions());
notifyDataSetChanged(); notifyDataSetChanged();
mIsExecuting = false; mIsExecuting = false;
} }
@ -401,9 +387,9 @@ public class SearchAdapter extends BaseAdapter implements Filterable {
private List<HistoryItem> getSuggestions() { private List<HistoryItem> getSuggestions() {
List<HistoryItem> filteredList = new ArrayList<>(); List<HistoryItem> filteredList = new ArrayList<>();
int suggestionsSize = (mSuggestions == null) ? 0 : mSuggestions.size(); int suggestionsSize = mSuggestions.size();
int historySize = (mHistory == null) ? 0 : mHistory.size(); int historySize = mHistory.size();
int bookmarkSize = (mBookmarks == null) ? 0 : mBookmarks.size(); int bookmarkSize = mBookmarks.size();
int maxSuggestions = (bookmarkSize + historySize < 3) ? (5 - bookmarkSize - historySize) int maxSuggestions = (bookmarkSize + historySize < 3) ? (5 - bookmarkSize - historySize)
: (bookmarkSize < 2) ? (4 - bookmarkSize) : (historySize < 1) ? 3 : 2; : (bookmarkSize < 2) ? (4 - bookmarkSize) : (historySize < 1) ? 3 : 2;
@ -412,11 +398,6 @@ public class SearchAdapter extends BaseAdapter implements Filterable {
int maxBookmarks = (suggestionsSize + historySize < 3) ? (5 - suggestionsSize - historySize) int maxBookmarks = (suggestionsSize + historySize < 3) ? (5 - suggestionsSize - historySize)
: 2; : 2;
if (!mUseGoogle || mIncognito) {
maxHistory++;
maxBookmarks++;
}
for (int n = 0; n < bookmarkSize && n < maxBookmarks; n++) { for (int n = 0; n < bookmarkSize && n < maxBookmarks; n++) {
filteredList.add(mBookmarks.get(n)); filteredList.add(mBookmarks.get(n));
} }

2
app/src/main/java/acr/browser/lightning/preference/PreferenceManager.java

@ -357,7 +357,7 @@ public class PreferenceManager {
} }
public void setReadingTextSize(int size) { public void setReadingTextSize(int size) {
putInt(Name.READING_TEXT_SIZE, 2); putInt(Name.READING_TEXT_SIZE, size);
} }
public void setRenderingMode(int mode) { public void setRenderingMode(int mode) {

5
app/src/main/java/acr/browser/lightning/reading/ArticleTextExtractor.java

@ -95,11 +95,10 @@ public class ArticleTextExtractor {
} }
/** /**
* @param html * @param doc the document to extract
* extracts article text from given html string. wasn't tested * extracts article text from given html string. wasn't tested
* with improper HTML, although jSoup should be able to handle * with improper HTML, although jSoup should be able to handle
* minor stuff. * minor stuff.
* @returns extracted article, all HTML tags stripped
*/ */
public JResult extractContent(Document doc) throws Exception { public JResult extractContent(Document doc) throws Exception {
return extractContent(new JResult(), doc, formatter); return extractContent(new JResult(), doc, formatter);
@ -235,14 +234,12 @@ public class ArticleTextExtractor {
protected Collection<String> extractKeywords(Document doc) { protected Collection<String> extractKeywords(Document doc) {
String content = SHelper.innerTrim(doc.select("head meta[name=keywords]").attr("content")); String content = SHelper.innerTrim(doc.select("head meta[name=keywords]").attr("content"));
if (content != null) {
if (content.startsWith("[") && content.endsWith("]")) if (content.startsWith("[") && content.endsWith("]"))
content = content.substring(1, content.length() - 1); content = content.substring(1, content.length() - 1);
String[] split = content.split("\\s*,\\s*"); String[] split = content.split("\\s*,\\s*");
if (split.length > 1 || (split.length > 0 && !"".equals(split[0]))) if (split.length > 1 || (split.length > 0 && !"".equals(split[0])))
return Arrays.asList(split); return Arrays.asList(split);
}
return Collections.emptyList(); return Collections.emptyList();
} }

2
app/src/main/java/acr/browser/lightning/reading/Converter.java

@ -94,7 +94,7 @@ public class Converter {
/** /**
* reads bytes off the string and returns a string * reads bytes off the string and returns a string
* *
* @param is * @param is input stream to read
* @param maxBytes * @param maxBytes
* The max bytes that we want to read from the input stream * The max bytes that we want to read from the input stream
* @return String * @return String

2
app/src/main/java/acr/browser/lightning/reading/HtmlFetcher.java

@ -230,7 +230,7 @@ public class HtmlFetcher {
} }
// if resolved url is longer then use it! // if resolved url is longer then use it!
if (resUrl != null && resUrl.trim().length() > url.length()) { if (resUrl.trim().length() > url.length()) {
// this is necessary e.g. for some homebaken url resolvers which // this is necessary e.g. for some homebaken url resolvers which
// return // return
// the resolved url relative to url! // the resolved url relative to url!

9
app/src/main/java/acr/browser/lightning/reading/SHelper.java

@ -164,7 +164,7 @@ public class SHelper {
* extract the domain from this url * extract the domain from this url
* @param path * @param path
* this url does not have a domain * this url does not have a domain
* @return * @return returns the domain
*/ */
public static String useDomainOfFirstArg4Second(String urlForDomain, String path) { public static String useDomainOfFirstArg4Second(String urlForDomain, String path) {
if (path.startsWith("http")) if (path.startsWith("http"))
@ -257,8 +257,7 @@ public class SHelper {
} }
/** /**
* @see http * http://blogs.sun.com/CoreJavaTechTips/entry/cookie_handling_in_java_se
* ://blogs.sun.com/CoreJavaTechTips/entry/cookie_handling_in_java_se
*/ */
public static void enableCookieMgmt() { public static void enableCookieMgmt() {
CookieManager manager = new CookieManager(); CookieManager manager = new CookieManager();
@ -267,9 +266,7 @@ public class SHelper {
} }
/** /**
* @see http * http://stackoverflow.com/questions/2529682/setting-user-agent-of-a-java-urlconnection
* ://stackoverflow.com/questions/2529682/setting-user-agent-of-a-java
* -urlconnection
*/ */
public static void enableUserAgentOverwrite() { public static void enableUserAgentOverwrite() {
System.setProperty("http.agent", ""); System.setProperty("http.agent", "");

2
app/src/main/java/acr/browser/lightning/utils/IntentUtils.java

@ -21,7 +21,7 @@ public class IntentUtils {
private final Activity mActivity; private final Activity mActivity;
static final Pattern ACCEPTED_URI_SCHEMA = Pattern.compile("(?i)" private static final Pattern ACCEPTED_URI_SCHEMA = Pattern.compile("(?i)"
+ // switch on case insensitive matching + // switch on case insensitive matching
"(" "("
+ // begin group for schema + // begin group for schema

34
app/src/main/java/acr/browser/lightning/utils/ThemeUtils.java

@ -0,0 +1,34 @@
package acr.browser.lightning.utils;
import android.content.Context;
import android.content.res.TypedArray;
import android.support.annotation.AttrRes;
import android.support.annotation.NonNull;
import android.util.TypedValue;
import acr.browser.lightning.R;
public class ThemeUtils {
private static final TypedValue sTypedValue = new TypedValue();
public static int getPrimaryColor(@NonNull Context context) {
return getColor(context, R.attr.colorPrimary);
}
public static int getPrimaryColorDark(@NonNull Context context) {
return getColor(context, R.attr.colorPrimaryDark);
}
public static int getAccentColor(@NonNull Context context) {
return getColor(context, R.attr.colorAccent);
}
private static int getColor(@NonNull Context context, @AttrRes int resource) {
TypedArray a = context.obtainStyledAttributes(sTypedValue.data, new int[]{resource});
int color = a.getColor(0, 0);
a.recycle();
return color;
}
}

25
app/src/main/java/acr/browser/lightning/utils/Utils.java

@ -5,7 +5,6 @@ package acr.browser.lightning.utils;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.app.Activity; import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
@ -17,11 +16,14 @@ import android.graphics.BitmapFactory;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Paint; import android.graphics.Paint;
import android.os.Environment; import android.os.Environment;
import android.support.annotation.StringRes;
import android.support.v7.app.AlertDialog;
import android.util.DisplayMetrics; import android.util.DisplayMetrics;
import android.util.Log; import android.util.Log;
import android.webkit.URLUtil; import android.webkit.URLUtil;
import android.widget.Toast; import android.widget.Toast;
import java.io.Closeable;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.net.URI; import java.net.URI;
@ -39,14 +41,14 @@ public final class Utils {
} }
public static void downloadFile(final Activity activity, final String url, public static void downloadFile(final Activity activity, final String url,
final String userAgent, final String contentDisposition, final boolean privateBrowsing) { final String userAgent, final String contentDisposition) {
String fileName = URLUtil.guessFileName(url, null, null); String fileName = URLUtil.guessFileName(url, null, null);
DownloadHandler.onDownloadStart(activity, url, userAgent, contentDisposition, null, DownloadHandler.onDownloadStart(activity, url, userAgent, contentDisposition, null
privateBrowsing); );
Log.i(Constants.TAG, "Downloading" + fileName); Log.i(Constants.TAG, "Downloading" + fileName);
} }
public static Intent newEmailIntent(Context context, String address, String subject, public static Intent newEmailIntent(String address, String subject,
String body, String cc) { String body, String cc) {
Intent intent = new Intent(Intent.ACTION_SEND); Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_EMAIL, new String[] { address }); intent.putExtra(Intent.EXTRA_EMAIL, new String[] { address });
@ -76,6 +78,10 @@ public final class Utils {
Toast.makeText(context, message, Toast.LENGTH_SHORT).show(); Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
} }
public static void showToast(Context context, @StringRes int resource) {
Toast.makeText(context, resource, Toast.LENGTH_SHORT).show();
}
/** /**
* Returns the number of pixels corresponding to the passed density pixels * Returns the number of pixels corresponding to the passed density pixels
*/ */
@ -237,4 +243,13 @@ public final class Utils {
private static Bitmap mWebIconLight; private static Bitmap mWebIconLight;
private static Bitmap mWebIconDark; private static Bitmap mWebIconDark;
public static void close(Closeable closeable) {
if (closeable == null)
return;
try {
closeable.close();
} catch (IOException e) {
e.printStackTrace();
}
}
} }

93
app/src/main/java/acr/browser/lightning/view/LightningView.java

@ -6,7 +6,6 @@ package acr.browser.lightning.view;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.app.Activity; import android.app.Activity;
import android.app.AlertDialog;
import android.content.ActivityNotFoundException; import android.content.ActivityNotFoundException;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
@ -21,6 +20,8 @@ import android.net.http.SslError;
import android.os.Build; import android.os.Build;
import android.os.Message; import android.os.Message;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AlertDialog;
import android.text.InputType; import android.text.InputType;
import android.text.method.PasswordTransformationMethod; import android.text.method.PasswordTransformationMethod;
import android.util.Log; import android.util.Log;
@ -29,6 +30,7 @@ import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View; import android.view.View;
import android.view.View.OnTouchListener; import android.view.View.OnTouchListener;
import android.view.ViewConfiguration;
import android.webkit.CookieManager; import android.webkit.CookieManager;
import android.webkit.GeolocationPermissions; import android.webkit.GeolocationPermissions;
import android.webkit.HttpAuthHandler; import android.webkit.HttpAuthHandler;
@ -80,6 +82,7 @@ public class LightningView {
private boolean isForegroundTab; private boolean isForegroundTab;
private boolean mTextReflow = false; private boolean mTextReflow = false;
private boolean mInvertPage = false; private boolean mInvertPage = false;
private static float mMaxFling;
private static final int API = android.os.Build.VERSION.SDK_INT; private static final int API = android.os.Build.VERSION.SDK_INT;
private static final int SCROLL_UP_THRESHOLD = Utils.convertDpToPixels(10); private static final int SCROLL_UP_THRESHOLD = Utils.convertDpToPixels(10);
private static final int SCROLL_DOWN_THRESHOLD = Utils.convertDpToPixels(100); private static final int SCROLL_DOWN_THRESHOLD = Utils.convertDpToPixels(100);
@ -100,6 +103,8 @@ public class LightningView {
mWebpageBitmap = Utils.getWebpageBitmap(activity.getResources(), darkTheme); mWebpageBitmap = Utils.getWebpageBitmap(activity.getResources(), darkTheme);
mMaxFling = ViewConfiguration.get(activity).getScaledMaximumFlingVelocity();
try { try {
mBrowserController = (BrowserController) activity; mBrowserController = (BrowserController) activity;
} catch (ClassCastException e) { } catch (ClassCastException e) {
@ -113,7 +118,7 @@ public class LightningView {
mWebView.setDrawingCacheEnabled(false); mWebView.setDrawingCacheEnabled(false);
mWebView.setWillNotCacheDrawing(true); mWebView.setWillNotCacheDrawing(true);
mWebView.setAlwaysDrawnWithCacheEnabled(false); mWebView.setAlwaysDrawnWithCacheEnabled(false);
mWebView.setBackgroundColor(activity.getResources().getColor(android.R.color.white)); mWebView.setBackgroundColor(0);
if (API > 15) { if (API > 15) {
mWebView.setBackground(null); mWebView.setBackground(null);
@ -363,13 +368,13 @@ public class LightningView {
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
@SuppressLint({"SetJavaScriptEnabled", "NewApi"}) @SuppressLint({"SetJavaScriptEnabled", "NewApi"})
private void initializeSettings(WebSettings settings, Context context) { private void initializeSettings(WebSettings settings, Context context) {
if (API < 18) { if (API < Build.VERSION_CODES.JELLY_BEAN_MR2) {
settings.setAppCacheMaxSize(Long.MAX_VALUE); settings.setAppCacheMaxSize(Long.MAX_VALUE);
} }
if (API < 17) { if (API < Build.VERSION_CODES.JELLY_BEAN_MR1) {
settings.setEnableSmoothTransition(true); settings.setEnableSmoothTransition(true);
} }
if (API > 16) { if (API > Build.VERSION_CODES.JELLY_BEAN) {
settings.setMediaPlaybackRequiresUserGesture(true); settings.setMediaPlaybackRequiresUserGesture(true);
} }
if (API >= Build.VERSION_CODES.LOLLIPOP && !mBrowserController.isIncognito()) { if (API >= Build.VERSION_CODES.LOLLIPOP && !mBrowserController.isIncognito()) {
@ -388,7 +393,7 @@ public class LightningView {
settings.setAllowContentAccess(true); settings.setAllowContentAccess(true);
settings.setAllowFileAccess(true); settings.setAllowFileAccess(true);
settings.setDefaultTextEncodingName("utf-8"); settings.setDefaultTextEncodingName("utf-8");
if (API > 16) { if (API >= Build.VERSION_CODES.JELLY_BEAN) {
settings.setAllowFileAccessFromFileURLs(false); settings.setAllowFileAccessFromFileURLs(false);
settings.setAllowUniversalAccessFromFileURLs(false); settings.setAllowUniversalAccessFromFileURLs(false);
} }
@ -405,15 +410,18 @@ public class LightningView {
} }
public synchronized void onPause() { public synchronized void onPause() {
if (mWebView != null) { if (mWebView != null)
mWebView.onPause(); mWebView.onPause();
} }
}
public synchronized void onResume() { public synchronized void onResume() {
if (mWebView != null) { if (mWebView != null)
mWebView.onResume(); mWebView.onResume();
} }
public synchronized void freeMemory() {
if (mWebView != null && Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT)
mWebView.freeMemory();
} }
public void setForegroundTab(boolean isForeground) { public void setForegroundTab(boolean isForeground) {
@ -451,7 +459,7 @@ public class LightningView {
mWebView.setLayerType(View.LAYER_TYPE_SOFTWARE, null); mWebView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
} }
public void setColorMode(int mode) { private void setColorMode(int mode) {
mInvertPage = false; mInvertPage = false;
switch (mode) { switch (mode) {
case 0: case 0:
@ -540,14 +548,16 @@ public class LightningView {
private void cacheFavicon(Bitmap icon) { private void cacheFavicon(Bitmap icon) {
String hash = String.valueOf(Utils.getDomainName(getUrl()).hashCode()); String hash = String.valueOf(Utils.getDomainName(getUrl()).hashCode());
Log.d(Constants.TAG, "Caching icon for " + Utils.getDomainName(getUrl())); Log.d(Constants.TAG, "Caching icon for " + Utils.getDomainName(getUrl()));
File image = new File(mActivity.getCacheDir(), hash + ".png"); FileOutputStream fos = null;
try { try {
FileOutputStream fos = new FileOutputStream(image); File image = new File(mActivity.getCacheDir(), hash + ".png");
fos = new FileOutputStream(image);
icon.compress(Bitmap.CompressFormat.PNG, 100, fos); icon.compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.flush(); fos.flush();
fos.close();
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} finally {
Utils.close(fos);
} }
} }
@ -563,6 +573,7 @@ public class LightningView {
} }
} }
@Nullable
public Activity getActivity() { public Activity getActivity() {
return mActivity; return mActivity;
} }
@ -608,6 +619,7 @@ public class LightningView {
return mWebView != null && mWebView.canGoForward(); return mWebView != null && mWebView.canGoForward();
} }
@Nullable
public WebView getWebView() { public WebView getWebView() {
return mWebView; return mWebView;
} }
@ -638,8 +650,9 @@ public class LightningView {
return mTitle.getTitle(); return mTitle.getTitle();
} }
@NonNull
public String getUrl() { public String getUrl() {
if (mWebView != null) { if (mWebView != null && mWebView.getUrl() != null) {
return mWebView.getUrl(); return mWebView.getUrl();
} else { } else {
return ""; return "";
@ -656,6 +669,7 @@ public class LightningView {
@Override @Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) { public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
if (mAdBlock.isAd(request.getUrl().getHost())) { if (mAdBlock.isAd(request.getUrl().getHost())) {
ByteArrayInputStream EMPTY = new ByteArrayInputStream("".getBytes()); ByteArrayInputStream EMPTY = new ByteArrayInputStream("".getBytes());
return new WebResourceResponse("text/plain", "utf-8", EMPTY); return new WebResourceResponse("text/plain", "utf-8", EMPTY);
@ -841,7 +855,7 @@ public class LightningView {
} }
if (url.contains("mailto:")) { if (url.contains("mailto:")) {
MailTo mailTo = MailTo.parse(url); MailTo mailTo = MailTo.parse(url);
Intent i = Utils.newEmailIntent(mActivity, mailTo.getTo(), mailTo.getSubject(), Intent i = Utils.newEmailIntent(mailTo.getTo(), mailTo.getSubject(),
mailTo.getBody(), mailTo.getCc()); mailTo.getBody(), mailTo.getCc());
mActivity.startActivity(i); mActivity.startActivity(i);
view.reload(); view.reload();
@ -883,6 +897,8 @@ public class LightningView {
@Override @Override
public void onReceivedIcon(WebView view, Bitmap icon) { public void onReceivedIcon(WebView view, Bitmap icon) {
if (icon == null)
return;
mTitle.setFavicon(icon); mTitle.setFavicon(icon);
mBrowserController.update(); mBrowserController.update();
cacheFavicon(icon); cacheFavicon(icon);
@ -890,12 +906,13 @@ public class LightningView {
@Override @Override
public void onReceivedTitle(WebView view, String title) { public void onReceivedTitle(WebView view, String title) {
if (!title.isEmpty()) { if (title != null && !title.isEmpty()) {
mTitle.setTitle(title); mTitle.setTitle(title);
} else { } else {
mTitle.setTitle(mActivity.getString(R.string.untitled)); mTitle.setTitle(mActivity.getString(R.string.untitled));
} }
mBrowserController.update(); mBrowserController.update();
if (view != null)
mBrowserController.updateHistory(title, view.getUrl()); mBrowserController.updateHistory(title, view.getUrl());
} }
@ -935,7 +952,7 @@ public class LightningView {
@Override @Override
public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture, public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture,
Message resultMsg) { Message resultMsg) {
mBrowserController.onCreateWindow(isUserGesture, resultMsg); mBrowserController.onCreateWindow(resultMsg);
return true; return true;
} }
@ -993,8 +1010,8 @@ public class LightningView {
// video.setVisibility(View.GONE); // video.setVisibility(View.GONE);
// } // }
// } else { // } else {
Activity activity = mBrowserController.getActivity(); // Activity activity = mBrowserController.getActivity();
mBrowserController.onShowCustomView(view, activity.getRequestedOrientation(), callback); mBrowserController.onShowCustomView(view, callback);
// } // }
@ -1017,7 +1034,7 @@ public class LightningView {
// video.setVisibility(View.GONE); // video.setVisibility(View.GONE);
// } // }
// } else { // } else {
mBrowserController.onShowCustomView(view, requestedOrientation, callback); mBrowserController.onShowCustomView(view, callback);
// } // }
@ -1082,7 +1099,10 @@ public class LightningView {
@SuppressLint("ClickableViewAccessibility") @SuppressLint("ClickableViewAccessibility")
@Override @Override
public boolean onTouch(View view, MotionEvent arg1) { public boolean onTouch(View view, MotionEvent arg1) {
if (view != null && !view.hasFocus()) { if (view == null)
return false;
if (!view.hasFocus()) {
view.requestFocus(); view.requestFocus();
} }
mAction = arg1.getAction(); mAction = arg1.getAction();
@ -1090,13 +1110,14 @@ public class LightningView {
if (mAction == MotionEvent.ACTION_DOWN) { if (mAction == MotionEvent.ACTION_DOWN) {
mLocation = mY; mLocation = mY;
} else if (mAction == MotionEvent.ACTION_UP) { } else if (mAction == MotionEvent.ACTION_UP) {
if ((mY - mLocation) > SCROLL_DOWN_THRESHOLD) { final float distance = (mY - mLocation);
if (mWebView.getScrollY() != 0) { if (distance > SCROLL_UP_THRESHOLD && view.getScrollY() < SCROLL_UP_THRESHOLD) {
// if (mWebView.getScrollY() != 0) {
mBrowserController.showActionBar(); mBrowserController.showActionBar();
} else { // } else {
mBrowserController.toggleActionBar(); // mBrowserController.toggleActionBar();
} // }
} else if ((mY - mLocation) < -SCROLL_UP_THRESHOLD) { } else if (distance < -SCROLL_UP_THRESHOLD) {
mBrowserController.hideActionBar(); mBrowserController.hideActionBar();
} }
mLocation = 0; mLocation = 0;
@ -1107,11 +1128,27 @@ public class LightningView {
} }
private class CustomGestureListener extends SimpleOnGestureListener { private class CustomGestureListener extends SimpleOnGestureListener {
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
return super.onScroll(e1, e2, distanceX, distanceY);
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
int power = (int) (velocityY * 100 / mMaxFling);
Log.e("YOLO", "POWER: " + power);
if (power < -10) {
mBrowserController.hideActionBar();
} else if (power > 15) {
mBrowserController.showActionBar();
}
return super.onFling(e1, e2, velocityX, velocityY);
}
/** /**
* Without this, onLongPress is not called when user is zooming using * Without this, onLongPress is not called when user is zooming using
* two fingers, but is when using only one. * two fingers, but is when using only one.
* * <p/>
* The required behaviour is to not trigger this when the user is * The required behaviour is to not trigger this when the user is
* zooming, it shouldn't matter how much fingers the user's using. * zooming, it shouldn't matter how much fingers the user's using.
*/ */

2
app/src/main/res/layout/picker_manual_proxy.xml

@ -3,7 +3,9 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical" android:orientation="vertical"
android:paddingEnd="4dp"
android:paddingLeft="4dp" android:paddingLeft="4dp"
android:paddingRight="4dp"
android:paddingStart="4dp"> android:paddingStart="4dp">
<LinearLayout <LinearLayout

2
app/src/main/res/layout/toolbar_content.xml

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal" > android:orientation="horizontal" >
@ -9,7 +8,6 @@
android:id="@+id/arrow_button" android:id="@+id/arrow_button"
android:layout_width="?attr/actionBarSize" android:layout_width="?attr/actionBarSize"
android:layout_height="?attr/actionBarSize" android:layout_height="?attr/actionBarSize"
android:layout_marginLeft="2dp"
android:layout_marginTop="2dp" android:layout_marginTop="2dp"
android:background="?attr/actionBarItemBackground" android:background="?attr/actionBarItemBackground"
android:clickable="true" android:clickable="true"

7
app/src/main/res/layout/two_line_autocomplete.xml

@ -3,11 +3,14 @@
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:clickable="false" android:clickable="false"
android:gravity="center_vertical"
android:orientation="horizontal" android:orientation="horizontal"
android:paddingBottom="3dp" android:paddingBottom="3dp"
android:paddingEnd="6dp"
android:paddingLeft="6dp" android:paddingLeft="6dp"
android:paddingTop="3dp" android:paddingRight="6dp"
android:gravity="center_vertical"> android:paddingStart="6dp"
android:paddingTop="3dp">
<ImageView <ImageView
android:id="@+id/suggestionIcon" android:id="@+id/suggestionIcon"

3
app/src/main/res/values-v21/styles.xml

@ -4,6 +4,7 @@
<style name="Theme.SettingsTheme" parent="Theme.AppCompat.Light"> <style name="Theme.SettingsTheme" parent="Theme.AppCompat.Light">
<!-- customize the color palette --> <!-- customize the color palette -->
<item name="android:windowBackground">@color/transparent</item>
<item name="toolbarSettingsBackground">@color/primary_color</item> <item name="toolbarSettingsBackground">@color/primary_color</item>
<item name="listBackground">?attr/listChoiceBackgroundIndicator</item> <item name="listBackground">?attr/listChoiceBackgroundIndicator</item>
<item name="colorPrimary">@color/primary_color</item> <item name="colorPrimary">@color/primary_color</item>
@ -20,6 +21,7 @@
<style name="Theme.SettingsTheme.Dark" parent="Theme.AppCompat"> <style name="Theme.SettingsTheme.Dark" parent="Theme.AppCompat">
<!-- customize the color palette --> <!-- customize the color palette -->
<item name="android:windowBackground">@color/transparent</item>
<item name="toolbarSettingsBackground">@color/primary_color_dark</item> <item name="toolbarSettingsBackground">@color/primary_color_dark</item>
<item name="listBackground">?attr/listChoiceBackgroundIndicator</item> <item name="listBackground">?attr/listChoiceBackgroundIndicator</item>
<item name="colorPrimary">@color/primary_color_dark</item> <item name="colorPrimary">@color/primary_color_dark</item>
@ -36,6 +38,7 @@
<style name="Theme.SettingsTheme.Black" parent="Theme.AppCompat"> <style name="Theme.SettingsTheme.Black" parent="Theme.AppCompat">
<!-- customize the color palette --> <!-- customize the color palette -->
<item name="android:windowBackground">@color/transparent</item>
<item name="toolbarSettingsBackground">@color/black</item> <item name="toolbarSettingsBackground">@color/black</item>
<item name="listBackground">?attr/listChoiceBackgroundIndicator</item> <item name="listBackground">?attr/listChoiceBackgroundIndicator</item>
<item name="colorPrimary">@color/black</item> <item name="colorPrimary">@color/black</item>

5
app/src/main/res/values/styles.xml

@ -4,6 +4,7 @@
<style name="Theme.SettingsTheme" parent="Theme.AppCompat.Light"> <style name="Theme.SettingsTheme" parent="Theme.AppCompat.Light">
<!-- customize the color palette --> <!-- customize the color palette -->
<item name="android:windowBackground">@color/transparent</item>
<item name="toolbarSettingsBackground">@drawable/toolbar_elevate</item> <item name="toolbarSettingsBackground">@drawable/toolbar_elevate</item>
<item name="listBackground">@drawable/list_bg</item> <item name="listBackground">@drawable/list_bg</item>
<item name="colorPrimary">@color/primary_color</item> <item name="colorPrimary">@color/primary_color</item>
@ -20,6 +21,7 @@
<style name="Theme.SettingsTheme.Dark" parent="Theme.AppCompat"> <style name="Theme.SettingsTheme.Dark" parent="Theme.AppCompat">
<!-- customize the color palette --> <!-- customize the color palette -->
<item name="android:windowBackground">@color/transparent</item>
<item name="toolbarSettingsBackground">@drawable/toolbar_elevate_dark</item> <item name="toolbarSettingsBackground">@drawable/toolbar_elevate_dark</item>
<item name="listBackground">@drawable/list_bg</item> <item name="listBackground">@drawable/list_bg</item>
<item name="colorPrimary">@color/primary_color_dark</item> <item name="colorPrimary">@color/primary_color_dark</item>
@ -36,6 +38,7 @@
<style name="Theme.SettingsTheme.Black" parent="Theme.AppCompat"> <style name="Theme.SettingsTheme.Black" parent="Theme.AppCompat">
<!-- customize the color palette --> <!-- customize the color palette -->
<item name="android:windowBackground">@color/transparent</item>
<item name="toolbarSettingsBackground">@drawable/toolbar_elevate_black</item> <item name="toolbarSettingsBackground">@drawable/toolbar_elevate_black</item>
<item name="listBackground">@drawable/list_bg</item> <item name="listBackground">@drawable/list_bg</item>
<item name="colorPrimary">@color/black</item> <item name="colorPrimary">@color/black</item>
@ -53,13 +56,13 @@
<!-- customize the color palette --> <!-- customize the color palette -->
<item name="searchBackground">@drawable/card_bg_elevate</item> <item name="searchBackground">@drawable/card_bg_elevate</item>
<item name="listBackground">@drawable/list_bg</item>
<item name="colorPrimary">@color/primary_color</item> <item name="colorPrimary">@color/primary_color</item>
<item name="colorPrimaryDark">@color/secondary_color</item> <item name="colorPrimaryDark">@color/secondary_color</item>
<item name="colorAccent">@color/accent_color</item> <item name="colorAccent">@color/accent_color</item>
<item name="windowNoTitle">true</item> <item name="windowNoTitle">true</item>
<item name="windowActionBar">false</item> <item name="windowActionBar">false</item>
<item name="progressBackgroundColor">@color/secondary_color</item> <item name="progressBackgroundColor">@color/secondary_color</item>
<item name="listBackground">@drawable/list_bg</item>
<item name="android:windowContentOverlay">@null</item> <item name="android:windowContentOverlay">@null</item>
<item name="progressColor">@color/gray_medium</item> <item name="progressColor">@color/gray_medium</item>
<item name="numberColor">@color/gray_dark</item> <item name="numberColor">@color/gray_dark</item>

Loading…
Cancel
Save