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 9 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. 5033
      app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java
  7. 109
      app/src/main/java/acr/browser/lightning/activity/IncognitoActivity.java
  8. 104
      app/src/main/java/acr/browser/lightning/activity/MainActivity.java
  9. 442
      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. 11
      app/src/main/java/acr/browser/lightning/activity/ThemableSettingsActivity.java
  13. 4
      app/src/main/java/acr/browser/lightning/controller/BrowserController.java
  14. 770
      app/src/main/java/acr/browser/lightning/database/BookmarkManager.java
  15. 4
      app/src/main/java/acr/browser/lightning/database/HistoryDatabase.java
  16. 369
      app/src/main/java/acr/browser/lightning/download/DownloadHandler.java
  17. 140
      app/src/main/java/acr/browser/lightning/download/FetchUrlMimeType.java
  18. 5
      app/src/main/java/acr/browser/lightning/download/LightningDownloadListener.java
  19. 2
      app/src/main/java/acr/browser/lightning/fragment/AdvancedSettingsFragment.java
  20. 60
      app/src/main/java/acr/browser/lightning/fragment/BookmarkSettingsFragment.java
  21. 13
      app/src/main/java/acr/browser/lightning/fragment/DisplaySettingsFragment.java
  22. 14
      app/src/main/java/acr/browser/lightning/fragment/GeneralSettingsFragment.java
  23. 9
      app/src/main/java/acr/browser/lightning/fragment/PrivacySettingsFragment.java
  24. 789
      app/src/main/java/acr/browser/lightning/object/SearchAdapter.java
  25. 2
      app/src/main/java/acr/browser/lightning/preference/PreferenceManager.java
  26. 15
      app/src/main/java/acr/browser/lightning/reading/ArticleTextExtractor.java
  27. 2
      app/src/main/java/acr/browser/lightning/reading/Converter.java
  28. 2
      app/src/main/java/acr/browser/lightning/reading/HtmlFetcher.java
  29. 9
      app/src/main/java/acr/browser/lightning/reading/SHelper.java
  30. 2
      app/src/main/java/acr/browser/lightning/utils/IntentUtils.java
  31. 34
      app/src/main/java/acr/browser/lightning/utils/ThemeUtils.java
  32. 37
      app/src/main/java/acr/browser/lightning/utils/Utils.java
  33. 2195
      app/src/main/java/acr/browser/lightning/view/LightningView.java
  34. 20
      app/src/main/res/layout/picker_manual_proxy.xml
  35. 2
      app/src/main/res/layout/toolbar_content.xml
  36. 11
      app/src/main/res/layout/two_line_autocomplete.xml
  37. 3
      app/src/main/res/values-v21/styles.xml
  38. 5
      app/src/main/res/values/styles.xml

2
Lightning-Browser.iml

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

20
app/app.iml

@ -12,10 +12,12 @@ @@ -12,10 +12,12 @@
<option name="SELECTED_TEST_ARTIFACT" value="_android_test_" />
<option name="ASSEMBLE_TASK_NAME" value="assembleLightningPlusDebug" />
<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="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="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
<option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
@ -24,7 +26,7 @@ @@ -24,7 +26,7 @@
</configuration>
</facet>
</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-test url="file://$MODULE_DIR$/build/intermediates/classes/androidTest/lightningPlus/debug" />
<exclude-output />
@ -48,13 +50,13 @@ @@ -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/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$/src/LightningPlus/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/LightningPlus/resources" 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/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/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/LightningPlus/rs" 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/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/assets" type="java-test-resource" />
@ -109,7 +111,7 @@ @@ -109,7 +111,7 @@
<excludeFolder url="file://$MODULE_DIR$/build/outputs" />
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
</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="library" exported="" name="client-0.7" level="project" />
<orderEntry type="library" exported="" name="palette-v7-22.2.0" level="project" />

5
app/build.gradle

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

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

@ -1,9 +1,9 @@ @@ -1,9 +1,9 @@
package acr.browser.lightning.utils;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.support.v7.app.AlertDialog;
import android.util.Log;
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; @@ -4,6 +4,7 @@ import android.content.res.Configuration;
import android.os.Bundle;
import android.preference.PreferenceActivity;
import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatDelegate;
@ -44,6 +45,7 @@ public abstract class AppCompatPreferenceActivity extends PreferenceActivity { @@ -44,6 +45,7 @@ public abstract class AppCompatPreferenceActivity extends PreferenceActivity {
getDelegate().setSupportActionBar(toolbar);
}
@NonNull
@Override
public MenuInflater getMenuInflater() {
return getDelegate().getMenuInflater();

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

File diff suppressed because it is too large Load Diff

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

@ -13,69 +13,66 @@ import acr.browser.lightning.R; @@ -13,69 +13,66 @@ import acr.browser.lightning.R;
@SuppressWarnings("deprecation")
public class IncognitoActivity extends BrowserActivity {
private CookieManager mCookieManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public void updateCookiePreference() {
CookieManager cookieManager = CookieManager.getInstance();
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
CookieSyncManager.createInstance(this);
}
cookieManager.setAcceptCookie(PreferenceManager.getInstance().getIncognitoCookiesEnabled());
super.updateCookiePreference();
}
@Override
public void updateCookiePreference() {
mCookieManager = CookieManager.getInstance();
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
CookieSyncManager.createInstance(this);
}
mCookieManager
.setAcceptCookie(PreferenceManager.getInstance().getIncognitoCookiesEnabled());
super.updateCookiePreference();
}
@Override
public synchronized void initializeTabs() {
super.initializeTabs();
// restoreOrNewTab();
newTab(null, true);
// if incognito mode use newTab(null, true); instead
}
@Override
public synchronized void initializeTabs() {
super.initializeTabs();
// restoreOrNewTab();
newTab(null, true);
// if incognito mode use newTab(null, true); instead
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.incognito, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.incognito, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
protected void onNewIntent(Intent intent) {
// handleNewIntent(intent);
super.onNewIntent(intent);
}
@Override
protected void onNewIntent(Intent intent) {
// handleNewIntent(intent);
super.onNewIntent(intent);
}
@Override
protected void onPause() {
super.onPause();
// saveOpenTabs();
}
@Override
protected void onPause() {
super.onPause();
// saveOpenTabs();
}
@Override
public void updateHistory(String title, String url) {
super.updateHistory(title, url);
// addItemToHistory(title, url);
}
@Override
public void updateHistory(String title, String url) {
super.updateHistory(title, url);
// addItemToHistory(title, url);
}
@Override
public boolean isIncognito() {
return true;
}
@Override
public boolean isIncognito() {
return true;
}
@Override
public void closeActivity() {
closeDrawers();
finish();
}
@Override
public void closeActivity() {
closeDrawers();
finish();
}
@Override
public int getMenu() {
return R.menu.incognito;
}
@Override
public int getMenu() {
return R.menu.incognito;
}
}

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

@ -13,66 +13,64 @@ import acr.browser.lightning.R; @@ -13,66 +13,64 @@ import acr.browser.lightning.R;
@SuppressWarnings("deprecation")
public class MainActivity extends BrowserActivity {
private CookieManager mCookieManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public void updateCookiePreference() {
CookieManager cookieManager = CookieManager.getInstance();
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
CookieSyncManager.createInstance(this);
}
cookieManager.setAcceptCookie(PreferenceManager.getInstance().getCookiesEnabled());
super.updateCookiePreference();
}
@Override
public void updateCookiePreference() {
mCookieManager = CookieManager.getInstance();
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
CookieSyncManager.createInstance(this);
}
mCookieManager.setAcceptCookie(PreferenceManager.getInstance().getCookiesEnabled());
super.updateCookiePreference();
}
@Override
public synchronized void initializeTabs() {
restoreOrNewTab();
// if incognito mode use newTab(null, true); instead
}
@Override
public synchronized void initializeTabs() {
restoreOrNewTab();
// if incognito mode use newTab(null, true); instead
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
protected void onNewIntent(Intent intent) {
handleNewIntent(intent);
super.onNewIntent(intent);
}
@Override
protected void onNewIntent(Intent intent) {
handleNewIntent(intent);
super.onNewIntent(intent);
}
@Override
protected void onPause() {
super.onPause();
saveOpenTabs();
}
@Override
protected void onPause() {
super.onPause();
saveOpenTabs();
}
@Override
public void updateHistory(String title, String url) {
super.updateHistory(title, url);
addItemToHistory(title, url);
}
@Override
public void updateHistory(String title, String url) {
super.updateHistory(title, url);
addItemToHistory(title, url);
}
@Override
public boolean isIncognito() {
return false;
}
@Override
public boolean isIncognito() {
return false;
}
@Override
public int getMenu() {
return R.menu.main;
}
@Override
public int getMenu() {
return R.menu.main;
}
@Override
public void closeActivity() {
closeDrawers();
moveTaskToBack(true);
}
@Override
public void closeActivity() {
closeDrawers();
moveTaskToBack(true);
}
}

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

@ -1,7 +1,6 @@ @@ -1,7 +1,6 @@
package acr.browser.lightning.activity;
import android.animation.ObjectAnimator;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
@ -9,6 +8,7 @@ import android.content.DialogInterface.OnClickListener; @@ -9,6 +8,7 @@ import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
@ -31,223 +31,225 @@ import acr.browser.lightning.utils.Utils; @@ -31,223 +31,225 @@ import acr.browser.lightning.utils.Utils;
public class ReadingActivity extends AppCompatActivity {
private TextView mTitle;
private TextView mBody;
private boolean mInvert;
private String mUrl = null;
private PreferenceManager mPreferences;
private int mTextSize;
private static final float XXLARGE = 30.0f;
private static final float XLARGE = 26.0f;
private static final float LARGE = 22.0f;
private static final float MEDIUM = 18.0f;
private static final float SMALL = 14.0f;
private static final float XSMALL = 10.0f;
@Override
protected void onCreate(Bundle savedInstanceState) {
mPreferences = PreferenceManager.getInstance();
mInvert = mPreferences.getInvertColors();
if (mInvert) {
this.setTheme(R.style.Theme_SettingsTheme_Dark);
}
super.onCreate(savedInstanceState);
setContentView(R.layout.reading_view);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
mTitle = (TextView) findViewById(R.id.textViewTitle);
mBody = (TextView) findViewById(R.id.textViewBody);
mTextSize = mPreferences.getReadingTextSize();
mBody.setTextSize(getTextSize(mTextSize));
mTitle.setText(getString(R.string.untitled));
mBody.setText(getString(R.string.loading));
mTitle.setVisibility(View.INVISIBLE);
mBody.setVisibility(View.INVISIBLE);
Intent intent = getIntent();
if (!loadPage(intent)) {
setText(getString(R.string.untitled), getString(R.string.loading_failed));
}
}
private float getTextSize(int size) {
switch (size) {
case 0:
return XSMALL;
case 1:
return SMALL;
case 2:
return MEDIUM;
case 3:
return LARGE;
case 4:
return XLARGE;
case 5:
return XXLARGE;
default:
return MEDIUM;
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.reading, menu);
return super.onCreateOptionsMenu(menu);
}
protected boolean loadPage(Intent intent) {
if (intent == null) {
return false;
}
mUrl = intent.getStringExtra(Constants.LOAD_READING_URL);
if (mUrl == null) {
return false;
}
getSupportActionBar().setTitle(Utils.getDomainName(mUrl));
new PageLoader(this).execute(mUrl);
return true;
}
private class PageLoader extends AsyncTask<String, Void, Void> {
private final Context mContext;
private ProgressDialog mProgressDialog;
private String mTitleText;
private List<String> mBodyText;
public PageLoader(Context context) {
mContext = context;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
mProgressDialog = new ProgressDialog(mContext);
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
mProgressDialog.setCancelable(false);
mProgressDialog.setIndeterminate(true);
mProgressDialog.setMessage(mContext.getString(R.string.loading));
mProgressDialog.show();
}
@Override
protected Void doInBackground(String... params) {
HtmlFetcher fetcher = new HtmlFetcher();
try {
JResult result = fetcher.fetchAndExtract(params[0], 2500, true);
mTitleText = result.getTitle();
mBodyText = result.getTextList();
} catch (Exception e) {
mTitleText = "";
mBodyText = new ArrayList<>();
e.printStackTrace();
} catch (OutOfMemoryError e) {
System.gc();
mTitleText = "";
mBodyText = new ArrayList<>();
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Void result) {
mProgressDialog.dismiss();
if (mTitleText.isEmpty() || mBodyText.isEmpty()) {
setText(getString(R.string.untitled), getString(R.string.loading_failed));
} else {
StringBuilder builder = new StringBuilder();
for (String text : mBodyText) {
builder.append(text).append("\n\n");
}
setText(mTitleText, builder.toString());
}
super.onPostExecute(result);
}
}
private void setText(String title, String body) {
if (mTitle.getVisibility() == View.INVISIBLE) {
mTitle.setAlpha(0.0f);
mTitle.setVisibility(View.VISIBLE);
mTitle.setText(title);
ObjectAnimator animator = ObjectAnimator.ofFloat(mTitle, "alpha", 1.0f);
animator.setDuration(300);
animator.start();
} else {
mTitle.setText(title);
}
if (mBody.getVisibility() == View.INVISIBLE) {
mBody.setAlpha(0.0f);
mBody.setVisibility(View.VISIBLE);
mBody.setText(body);
ObjectAnimator animator = ObjectAnimator.ofFloat(mBody, "alpha", 1.0f);
animator.setDuration(300);
animator.start();
} else {
mBody.setText(body);
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.invert_item:
mPreferences.setInvertColors(!mInvert);
Intent read = new Intent(this, ReadingActivity.class);
read.putExtra(Constants.LOAD_READING_URL, mUrl);
startActivity(read);
finish();
break;
case R.id.text_size_item:
AlertDialog.Builder builder = new AlertDialog.Builder(this);
LayoutInflater inflater = this.getLayoutInflater();
View view = inflater.inflate(R.layout.seek_layout, null);
final SeekBar bar = (SeekBar) view.findViewById(R.id.text_size_seekbar);
bar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar view, int size, boolean user) {
mBody.setTextSize(getTextSize(size));
}
@Override
public void onStartTrackingTouch(SeekBar arg0) {
}
@Override
public void onStopTrackingTouch(SeekBar arg0) {
}
});
bar.setMax(5);
bar.setProgress(mTextSize);
builder.setView(view);
builder.setTitle(R.string.size);
builder.setPositiveButton(android.R.string.ok, new OnClickListener() {
@Override
public void onClick(DialogInterface arg0, int arg1) {
mTextSize = bar.getProgress();
mBody.setTextSize(getTextSize(mTextSize));
mPreferences.setReadingTextSize(bar.getProgress());
}
});
builder.show();
break;
default:
finish();
break;
}
return super.onOptionsItemSelected(item);
}
private TextView mTitle;
private TextView mBody;
private boolean mInvert;
private String mUrl = null;
private PreferenceManager mPreferences;
private int mTextSize;
private static final float XXLARGE = 30.0f;
private static final float XLARGE = 26.0f;
private static final float LARGE = 22.0f;
private static final float MEDIUM = 18.0f;
private static final float SMALL = 14.0f;
private static final float XSMALL = 10.0f;
@Override
protected void onCreate(Bundle savedInstanceState) {
mPreferences = PreferenceManager.getInstance();
mInvert = mPreferences.getInvertColors();
if (mInvert) {
this.setTheme(R.style.Theme_SettingsTheme_Dark);
}
super.onCreate(savedInstanceState);
setContentView(R.layout.reading_view);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
if (getSupportActionBar() != null)
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
mTitle = (TextView) findViewById(R.id.textViewTitle);
mBody = (TextView) findViewById(R.id.textViewBody);
mTextSize = mPreferences.getReadingTextSize();
mBody.setTextSize(getTextSize(mTextSize));
mTitle.setText(getString(R.string.untitled));
mBody.setText(getString(R.string.loading));
mTitle.setVisibility(View.INVISIBLE);
mBody.setVisibility(View.INVISIBLE);
Intent intent = getIntent();
if (!loadPage(intent)) {
setText(getString(R.string.untitled), getString(R.string.loading_failed));
}
}
private float getTextSize(int size) {
switch (size) {
case 0:
return XSMALL;
case 1:
return SMALL;
case 2:
return MEDIUM;
case 3:
return LARGE;
case 4:
return XLARGE;
case 5:
return XXLARGE;
default:
return MEDIUM;
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.reading, menu);
return super.onCreateOptionsMenu(menu);
}
private boolean loadPage(Intent intent) {
if (intent == null) {
return false;
}
mUrl = intent.getStringExtra(Constants.LOAD_READING_URL);
if (mUrl == null) {
return false;
}
if (getSupportActionBar() != null)
getSupportActionBar().setTitle(Utils.getDomainName(mUrl));
new PageLoader(this).execute(mUrl);
return true;
}
private class PageLoader extends AsyncTask<String, Void, Void> {
private final Context mContext;
private ProgressDialog mProgressDialog;
private String mTitleText;
private List<String> mBodyText;
public PageLoader(Context context) {
mContext = context;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
mProgressDialog = new ProgressDialog(mContext);
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
mProgressDialog.setCancelable(false);
mProgressDialog.setIndeterminate(true);
mProgressDialog.setMessage(mContext.getString(R.string.loading));
mProgressDialog.show();
}
@Override
protected Void doInBackground(String... params) {
HtmlFetcher fetcher = new HtmlFetcher();
try {
JResult result = fetcher.fetchAndExtract(params[0], 2500, true);
mTitleText = result.getTitle();
mBodyText = result.getTextList();
} catch (Exception e) {
mTitleText = "";
mBodyText = new ArrayList<>();
e.printStackTrace();
} catch (OutOfMemoryError e) {
System.gc();
mTitleText = "";
mBodyText = new ArrayList<>();
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Void result) {
mProgressDialog.dismiss();
if (mTitleText.isEmpty() || mBodyText.isEmpty()) {
setText(getString(R.string.untitled), getString(R.string.loading_failed));
} else {
StringBuilder builder = new StringBuilder();
for (String text : mBodyText) {
builder.append(text).append("\n\n");
}
setText(mTitleText, builder.toString());
}
super.onPostExecute(result);
}
}
private void setText(String title, String body) {
if (mTitle.getVisibility() == View.INVISIBLE) {
mTitle.setAlpha(0.0f);
mTitle.setVisibility(View.VISIBLE);
mTitle.setText(title);
ObjectAnimator animator = ObjectAnimator.ofFloat(mTitle, "alpha", 1.0f);
animator.setDuration(300);
animator.start();
} else {
mTitle.setText(title);
}
if (mBody.getVisibility() == View.INVISIBLE) {
mBody.setAlpha(0.0f);
mBody.setVisibility(View.VISIBLE);
mBody.setText(body);
ObjectAnimator animator = ObjectAnimator.ofFloat(mBody, "alpha", 1.0f);
animator.setDuration(300);
animator.start();
} else {
mBody.setText(body);
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.invert_item:
mPreferences.setInvertColors(!mInvert);
Intent read = new Intent(this, ReadingActivity.class);
read.putExtra(Constants.LOAD_READING_URL, mUrl);
startActivity(read);
finish();
break;
case R.id.text_size_item:
AlertDialog.Builder builder = new AlertDialog.Builder(this);
LayoutInflater inflater = this.getLayoutInflater();
View view = inflater.inflate(R.layout.seek_layout, null);
final SeekBar bar = (SeekBar) view.findViewById(R.id.text_size_seekbar);
bar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar view, int size, boolean user) {
mBody.setTextSize(getTextSize(size));
}
@Override
public void onStartTrackingTouch(SeekBar arg0) {
}
@Override
public void onStopTrackingTouch(SeekBar arg0) {
}
});
bar.setMax(5);
bar.setProgress(mTextSize);
builder.setView(view);
builder.setTitle(R.string.size);
builder.setPositiveButton(android.R.string.ok, new OnClickListener() {
@Override
public void onClick(DialogInterface arg0, int arg1) {
mTextSize = bar.getProgress();
mBody.setTextSize(getTextSize(mTextSize));
mPreferences.setReadingTextSize(bar.getProgress());
}
});
builder.show();
break;
default:
finish();
break;
}
return super.onOptionsItemSelected(item);
}
}

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

@ -17,7 +17,7 @@ import acr.browser.lightning.R; @@ -17,7 +17,7 @@ import acr.browser.lightning.R;
public class SettingsActivity extends ThemableSettingsActivity {
private static List<String> fragments = new ArrayList<>();
private static final List<String> fragments = new ArrayList<>();
@Override
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 { @@ -33,9 +33,7 @@ public abstract class ThemableActivity extends AppCompatActivity {
}
protected void restart() {
final Bundle outState = new Bundle();
onSaveInstanceState(outState);
final Intent intent = new Intent(this, getClass());
Intent intent = getIntent();
finish();
overridePendingTransition(0, 0);
startActivity(intent);

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

@ -6,8 +6,9 @@ import android.os.Bundle; @@ -6,8 +6,9 @@ import android.os.Bundle;
import acr.browser.lightning.R;
import acr.browser.lightning.preference.PreferenceManager;
import acr.browser.lightning.utils.ThemeUtils;
public abstract class ThemableSettingsActivity extends AppCompatPreferenceActivity {
public abstract class ThemableSettingsActivity extends AppCompatPreferenceActivity {
private int mTheme;
@ -16,11 +17,15 @@ public abstract class ThemableSettingsActivity extends AppCompatPreferenceActivi @@ -16,11 +17,15 @@ public abstract class ThemableSettingsActivity extends AppCompatPreferenceActivi
mTheme = PreferenceManager.getInstance().getUseTheme();
// 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);
this.getWindow().setBackgroundDrawable(new ColorDrawable(ThemeUtils.getPrimaryColorDark(this)));
} else if (mTheme == 2) {
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);
}

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

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

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

@ -30,398 +30,422 @@ import acr.browser.lightning.utils.Utils; @@ -30,398 +30,422 @@ import acr.browser.lightning.utils.Utils;
public class BookmarkManager {
private final Context mContext;
private static final String TITLE = "title";
private static final String URL = "url";
private static final String FOLDER = "folder";
private static final String ORDER = "order";
private static final String FILE_BOOKMARKS = "bookmarks.dat";
private static SortedMap<String, Integer> mBookmarkMap = new TreeMap<>(
String.CASE_INSENSITIVE_ORDER);
private static BookmarkManager mInstance;
private final Context mContext;
private static final String TITLE = "title";
private static final String URL = "url";
private static final String FOLDER = "folder";
private static final String ORDER = "order";
private static final String FILE_BOOKMARKS = "bookmarks.dat";
private static SortedMap<String, Integer> mBookmarkMap = new TreeMap<>(
String.CASE_INSENSITIVE_ORDER);
private static BookmarkManager mInstance;
public static BookmarkManager getInstance(Context context) {
if (mInstance == null) {
mInstance = new BookmarkManager(context);
}
return mInstance;
}
public static BookmarkManager getInstance(Context context) {
if (mInstance == null) {
mInstance = new BookmarkManager(context);
}
return mInstance;
}
private BookmarkManager(Context context) {
mContext = context;
mBookmarkMap = getBookmarkUrls();
}
private BookmarkManager(Context context) {
mContext = context;
mBookmarkMap = getBookmarkUrls();
}
/**
* This method adds the the HistoryItem item to permanent bookmark storage
*
* @param item
*/
public synchronized boolean addBookmark(HistoryItem item) {
File bookmarksFile = new File(mContext.getFilesDir(), FILE_BOOKMARKS);
if (item.getUrl() == null || mBookmarkMap.containsKey(item.getUrl())) {
return false;
}
try {
BufferedWriter bookmarkWriter = new BufferedWriter(new FileWriter(bookmarksFile, true));
JSONObject object = new JSONObject();
object.put(TITLE, item.getTitle());
object.put(URL, item.getUrl());
object.put(FOLDER, item.getFolder());
object.put(ORDER, item.getOrder());
bookmarkWriter.write(object.toString());
bookmarkWriter.newLine();
bookmarkWriter.close();
mBookmarkMap.put(item.getUrl(), 1);
} catch (IOException | JSONException e) {
e.printStackTrace();
}
return true;
}
/**
* This method adds the the HistoryItem item to permanent bookmark storage
*
* @param item the item to add
*/
public synchronized boolean addBookmark(HistoryItem item) {
File bookmarksFile = new File(mContext.getFilesDir(), FILE_BOOKMARKS);
if (item.getUrl() == null || mBookmarkMap.containsKey(item.getUrl())) {
return false;
}
BufferedWriter bookmarkWriter = null;
try {
bookmarkWriter = new BufferedWriter(new FileWriter(bookmarksFile, true));
JSONObject object = new JSONObject();
object.put(TITLE, item.getTitle());
object.put(URL, item.getUrl());
object.put(FOLDER, item.getFolder());
object.put(ORDER, item.getOrder());
bookmarkWriter.write(object.toString());
bookmarkWriter.newLine();
bookmarkWriter.close();
mBookmarkMap.put(item.getUrl(), 1);
} catch (IOException | JSONException e) {
e.printStackTrace();
} finally {
Utils.close(bookmarkWriter);
}
return true;
}
/**
* This method adds the list of HistoryItems to permanent bookmark storage
*
* @param list
*/
public synchronized void addBookmarkList(List<HistoryItem> list) {
File bookmarksFile = new File(mContext.getFilesDir(), FILE_BOOKMARKS);
try {
BufferedWriter bookmarkWriter = new BufferedWriter(new FileWriter(bookmarksFile, true));
for (HistoryItem item : list) {
if (item.getUrl() != null && !mBookmarkMap.containsKey(item.getUrl())) {
JSONObject object = new JSONObject();
object.put(TITLE, item.getTitle());
object.put(URL, item.getUrl());
object.put(FOLDER, item.getFolder());
object.put(ORDER, item.getOrder());
bookmarkWriter.write(object.toString());
bookmarkWriter.newLine();
mBookmarkMap.put(item.getUrl(), 1);
}
}
bookmarkWriter.close();
} catch (IOException | JSONException e) {
e.printStackTrace();
}
}
/**
* This method adds the list of HistoryItems to permanent bookmark storage
*
* @param list the list of HistoryItems to add to bookmarks
*/
private synchronized void addBookmarkList(List<HistoryItem> list) {
File bookmarksFile = new File(mContext.getFilesDir(), FILE_BOOKMARKS);
BufferedWriter bookmarkWriter = null;
try {
bookmarkWriter = new BufferedWriter(new FileWriter(bookmarksFile, true));
JSONObject object = new JSONObject();
for (HistoryItem item : list) {
if (item.getUrl() != null && !mBookmarkMap.containsKey(item.getUrl())) {
object.put(TITLE, item.getTitle());
object.put(URL, item.getUrl());
object.put(FOLDER, item.getFolder());
object.put(ORDER, item.getOrder());
bookmarkWriter.write(object.toString());
bookmarkWriter.newLine();
mBookmarkMap.put(item.getUrl(), 1);
}
}
} catch (IOException | JSONException e) {
e.printStackTrace();
} finally {
Utils.close(bookmarkWriter);
}
}
/**
* This method deletes the bookmark with the given url
*
* @param url
*/
public synchronized boolean deleteBookmark(String url) {
List<HistoryItem> list;
if (url == null) {
return false;
}
mBookmarkMap.remove(url);
list = getBookmarks(false);
File bookmarksFile = new File(mContext.getFilesDir(), FILE_BOOKMARKS);
boolean bookmarkDeleted = false;
try {
BufferedWriter fileWriter = new BufferedWriter(new FileWriter(bookmarksFile, false));
for (HistoryItem item : list) {
if (!item.getUrl().equalsIgnoreCase(url)) {
JSONObject object = new JSONObject();
object.put(TITLE, item.getTitle());
object.put(URL, item.getUrl());
object.put(FOLDER, item.getFolder());
object.put(ORDER, item.getOrder());
fileWriter.write(object.toString());
fileWriter.newLine();
} else {
bookmarkDeleted = true;
}
}
fileWriter.close();
} catch (IOException | JSONException e) {
e.printStackTrace();
}
return bookmarkDeleted;
}
/**
* This method deletes the bookmark with the given url
*
* @param url the url of the bookmark to delete
*/
public synchronized boolean deleteBookmark(String url) {
List<HistoryItem> list;
if (url == null) {
return false;
}
mBookmarkMap.remove(url);
list = getBookmarks(false);
File bookmarksFile = new File(mContext.getFilesDir(), FILE_BOOKMARKS);
boolean bookmarkDeleted = false;
BufferedWriter fileWriter = null;
try {
fileWriter = new BufferedWriter(new FileWriter(bookmarksFile, false));
JSONObject object = new JSONObject();
for (HistoryItem item : list) {
if (!item.getUrl().equalsIgnoreCase(url)) {
object.put(TITLE, item.getTitle());
object.put(URL, item.getUrl());
object.put(FOLDER, item.getFolder());
object.put(ORDER, item.getOrder());
fileWriter.write(object.toString());
fileWriter.newLine();
} else {
bookmarkDeleted = true;
}
}
} catch (IOException | JSONException e) {
e.printStackTrace();
} finally {
Utils.close(fileWriter);
}
return bookmarkDeleted;
}
/**
* This method exports the stored bookmarks to a text file in the device's
* external download directory
*/
public synchronized void exportBookmarks() {
List<HistoryItem> bookmarkList = getBookmarks(true);
File bookmarksExport = new File(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),
"BookmarksExport.txt");
int counter = 0;
while (bookmarksExport.exists()) {
counter++;
bookmarksExport = new File(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),
"BookmarksExport-" + counter + ".txt");
}
try {
BufferedWriter bookmarkWriter = new BufferedWriter(new FileWriter(bookmarksExport,
false));
for (HistoryItem item : bookmarkList) {
JSONObject object = new JSONObject();
object.put(TITLE, item.getTitle());
object.put(URL, item.getUrl());
object.put(FOLDER, item.getFolder());
object.put(ORDER, item.getOrder());
bookmarkWriter.write(object.toString());
bookmarkWriter.newLine();
}
bookmarkWriter.close();
Toast.makeText(
mContext,
mContext.getString(R.string.bookmark_export_path) + " "
+ bookmarksExport.getPath(), Toast.LENGTH_SHORT).show();
} catch (IOException | JSONException e) {
e.printStackTrace();
}
/**
* This method exports the stored bookmarks to a text file in the device's
* external download directory
*/
public synchronized void exportBookmarks() {
List<HistoryItem> bookmarkList = getBookmarks(true);
File bookmarksExport = new File(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),
"BookmarksExport.txt");
int counter = 0;
while (bookmarksExport.exists()) {
counter++;
bookmarksExport = new File(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),
"BookmarksExport-" + counter + ".txt");
}
BufferedWriter bookmarkWriter = null;
try {
bookmarkWriter = new BufferedWriter(new FileWriter(bookmarksExport,
false));
JSONObject object = new JSONObject();
for (HistoryItem item : bookmarkList) {
object.put(TITLE, item.getTitle());
object.put(URL, item.getUrl());
object.put(FOLDER, item.getFolder());
object.put(ORDER, item.getOrder());
bookmarkWriter.write(object.toString());
bookmarkWriter.newLine();
}
if (mContext != null)
Toast.makeText(
mContext,
mContext.getString(R.string.bookmark_export_path) + ' '
+ bookmarksExport.getPath(), Toast.LENGTH_SHORT).show();
} catch (IOException | JSONException e) {
e.printStackTrace();
} finally {
Utils.close(bookmarkWriter);
}
}
}
/**
* This method returns a list of all stored bookmarks
*
* @return
*/
public synchronized List<HistoryItem> getBookmarks(boolean sort) {
List<HistoryItem> bookmarks = new ArrayList<>();
File bookmarksFile = new File(mContext.getFilesDir(), FILE_BOOKMARKS);
try {
BufferedReader bookmarksReader = new BufferedReader(new FileReader(bookmarksFile));
String line;
while ((line = bookmarksReader.readLine()) != null) {
JSONObject object = new JSONObject(line);
HistoryItem item = new HistoryItem();
item.setTitle(object.getString(TITLE));
item.setUrl(object.getString(URL));
item.setFolder(object.getString(FOLDER));
item.setOrder(object.getInt(ORDER));
item.setImageId(R.drawable.ic_bookmark);
bookmarks.add(item);
}
bookmarksReader.close();
} catch (IOException | JSONException e) {
e.printStackTrace();
}
if (sort) {
Collections.sort(bookmarks, new SortIgnoreCase());
}
return bookmarks;
}
/**
* This method returns a list of all stored bookmarks
*
* @return returns a list of bookmarks that can be sorted
*/
public synchronized List<HistoryItem> getBookmarks(boolean sort) {
List<HistoryItem> bookmarks = new ArrayList<>();
File bookmarksFile = new File(mContext.getFilesDir(), FILE_BOOKMARKS);
BufferedReader bookmarksReader = null;
try {
bookmarksReader = new BufferedReader(new FileReader(bookmarksFile));
String line;
while ((line = bookmarksReader.readLine()) != null) {
JSONObject object = new JSONObject(line);
HistoryItem item = new HistoryItem();
item.setTitle(object.getString(TITLE));
item.setUrl(object.getString(URL));
item.setFolder(object.getString(FOLDER));
item.setOrder(object.getInt(ORDER));
item.setImageId(R.drawable.ic_bookmark);
bookmarks.add(item);
}
} catch (IOException | JSONException e) {
e.printStackTrace();
} finally {
Utils.close(bookmarksReader);
}
if (sort) {
Collections.sort(bookmarks, new SortIgnoreCase());
}
return bookmarks;
}
/**
* This method returns a list of bookmarks located in the specified folder
*
* @param folder
* @return
*/
public synchronized List<HistoryItem> getBookmarksFromFolder(String folder) {
List<HistoryItem> bookmarks = new ArrayList<>();
File bookmarksFile = new File(mContext.getFilesDir(), FILE_BOOKMARKS);
try {
BufferedReader bookmarksReader = new BufferedReader(new FileReader(bookmarksFile));
String line;
while ((line = bookmarksReader.readLine()) != null) {
JSONObject object = new JSONObject(line);
if (object.getString(FOLDER).equals(folder)) {
HistoryItem item = new HistoryItem();
item.setTitle(object.getString(TITLE));
item.setUrl(object.getString(URL));
item.setFolder(object.getString(FOLDER));
item.setOrder(object.getInt(ORDER));
item.setImageId(R.drawable.ic_bookmark);
bookmarks.add(item);
}
}
bookmarksReader.close();
} catch (IOException | JSONException e) {
e.printStackTrace();
}
return bookmarks;
}
/**
* This method returns a list of bookmarks located in the specified folder
*
* @param folder the name of the folder to retrieve bookmarks from
* @return a list of bookmarks found in that folder
*/
public synchronized List<HistoryItem> getBookmarksFromFolder(String folder) {
List<HistoryItem> bookmarks = new ArrayList<>();
File bookmarksFile = new File(mContext.getFilesDir(), FILE_BOOKMARKS);
BufferedReader bookmarksReader = null;
try {
bookmarksReader = new BufferedReader(new FileReader(bookmarksFile));
String line;
while ((line = bookmarksReader.readLine()) != null) {
JSONObject object = new JSONObject(line);
if (object.getString(FOLDER).equals(folder)) {
HistoryItem item = new HistoryItem();
item.setTitle(object.getString(TITLE));
item.setUrl(object.getString(URL));
item.setFolder(object.getString(FOLDER));
item.setOrder(object.getInt(ORDER));
item.setImageId(R.drawable.ic_bookmark);
bookmarks.add(item);
}
}
bookmarksReader.close();
} catch (IOException | JSONException e) {
e.printStackTrace();
} finally {
Utils.close(bookmarksReader);
}
return bookmarks;
}
/**
* Method is used internally for searching the bookmarks
*
* @return
*/
private synchronized SortedMap<String, Integer> getBookmarkUrls() {
SortedMap<String, Integer> map = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
File bookmarksFile = new File(mContext.getFilesDir(), FILE_BOOKMARKS);
try {
BufferedReader bookmarksReader = new BufferedReader(new FileReader(bookmarksFile));
String line;
while ((line = bookmarksReader.readLine()) != null) {
JSONObject object = new JSONObject(line);
map.put(object.getString(URL), 1);
}
bookmarksReader.close();
} catch (JSONException | IOException e) {
e.printStackTrace();
}
return map;
}
/**
* Method is used internally for searching the bookmarks
*
* @return a sorted map of all bookmarks, useful for seeing if a bookmark exists
*/
private synchronized SortedMap<String, Integer> getBookmarkUrls() {
SortedMap<String, Integer> map = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
File bookmarksFile = new File(mContext.getFilesDir(), FILE_BOOKMARKS);
BufferedReader bookmarksReader = null;
try {
bookmarksReader = new BufferedReader(new FileReader(bookmarksFile));
String line;
while ((line = bookmarksReader.readLine()) != null) {
JSONObject object = new JSONObject(line);
map.put(object.getString(URL), 1);
}
bookmarksReader.close();
} catch (JSONException | IOException e) {
e.printStackTrace();
} finally {
Utils.close(bookmarksReader);
}
return map;
}
/**
* This method returns a list of all folders
*
* @return
*/
public synchronized List<HistoryItem> getFolders() {
List<HistoryItem> folders = new ArrayList<>();
SortedMap<String, Integer> folderMap = new TreeMap<>(
String.CASE_INSENSITIVE_ORDER);
File bookmarksFile = new File(mContext.getFilesDir(), FILE_BOOKMARKS);
try {
BufferedReader bookmarksReader = new BufferedReader(new FileReader(bookmarksFile));
String line;
while ((line = bookmarksReader.readLine()) != null) {
JSONObject object = new JSONObject(line);
String folderName = object.getString(FOLDER);
if (!folderName.isEmpty() && !folderMap.containsKey(folderName)) {
HistoryItem item = new HistoryItem();
item.setTitle(folderName);
item.setUrl(Constants.FOLDER + folderName);
folderMap.put(folderName, 1);
folders.add(item);
}
}
bookmarksReader.close();
} catch (IOException | JSONException e) {
e.printStackTrace();
}
return folders;
}
/**
* This method returns a list of all folders
*
* @return a list of all folders
*/
public synchronized List<HistoryItem> getFolders() {
List<HistoryItem> folders = new ArrayList<>();
SortedMap<String, Integer> folderMap = new TreeMap<>(
String.CASE_INSENSITIVE_ORDER);
File bookmarksFile = new File(mContext.getFilesDir(), FILE_BOOKMARKS);
BufferedReader bookmarksReader = null;
try {
bookmarksReader = new BufferedReader(new FileReader(bookmarksFile));
String line;
while ((line = bookmarksReader.readLine()) != null) {
JSONObject object = new JSONObject(line);
String folderName = object.getString(FOLDER);
if (!folderName.isEmpty() && !folderMap.containsKey(folderName)) {
HistoryItem item = new HistoryItem();
item.setTitle(folderName);
item.setUrl(Constants.FOLDER + folderName);
folderMap.put(folderName, 1);
folders.add(item);
}
}
} catch (IOException | JSONException e) {
e.printStackTrace();
} finally {
Utils.close(bookmarksReader);
}
return folders;
}
/**
* This method imports all bookmarks that are included in the device's
* permanent bookmark storage
*/
public synchronized void importBookmarksFromBrowser(Context context) {
if (PreferenceManager.getInstance().getSystemBrowserPresent()) {
/**
* This method imports all bookmarks that are included in the device's
* permanent bookmark storage
*/
public synchronized void importBookmarksFromBrowser(Context context) {
if (PreferenceManager.getInstance().getSystemBrowserPresent()) {
List<HistoryItem> bookmarkList = new ArrayList<>();
String[] columns = new String[] { Browser.BookmarkColumns.TITLE,
Browser.BookmarkColumns.URL };
String selection = Browser.BookmarkColumns.BOOKMARK + " = 1";
Cursor cursor = mContext.getContentResolver().query(Browser.BOOKMARKS_URI, columns,
selection, null, null);
List<HistoryItem> bookmarkList = new ArrayList<>();
String[] columns = new String[]{Browser.BookmarkColumns.TITLE,
Browser.BookmarkColumns.URL};
String selection = Browser.BookmarkColumns.BOOKMARK + " = 1";
Cursor cursor = mContext.getContentResolver().query(Browser.BOOKMARKS_URI, columns,
selection, null, null);
if (cursor == null)
return;
String title, url;
int number = 0;
if (cursor.moveToFirst()) {
do {
title = cursor.getString(0);
url = cursor.getString(1);
if (title.isEmpty()) {
title = Utils.getDomainName(url);
}
number++;
bookmarkList.add(new HistoryItem(url, title));
} while (cursor.moveToNext());
}
String title, url;
int number = 0;
if (cursor.moveToFirst()) {
do {
title = cursor.getString(0);
url = cursor.getString(1);
if (title.isEmpty()) {
title = Utils.getDomainName(url);
}
number++;
bookmarkList.add(new HistoryItem(url, title));
} while (cursor.moveToNext());
}
cursor.close();
addBookmarkList(bookmarkList);
cursor.close();
addBookmarkList(bookmarkList);
Utils.showToast(context,
number + " " + mContext.getResources().getString(R.string.message_import));
} else {
Utils.createInformativeDialog(context,
mContext.getResources().getString(R.string.title_error), mContext
.getResources().getString(R.string.dialog_import_error));
}
}
Utils.showToast(mContext,
number + " " + mContext.getResources().getString(R.string.message_import));
} else {
Utils.createInformativeDialog(context,
mContext.getResources().getString(R.string.title_error), mContext
.getResources().getString(R.string.dialog_import_error));
}
}
/**
* This method imports the bookmarks from a backup file that is located on
* external storage
*
* @param file the file to attempt to import bookmarks from
*/
public synchronized void importBookmarksFromFile(File file, Context context) {
if (file == null) {
return;
}
List<HistoryItem> list = new ArrayList<>();
BufferedReader bookmarksReader = null;
try {
bookmarksReader = new BufferedReader(new FileReader(file));
String line;
int number = 0;
while ((line = bookmarksReader.readLine()) != null) {
JSONObject object = new JSONObject(line);
HistoryItem item = new HistoryItem();
item.setTitle(object.getString(TITLE));
item.setUrl(object.getString(URL));
item.setFolder(object.getString(FOLDER));
item.setOrder(object.getInt(ORDER));
list.add(item);
number++;
}
addBookmarkList(list);
Utils.showToast(context,
number + " " + mContext.getResources().getString(R.string.message_import));
} catch (IOException | JSONException e) {
e.printStackTrace();
Utils.createInformativeDialog(context,
mContext.getResources().getString(R.string.title_error), mContext
.getResources().getString(R.string.import_bookmark_error));
} finally {
Utils.close(bookmarksReader);
}
}
/**
* This method imports the bookmarks from a backup file that is located on
* external storage
*
* @param dir
* @param file
*/
public synchronized void importBookmarksFromFile(File file, Context context) {
if (file == null) {
return;
}
List<HistoryItem> list = new ArrayList<>();
try {
BufferedReader bookmarksReader = new BufferedReader(new FileReader(file));
String line;
int number = 0;
while ((line = bookmarksReader.readLine()) != null) {
JSONObject object = new JSONObject(line);
HistoryItem item = new HistoryItem();
item.setTitle(object.getString(TITLE));
item.setUrl(object.getString(URL));
item.setFolder(object.getString(FOLDER));
item.setOrder(object.getInt(ORDER));
list.add(item);
number++;
}
bookmarksReader.close();
addBookmarkList(list);
Utils.showToast(mContext,
number + " " + mContext.getResources().getString(R.string.message_import));
} catch (IOException | JSONException e) {
e.printStackTrace();
Utils.createInformativeDialog(context,
mContext.getResources().getString(R.string.title_error), mContext
.getResources().getString(R.string.import_bookmark_error));
}
}
/**
* This method overwrites the entire bookmark file with the list of
* bookmarks. This is useful when an edit has been made to one or more
* bookmarks in the list
*
* @param list the list of bookmarks to overwrite the old ones with
*/
public synchronized void overwriteBookmarks(List<HistoryItem> list) {
File bookmarksFile = new File(mContext.getFilesDir(), FILE_BOOKMARKS);
BufferedWriter bookmarkWriter = null;
try {
bookmarkWriter = new BufferedWriter(new FileWriter(bookmarksFile, false));
JSONObject object = new JSONObject();
for (HistoryItem item : list) {
object.put(TITLE, item.getTitle());
object.put(URL, item.getUrl());
object.put(FOLDER, item.getFolder());
object.put(ORDER, item.getOrder());
bookmarkWriter.write(object.toString());
bookmarkWriter.newLine();
}
} catch (IOException | JSONException e) {
e.printStackTrace();
} finally {
Utils.close(bookmarkWriter);
}
}
/**
* This method overwrites the entire bookmark file with the list of
* bookmarks. This is useful when an edit has been made to one or more
* bookmarks in the list
*
* @param list
*/
public synchronized void overwriteBookmarks(List<HistoryItem> list) {
File bookmarksFile = new File(mContext.getFilesDir(), FILE_BOOKMARKS);
try {
BufferedWriter bookmarkWriter = new BufferedWriter(new FileWriter(bookmarksFile, false));
for (HistoryItem item : list) {
JSONObject object = new JSONObject();
object.put(TITLE, item.getTitle());
object.put(URL, item.getUrl());
object.put(FOLDER, item.getFolder());
object.put(ORDER, item.getOrder());
bookmarkWriter.write(object.toString());
bookmarkWriter.newLine();
}
bookmarkWriter.close();
} catch (IOException | JSONException e) {
e.printStackTrace();
}
}
private class SortIgnoreCase implements Comparator<HistoryItem> {
private class SortIgnoreCase implements Comparator<HistoryItem> {
public int compare(HistoryItem o1, HistoryItem o2) {
if (o1 == null || o2 == null || o1.getTitle() == null || o2.getTitle() == null) {
return 0;
}
return o1.getTitle().toLowerCase(Locale.getDefault())
.compareTo(o2.getTitle().toLowerCase(Locale.getDefault()));
}
public int compare(HistoryItem o1, HistoryItem o2) {
if (o1 == null || o2 == null || o1.getTitle() == null || o2.getTitle() == null) {
return 0;
}
return o1.getTitle().toLowerCase(Locale.getDefault())
.compareTo(o2.getTitle().toLowerCase(Locale.getDefault()));
}
}
}
private static final String[] DEV = {"https://twitter.com/RestainoAnthony", "The Developer"};
private static final String[] FACEBOOK = {"https://www.facebook.com/", "Facebook"};
private static final String[] TWITTER = {"https://twitter.com", "Twitter"};
private static final String[] GOOGLE = {"https://www.google.com/", "Google"};
private static final String[] YAHOO = {"https://www.yahoo.com/", "Yahoo"};
public static final String[][] DEFAULT_BOOKMARKS = {
DEV,
FACEBOOK,
TWITTER,
GOOGLE,
YAHOO
};
private static final String[] DEV = {"https://twitter.com/RestainoAnthony", "The Developer"};
private static final String[] FACEBOOK = {"https://www.facebook.com/", "Facebook"};
private static final String[] TWITTER = {"https://twitter.com", "Twitter"};
private static final String[] GOOGLE = {"https://www.google.com/", "Google"};
private static final String[] YAHOO = {"https://www.yahoo.com/", "Yahoo"};
public static final String[][] DEFAULT_BOOKMARKS = {
DEV,
FACEBOOK,
TWITTER,
GOOGLE,
YAHOO
};
}

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

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

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

@ -4,7 +4,6 @@ @@ -4,7 +4,6 @@
package acr.browser.lightning.download;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.DownloadManager;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
@ -14,6 +13,7 @@ import android.content.pm.PackageManager; @@ -14,6 +13,7 @@ import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Environment;
import android.support.v7.app.AlertDialog;
import android.text.TextUtils;
import android.util.Log;
import android.webkit.CookieManager;
@ -22,197 +22,190 @@ import android.widget.Toast; @@ -22,197 +22,190 @@ import android.widget.Toast;
import acr.browser.lightning.R;
import acr.browser.lightning.preference.PreferenceManager;
import acr.browser.lightning.utils.Utils;
/**
* Handle download requests
*/
public class DownloadHandler {
private static final String LOGTAG = "DLHandler";
/**
* Notify the host application a download should be done, or that the data
* should be streamed if a streaming viewer is available.
*
* @param activity
* Activity requesting the download.
* @param url
* The full url to the content that should be downloaded
* @param userAgent
* User agent of the downloading application.
* @param contentDisposition
* Content-disposition http header, if present.
* @param mimetype
* The mimetype of the content reported by the server
* @param privateBrowsing
* If the request is coming from a private browsing tab.
*/
public static void onDownloadStart(Activity activity, String url, String userAgent,
String contentDisposition, String mimetype, boolean privateBrowsing) {
// if we're dealing wih A/V content that's not explicitly marked
// for download, check if it's streamable.
if (contentDisposition == null
|| !contentDisposition.regionMatches(true, 0, "attachment", 0, 10)) {
// query the package manager to see if there's a registered handler
// that matches.
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse(url), mimetype);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
ResolveInfo info = activity.getPackageManager().resolveActivity(intent,
PackageManager.MATCH_DEFAULT_ONLY);
if (info != null) {
ComponentName myName = activity.getComponentName();
// If we resolved to ourselves, we don't want to attempt to
// load the url only to try and download it again.
if (!myName.getPackageName().equals(info.activityInfo.packageName)
|| !myName.getClassName().equals(info.activityInfo.name)) {
// someone (other than us) knows how to handle this mime
// type with this scheme, don't download.
try {
activity.startActivity(intent);
return;
} catch (ActivityNotFoundException ex) {
// Best behavior is to fall back to a download in this
// case
}
}
}
}
onDownloadStartNoStream(activity, url, userAgent, contentDisposition, mimetype,
privateBrowsing);
}
// This is to work around the fact that java.net.URI throws Exceptions
// instead of just encoding URL's properly
// Helper method for onDownloadStartNoStream
private static String encodePath(String path) {
char[] chars = path.toCharArray();
boolean needed = false;
for (char c : chars) {
if (c == '[' || c == ']' || c == '|') {
needed = true;
break;
}
}
if (!needed) {
return path;
}
StringBuilder sb = new StringBuilder("");
for (char c : chars) {
if (c == '[' || c == ']' || c == '|') {
sb.append('%');
sb.append(Integer.toHexString(c));
} else {
sb.append(c);
}
}
return sb.toString();
}
/**
* Notify the host application a download should be done, even if there is a
* streaming viewer available for thise type.
*
* @param activity
* Activity requesting the download.
* @param url
* The full url to the content that should be downloaded
* @param userAgent
* User agent of the downloading application.
* @param contentDisposition
* Content-disposition http header, if present.
* @param mimetype
* The mimetype of the content reported by the server
* @param privateBrowsing
* If the request is coming from a private browsing tab.
*/
/* package */
private static void onDownloadStartNoStream(Activity activity, String url, String userAgent,
String contentDisposition, String mimetype, boolean privateBrowsing) {
String filename = URLUtil.guessFileName(url, contentDisposition, mimetype);
// Check to see if we have an SDCard
String status = Environment.getExternalStorageState();
if (!status.equals(Environment.MEDIA_MOUNTED)) {
int title;
String msg;
// Check to see if the SDCard is busy, same as the music app
if (status.equals(Environment.MEDIA_SHARED)) {
msg = activity.getString(R.string.download_sdcard_busy_dlg_msg);
title = R.string.download_sdcard_busy_dlg_title;
} else {
msg = activity.getString(R.string.download_no_sdcard_dlg_msg, filename);
title = R.string.download_no_sdcard_dlg_title;
}
new AlertDialog.Builder(activity).setTitle(title)
.setIcon(android.R.drawable.ic_dialog_alert).setMessage(msg)
.setPositiveButton(R.string.action_ok, null).show();
return;
}
// java.net.URI is a lot stricter than KURL so we have to encode some
// extra characters. Fix for b 2538060 and b 1634719
WebAddress webAddress;
try {
webAddress = new WebAddress(url);
webAddress.setPath(encodePath(webAddress.getPath()));
} catch (Exception e) {
// This only happens for very bad urls, we want to catch the
// exception here
Log.e(LOGTAG, "Exception while trying to parse url '" + url + '\'', e);
return;
}
String addressString = webAddress.toString();
Uri uri = Uri.parse(addressString);
final DownloadManager.Request request;
try {
request = new DownloadManager.Request(uri);
} catch (IllegalArgumentException e) {
Toast.makeText(activity, R.string.cannot_download, Toast.LENGTH_SHORT).show();
return;
}
request.setMimeType(mimetype);
// set downloaded file destination to /sdcard/Download.
// or, should it be set to one of several Environment.DIRECTORY* dirs
// depending on mimetype?
String location = PreferenceManager.getInstance().getDownloadDirectory();
request.setDestinationInExternalPublicDir(location, filename);
// let this downloaded file be scanned by MediaScanner - so that it can
// show up in Gallery app, for example.
request.allowScanningByMediaScanner();
request.setDescription(webAddress.getHost());
// XXX: Have to use the old url since the cookies were stored using the
// old percent-encoded url.
String cookies = CookieManager.getInstance().getCookie(url);
request.addRequestHeader("cookie", cookies);
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
if (mimetype == null) {
if (TextUtils.isEmpty(addressString)) {
return;
}
// We must have long pressed on a link or image to download it. We
// are not sure of the mimetype in this case, so do a head request
new FetchUrlMimeType(activity, request, addressString, cookies, userAgent).start();
} else {
final DownloadManager manager = (DownloadManager) activity
.getSystemService(Context.DOWNLOAD_SERVICE);
new Thread("Browser download") {
@Override
public void run() {
manager.enqueue(request);
}
}.start();
Toast.makeText(activity, R.string.download_pending, Toast.LENGTH_SHORT).show();
}
}
private static final String LOGTAG = "DLHandler";
/**
* Notify the host application a download should be done, or that the data
* should be streamed if a streaming viewer is available.
*
* @param activity Activity requesting the download.
* @param url The full url to the content that should be downloaded
* @param userAgent User agent of the downloading application.
* @param contentDisposition Content-disposition http header, if present.
* @param mimetype The mimetype of the content reported by the server
*/
public static void onDownloadStart(Activity activity, String url, String userAgent,
String contentDisposition, String mimetype) {
// if we're dealing wih A/V content that's not explicitly marked
// for download, check if it's streamable.
if (contentDisposition == null
|| !contentDisposition.regionMatches(true, 0, "attachment", 0, 10)) {
// query the package manager to see if there's a registered handler
// that matches.
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse(url), mimetype);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
ResolveInfo info = activity.getPackageManager().resolveActivity(intent,
PackageManager.MATCH_DEFAULT_ONLY);
if (info != null) {
ComponentName myName = activity.getComponentName();
// If we resolved to ourselves, we don't want to attempt to
// load the url only to try and download it again.
if (!myName.getPackageName().equals(info.activityInfo.packageName)
|| !myName.getClassName().equals(info.activityInfo.name)) {
// someone (other than us) knows how to handle this mime
// type with this scheme, don't download.
try {
activity.startActivity(intent);
return;
} catch (ActivityNotFoundException ex) {
// Best behavior is to fall back to a download in this
// case
}
}
}
}
onDownloadStartNoStream(activity, url, userAgent, contentDisposition, mimetype
);
}
// This is to work around the fact that java.net.URI throws Exceptions
// instead of just encoding URL's properly
// Helper method for onDownloadStartNoStream
private static String encodePath(String path) {
char[] chars = path.toCharArray();
boolean needed = false;
for (char c : chars) {
if (c == '[' || c == ']' || c == '|') {
needed = true;
break;
}
}
if (!needed) {
return path;
}
StringBuilder sb = new StringBuilder("");
for (char c : chars) {
if (c == '[' || c == ']' || c == '|') {
sb.append('%');
sb.append(Integer.toHexString(c));
} else {
sb.append(c);
}
}
return sb.toString();
}
/**
* Notify the host application a download should be done, even if there is a
* streaming viewer available for thise type.
*
* @param activity Activity requesting the download.
* @param url The full url to the content that should be downloaded
* @param userAgent User agent of the downloading application.
* @param contentDisposition Content-disposition http header, if present.
* @param mimetype The mimetype of the content reported by the server
*/
/* package */
private static void onDownloadStartNoStream(final Activity activity, String url, String userAgent,
String contentDisposition, String mimetype) {
String filename = URLUtil.guessFileName(url, contentDisposition, mimetype);
// Check to see if we have an SDCard
String status = Environment.getExternalStorageState();
if (!status.equals(Environment.MEDIA_MOUNTED)) {
int title;
String msg;
// Check to see if the SDCard is busy, same as the music app
if (status.equals(Environment.MEDIA_SHARED)) {
msg = activity.getString(R.string.download_sdcard_busy_dlg_msg);
title = R.string.download_sdcard_busy_dlg_title;
} else {
msg = activity.getString(R.string.download_no_sdcard_dlg_msg, filename);
title = R.string.download_no_sdcard_dlg_title;
}
new AlertDialog.Builder(activity).setTitle(title)
.setIcon(android.R.drawable.ic_dialog_alert).setMessage(msg)
.setPositiveButton(R.string.action_ok, null).show();
return;
}
// java.net.URI is a lot stricter than KURL so we have to encode some
// extra characters. Fix for b 2538060 and b 1634719
WebAddress webAddress;
try {
webAddress = new WebAddress(url);
webAddress.setPath(encodePath(webAddress.getPath()));
} catch (Exception e) {
// This only happens for very bad urls, we want to catch the
// exception here
Log.e(LOGTAG, "Exception while trying to parse url '" + url + '\'', e);
return;
}
String addressString = webAddress.toString();
Uri uri = Uri.parse(addressString);
final DownloadManager.Request request;
try {
request = new DownloadManager.Request(uri);
} catch (IllegalArgumentException e) {
Toast.makeText(activity, R.string.cannot_download, Toast.LENGTH_SHORT).show();
return;
}
request.setMimeType(mimetype);
// set downloaded file destination to /sdcard/Download.
// or, should it be set to one of several Environment.DIRECTORY* dirs
// depending on mimetype?
String location = PreferenceManager.getInstance().getDownloadDirectory();
request.setDestinationInExternalPublicDir(location, filename);
// let this downloaded file be scanned by MediaScanner - so that it can
// show up in Gallery app, for example.
request.allowScanningByMediaScanner();
request.setDescription(webAddress.getHost());
// XXX: Have to use the old url since the cookies were stored using the
// old percent-encoded url.
String cookies = CookieManager.getInstance().getCookie(url);
request.addRequestHeader("cookie", cookies);
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
if (mimetype == null) {
if (TextUtils.isEmpty(addressString)) {
return;
}
// We must have long pressed on a link or image to download it. We
// are not sure of the mimetype in this case, so do a head request
new FetchUrlMimeType(activity, request, addressString, cookies, userAgent).start();
} else {
final DownloadManager manager = (DownloadManager) activity
.getSystemService(Context.DOWNLOAD_SERVICE);
new Thread("Browser download") {
@Override
public void run() {
try {
manager.enqueue(request);
} catch (IllegalArgumentException e) {
// Probably got a bad URL or something
e.printStackTrace();
Utils.showToast(activity, R.string.cannot_download);
}
}
}.start();
Toast.makeText(activity, R.string.download_pending, Toast.LENGTH_SHORT).show();
}
}
}

140
app/src/main/java/acr/browser/lightning/download/FetchUrlMimeType.java

@ -26,82 +26,82 @@ import acr.browser.lightning.R; @@ -26,82 +26,82 @@ import acr.browser.lightning.R;
*/
public class FetchUrlMimeType extends Thread {
private final Context mContext;
private final Context mContext;
private final DownloadManager.Request mRequest;
private final DownloadManager.Request mRequest;
private final String mUri;
private final String mUri;
private final String mCookies;
private final String mCookies;
private final String mUserAgent;
private final String mUserAgent;
public FetchUrlMimeType(Context context, DownloadManager.Request request, String uri,
String cookies, String userAgent) {
mContext = context.getApplicationContext();
mRequest = request;
mUri = uri;
mCookies = cookies;
mUserAgent = userAgent;
Toast.makeText(mContext, R.string.download_pending, Toast.LENGTH_SHORT).show();
}
public FetchUrlMimeType(Context context, DownloadManager.Request request, String uri,
String cookies, String userAgent) {
mContext = context.getApplicationContext();
mRequest = request;
mUri = uri;
mCookies = cookies;
mUserAgent = userAgent;
Toast.makeText(mContext, R.string.download_pending, Toast.LENGTH_SHORT).show();
}
@Override
public void run() {
// User agent is likely to be null, though the AndroidHttpClient
// seems ok with that.
String mimeType = null;
String contentDisposition = null;
HttpURLConnection connection = null;
try {
URL url = new URL(mUri);
connection = (HttpURLConnection) url.openConnection();
if (mCookies != null && mCookies.length() > 0) {
connection.addRequestProperty("Cookie", mCookies);
connection.setRequestProperty("User-Agent", mUserAgent);
}
connection.connect();
// We could get a redirect here, but if we do lets let
// the download manager take care of it, and thus trust that
// the server sends the right mimetype
if (connection.getResponseCode() == 200) {
String header = connection.getHeaderField("Content-Type");
if (header != null) {
mimeType = header;
final int semicolonIndex = mimeType.indexOf(';');
if (semicolonIndex != -1) {
mimeType = mimeType.substring(0, semicolonIndex);
}
}
String contentDispositionHeader = connection.getHeaderField("Content-Disposition");
if (contentDispositionHeader != null) {
contentDisposition = contentDispositionHeader;
}
}
} catch (IllegalArgumentException | IOException ex) {
if (connection != null)
connection.disconnect();
} finally {
if (connection != null)
connection.disconnect();
}
@Override
public void run() {
// User agent is likely to be null, though the AndroidHttpClient
// seems ok with that.
String mimeType = null;
String contentDisposition = null;
HttpURLConnection connection = null;
try {
URL url = new URL(mUri);
connection = (HttpURLConnection) url.openConnection();
if (mCookies != null && mCookies.length() > 0) {
connection.addRequestProperty("Cookie", mCookies);
connection.setRequestProperty("User-Agent", mUserAgent);
}
connection.connect();
// We could get a redirect here, but if we do lets let
// the download manager take care of it, and thus trust that
// the server sends the right mimetype
if (connection.getResponseCode() == 200) {
String header = connection.getHeaderField("Content-Type");
if (header != null) {
mimeType = header;
final int semicolonIndex = mimeType.indexOf(';');
if (semicolonIndex != -1) {
mimeType = mimeType.substring(0, semicolonIndex);
}
}
String contentDispositionHeader = connection.getHeaderField("Content-Disposition");
if (contentDispositionHeader != null) {
contentDisposition = contentDispositionHeader;
}
}
} catch (IllegalArgumentException | IOException ex) {
if (connection != null)
connection.disconnect();
} finally {
if (connection != null)
connection.disconnect();
}
if (mimeType != null) {
if (mimeType.equalsIgnoreCase("text/plain")
|| mimeType.equalsIgnoreCase("application/octet-stream")) {
String newMimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(
MimeTypeMap.getFileExtensionFromUrl(mUri));
if (newMimeType != null) {
mRequest.setMimeType(newMimeType);
}
}
String filename = URLUtil.guessFileName(mUri, contentDisposition, mimeType);
mRequest.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, filename);
}
if (mimeType != null) {
if (mimeType.equalsIgnoreCase("text/plain")
|| mimeType.equalsIgnoreCase("application/octet-stream")) {
String newMimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(
MimeTypeMap.getFileExtensionFromUrl(mUri));
if (newMimeType != null) {
mRequest.setMimeType(newMimeType);
}
}
String filename = URLUtil.guessFileName(mUri, contentDisposition, mimeType);
mRequest.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, filename);
}
// Start the download
DownloadManager manager = (DownloadManager) mContext
.getSystemService(Context.DOWNLOAD_SERVICE);
manager.enqueue(mRequest);
}
// Start the download
DownloadManager manager = (DownloadManager) mContext
.getSystemService(Context.DOWNLOAD_SERVICE);
manager.enqueue(mRequest);
}
}

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

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

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

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

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

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

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

@ -4,15 +4,14 @@ @@ -4,15 +4,14 @@
package acr.browser.lightning.fragment;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.Preference;
import android.preference.PreferenceFragment;
import android.support.v7.app.AlertDialog;
import acr.browser.lightning.R;
import acr.browser.lightning.activity.SettingsActivity;
import acr.browser.lightning.preference.PreferenceManager;
public class DisplaySettingsFragment extends PreferenceFragment implements Preference.OnPreferenceClickListener, Preference.OnPreferenceChangeListener {
@ -28,7 +27,7 @@ public class DisplaySettingsFragment extends PreferenceFragment implements Prefe @@ -28,7 +27,7 @@ public class DisplaySettingsFragment extends PreferenceFragment implements Prefe
private Activity mActivity;
private PreferenceManager mPreferences;
private CheckBoxPreference cbstatus, cbfullscreen, cbviewport, cboverview, cbreflow;
private Preference theme, textsize;
private Preference theme;
private String[] mThemeOptions;
private int mCurrentTheme;
@ -50,7 +49,7 @@ public class DisplaySettingsFragment extends PreferenceFragment implements Prefe @@ -50,7 +49,7 @@ public class DisplaySettingsFragment extends PreferenceFragment implements Prefe
mCurrentTheme = mPreferences.getUseTheme();
theme = findPreference(SETTINGS_THEME);
textsize = findPreference(SETTINGS_TEXTSIZE);
Preference textsize = findPreference(SETTINGS_TEXTSIZE);
cbstatus = (CheckBoxPreference) findPreference(SETTINGS_HIDESTATUSBAR);
cbfullscreen = (CheckBoxPreference) findPreference(SETTINGS_FULLSCREEN);
cbviewport = (CheckBoxPreference) findPreference(SETTINGS_VIEWPORT);
@ -163,7 +162,8 @@ public class DisplaySettingsFragment extends PreferenceFragment implements Prefe @@ -163,7 +162,8 @@ public class DisplaySettingsFragment extends PreferenceFragment implements Prefe
@Override
public void onClick(DialogInterface dialog, int which) {
if (mCurrentTheme != mPreferences.getUseTheme()) {
((SettingsActivity) getActivity()).restart();
// ((SettingsActivity) getActivity()).restart();
getActivity().onBackPressed();
}
}
});
@ -171,7 +171,8 @@ public class DisplaySettingsFragment extends PreferenceFragment implements Prefe @@ -171,7 +171,8 @@ public class DisplaySettingsFragment extends PreferenceFragment implements Prefe
@Override
public void onCancel(DialogInterface dialog) {
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 @@ @@ -4,14 +4,16 @@
package acr.browser.lightning.fragment;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.preference.CheckBoxPreference;
import android.preference.Preference;
import android.preference.PreferenceFragment;
import android.support.v7.app.AlertDialog;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;
@ -468,10 +470,16 @@ public class GeneralSettingsFragment extends PreferenceFragment implements Prefe @@ -468,10 +470,16 @@ public class GeneralSettingsFragment extends PreferenceFragment implements Prefe
v.setPadding(padding, padding, 0, padding);
layout.addView(v);
layout.addView(getDownload);
if (API < 16) {
if (API < Build.VERSION_CODES.JELLY_BEAN) {
layout.setBackgroundDrawable(getResources().getDrawable(android.R.drawable.edit_text));
} 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.setPositiveButton(getResources().getString(R.string.action_ok),

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

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

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

@ -1,23 +1,5 @@ @@ -1,23 +1,5 @@
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.app.Activity;
import android.content.Context;
@ -36,399 +18,398 @@ import android.widget.Filterable; @@ -36,399 +18,398 @@ import android.widget.Filterable;
import android.widget.ImageView;
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.database.BookmarkManager;
import acr.browser.lightning.database.HistoryDatabase;
import acr.browser.lightning.database.HistoryItem;
import acr.browser.lightning.preference.PreferenceManager;
import acr.browser.lightning.utils.Utils;
public class SearchAdapter extends BaseAdapter implements Filterable {
private List<HistoryItem> mHistory;
private List<HistoryItem> mBookmarks;
private List<HistoryItem> mSuggestions;
private List<HistoryItem> mFilteredList;
private List<HistoryItem> mAllBookmarks;
private HistoryDatabase mDatabaseHandler;
private final Context mContext;
private boolean mUseGoogle = true;
private boolean mIsExecuting = false;
private final boolean mDarkTheme;
private final boolean mIncognito;
private final BookmarkManager mBookmarkManager;
private static final String ENCODING = "ISO-8859-1";
private static final long INTERVAL_DAY = 86400000;
private final String mSearchSubtitle;
private static final int API = Build.VERSION.SDK_INT;
private final Theme mTheme;
private SearchFilter mFilter;
public SearchAdapter(Context context, boolean dark, boolean incognito) {
mDatabaseHandler = HistoryDatabase.getInstance(context.getApplicationContext());
mTheme = context.getTheme();
mFilteredList = new ArrayList<>();
mHistory = new ArrayList<>();
mBookmarks = new ArrayList<>();
mSuggestions = new ArrayList<>();
mBookmarkManager = BookmarkManager.getInstance(context.getApplicationContext());
mAllBookmarks = mBookmarkManager.getBookmarks(true);
mUseGoogle = PreferenceManager.getInstance().getGoogleSearchSuggestionsEnabled();
mContext = context;
mSearchSubtitle = mContext.getString(R.string.suggestion);
mDarkTheme = dark || incognito;
mIncognito = incognito;
Thread delete = new Thread(new Runnable() {
@Override
public void run() {
deleteOldCacheFiles(mContext);
}
});
delete.start();
}
private void deleteOldCacheFiles(Context context) {
File dir = new File(context.getCacheDir().toString());
String[] fileList = dir.list(new NameFilter());
long earliestTimeAllowed = System.currentTimeMillis() - INTERVAL_DAY;
for (String fileName : fileList) {
File file = new File(dir.getPath() + fileName);
if (earliestTimeAllowed > file.lastModified()) {
file.delete();
}
}
}
private class NameFilter implements FilenameFilter {
private static final String ext = ".sgg";
@Override
public boolean accept(File dir, String filename) {
return filename.endsWith(ext);
}
}
public void refreshPreferences() {
mUseGoogle = PreferenceManager.getInstance().getGoogleSearchSuggestionsEnabled();
if (!mUseGoogle && mSuggestions != null) {
mSuggestions.clear();
}
mDatabaseHandler = HistoryDatabase.getInstance(mContext.getApplicationContext());
}
public void refreshBookmarks() {
mAllBookmarks = mBookmarkManager.getBookmarks(true);
}
@Override
public int getCount() {
if (mFilteredList != null) {
return mFilteredList.size();
} else {
return 0;
}
}
@Override
public Object getItem(int position) {
return mFilteredList.get(position);
}
@Override
public long getItemId(int position) {
return 0;
}
@SuppressWarnings("deprecation")
@SuppressLint("NewApi")
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
SuggestionHolder holder;
if (row == null) {
LayoutInflater inflater = ((Activity) mContext).getLayoutInflater();
row = inflater.inflate(R.layout.two_line_autocomplete, parent, false);
holder = new SuggestionHolder();
holder.mTitle = (TextView) row.findViewById(R.id.title);
holder.mUrl = (TextView) row.findViewById(R.id.url);
holder.mImage = (ImageView) row.findViewById(R.id.suggestionIcon);
row.setTag(holder);
} else {
holder = (SuggestionHolder) row.getTag();
}
HistoryItem web = mFilteredList.get(position);
holder.mTitle.setText(web.getTitle());
holder.mUrl.setText(web.getUrl());
int imageId = R.drawable.ic_bookmark;
switch (web.getImageId()) {
case R.drawable.ic_bookmark: {
if (!mDarkTheme) {
imageId = R.drawable.ic_bookmark;
} else {
holder.mTitle.setTextColor(Color.WHITE);
imageId = R.drawable.ic_bookmark_dark;
}
break;
}
case R.drawable.ic_search: {
if (!mDarkTheme) {
imageId = R.drawable.ic_search;
} else {
holder.mTitle.setTextColor(Color.WHITE);
imageId = R.drawable.ic_search_dark;
}
break;
}
case R.drawable.ic_history: {
if (!mDarkTheme) {
imageId = R.drawable.ic_history;
} else {
holder.mTitle.setTextColor(Color.WHITE);
imageId = R.drawable.ic_history_dark;
}
break;
}
}
if (API < Build.VERSION_CODES.LOLLIPOP) {
holder.mImage.setImageDrawable(mContext.getResources().getDrawable(imageId));
} else {
holder.mImage.setImageDrawable(mContext.getResources().getDrawable(imageId, mTheme));
}
return row;
}
public void setContents(List<HistoryItem> list) {
if (mFilteredList != null) {
mFilteredList.clear();
mFilteredList.addAll(list);
} else {
mFilteredList = list;
}
notifyDataSetChanged();
}
@Override
public Filter getFilter() {
if (mFilter == null) {
mFilter = new SearchFilter();
}
return mFilter;
}
private class SearchFilter extends Filter {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
if (constraint == null) {
return results;
}
String query = constraint.toString().toLowerCase(Locale.getDefault());
if (mUseGoogle && !mIncognito && !mIsExecuting) {
new RetrieveSearchSuggestions().execute(query);
}
int counter = 0;
mBookmarks = new ArrayList<>();
for (int n = 0; n < mAllBookmarks.size(); n++) {
if (counter >= 5) {
break;
}
if (mAllBookmarks.get(n).getTitle().toLowerCase(Locale.getDefault())
.startsWith(query)) {
mBookmarks.add(mAllBookmarks.get(n));
counter++;
} else if (mAllBookmarks.get(n).getUrl().contains(query)) {
mBookmarks.add(mAllBookmarks.get(n));
counter++;
}
}
if (mDatabaseHandler == null) {
mDatabaseHandler = HistoryDatabase.getInstance(mContext.getApplicationContext());
}
mHistory = mDatabaseHandler.findItemsContaining(constraint.toString());
results.count = 1;
return results;
}
@Override
public CharSequence convertResultToString(Object resultValue) {
return ((HistoryItem) resultValue).getUrl();
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
mFilteredList = getSuggestions();
notifyDataSetChanged();
}
}
private class SuggestionHolder {
ImageView mImage;
TextView mTitle;
TextView mUrl;
}
private class RetrieveSearchSuggestions extends AsyncTask<String, Void, List<HistoryItem>> {
private XmlPullParserFactory mFactory;
private XmlPullParser mXpp;
@Override
protected List<HistoryItem> doInBackground(String... arg0) {
mIsExecuting = true;
List<HistoryItem> filter = new ArrayList<>();
String query = arg0[0];
try {
query = query.replace(" ", "+");
URLEncoder.encode(query, ENCODING);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
File cache = downloadSuggestionsForQuery(query);
if (!cache.exists()) {
return filter;
}
InputStream fileInput = null;
try {
fileInput = new BufferedInputStream(new FileInputStream(cache));
if (mFactory == null) {
mFactory = XmlPullParserFactory.newInstance();
mFactory.setNamespaceAware(true);
}
if (mXpp == null) {
mXpp = mFactory.newPullParser();
}
mXpp.setInput(fileInput, ENCODING);
int eventType = mXpp.getEventType();
int counter = 0;
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_TAG && "suggestion".equals(mXpp.getName())) {
String suggestion = mXpp.getAttributeValue(null, "data");
filter.add(new HistoryItem(mSearchSubtitle + " \"" + suggestion + '"',
suggestion, R.drawable.ic_search));
counter++;
if (counter >= 5) {
break;
}
}
eventType = mXpp.next();
}
} catch (Exception e) {
return filter;
} finally {
if (fileInput != null) {
try {
fileInput.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return filter;
}
@Override
protected void onPostExecute(List<HistoryItem> result) {
mSuggestions = result;
mFilteredList = getSuggestions();
notifyDataSetChanged();
mIsExecuting = false;
}
}
private File downloadSuggestionsForQuery(String query) {
File cacheFile = new File(mContext.getCacheDir(), query.hashCode() + ".sgg");
if (System.currentTimeMillis() - INTERVAL_DAY < cacheFile.lastModified()) {
return cacheFile;
}
if (!isNetworkConnected(mContext)) {
return cacheFile;
}
try {
URL url = new URL("http://google.com/complete/search?q=" + query
+ "&output=toolbar&hl=en");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream in = connection.getInputStream();
if (in != null) {
FileOutputStream fos = new FileOutputStream(cacheFile);
int buffer;
while ((buffer = in.read()) != -1) {
fos.write(buffer);
}
fos.flush();
fos.close();
}
cacheFile.setLastModified(System.currentTimeMillis());
} catch (Exception e) {
e.printStackTrace();
}
return cacheFile;
}
private boolean isNetworkConnected(Context context) {
NetworkInfo networkInfo = getActiveNetworkInfo(context);
return networkInfo != null && networkInfo.isConnected();
}
private NetworkInfo getActiveNetworkInfo(Context context) {
ConnectivityManager connectivity = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivity == null) {
return null;
}
return connectivity.getActiveNetworkInfo();
}
//TODO Write simpler algorithm
private List<HistoryItem> getSuggestions() {
List<HistoryItem> filteredList = new ArrayList<>();
int suggestionsSize = (mSuggestions == null) ? 0 : mSuggestions.size();
int historySize = (mHistory == null) ? 0 : mHistory.size();
int bookmarkSize = (mBookmarks == null) ? 0 : mBookmarks.size();
int maxSuggestions = (bookmarkSize + historySize < 3) ? (5 - bookmarkSize - historySize)
: (bookmarkSize < 2) ? (4 - bookmarkSize) : (historySize < 1) ? 3 : 2;
int maxHistory = (suggestionsSize + bookmarkSize < 4) ? (5 - suggestionsSize - bookmarkSize)
: 1;
int maxBookmarks = (suggestionsSize + historySize < 3) ? (5 - suggestionsSize - historySize)
: 2;
if (!mUseGoogle || mIncognito) {
maxHistory++;
maxBookmarks++;
}
for (int n = 0; n < bookmarkSize && n < maxBookmarks; n++) {
filteredList.add(mBookmarks.get(n));
}
for (int n = 0; n < historySize && n < maxHistory; n++) {
filteredList.add(mHistory.get(n));
}
for (int n = 0; n < suggestionsSize && n < maxSuggestions; n++) {
filteredList.add(mSuggestions.get(n));
}
return filteredList;
}
private final List<HistoryItem> mHistory = new ArrayList<>();
private final List<HistoryItem> mBookmarks = new ArrayList<>();
private final List<HistoryItem> mSuggestions = new ArrayList<>();
private final List<HistoryItem> mFilteredList = new ArrayList<>();
private final List<HistoryItem> mAllBookmarks = new ArrayList<>();
private HistoryDatabase mDatabaseHandler;
private final Context mContext;
private boolean mUseGoogle = true;
private boolean mIsExecuting = false;
private final boolean mDarkTheme;
private final boolean mIncognito;
private final BookmarkManager mBookmarkManager;
private static final String ENCODING = "ISO-8859-1";
private static final long INTERVAL_DAY = 86400000;
private final String mSearchSubtitle;
private static final int API = Build.VERSION.SDK_INT;
private final Theme mTheme;
private SearchFilter mFilter;
public SearchAdapter(Context context, boolean dark, boolean incognito) {
mDatabaseHandler = HistoryDatabase.getInstance(context.getApplicationContext());
mTheme = context.getTheme();
mBookmarkManager = BookmarkManager.getInstance(context.getApplicationContext());
mAllBookmarks.addAll(mBookmarkManager.getBookmarks(true));
mUseGoogle = PreferenceManager.getInstance().getGoogleSearchSuggestionsEnabled();
mContext = context;
mSearchSubtitle = mContext.getString(R.string.suggestion);
mDarkTheme = dark || incognito;
mIncognito = incognito;
Thread delete = new Thread(new Runnable() {
@Override
public void run() {
deleteOldCacheFiles(mContext);
}
});
delete.start();
}
private void deleteOldCacheFiles(Context context) {
File dir = new File(context.getCacheDir().toString());
String[] fileList = dir.list(new NameFilter());
long earliestTimeAllowed = System.currentTimeMillis() - INTERVAL_DAY;
for (String fileName : fileList) {
File file = new File(dir.getPath() + fileName);
if (earliestTimeAllowed > file.lastModified()) {
file.delete();
}
}
}
private class NameFilter implements FilenameFilter {
private static final String ext = ".sgg";
@Override
public boolean accept(File dir, String filename) {
return filename.endsWith(ext);
}
}
public void refreshPreferences() {
mUseGoogle = PreferenceManager.getInstance().getGoogleSearchSuggestionsEnabled();
if (!mUseGoogle) {
mSuggestions.clear();
}
mDatabaseHandler = HistoryDatabase.getInstance(mContext.getApplicationContext());
}
public void refreshBookmarks() {
mAllBookmarks.clear();
mAllBookmarks.addAll(mBookmarkManager.getBookmarks(true));
}
@Override
public int getCount() {
return mFilteredList.size();
}
@Override
public Object getItem(int position) {
return mFilteredList.get(position);
}
@Override
public long getItemId(int position) {
return 0;
}
@SuppressWarnings("deprecation")
@SuppressLint("NewApi")
@Override
public View getView(int position, View convertView, ViewGroup parent) {
SuggestionHolder holder;
if (convertView == null) {
LayoutInflater inflater = ((Activity) mContext).getLayoutInflater();
convertView = inflater.inflate(R.layout.two_line_autocomplete, parent, false);
holder = new SuggestionHolder();
holder.mTitle = (TextView) convertView.findViewById(R.id.title);
holder.mUrl = (TextView) convertView.findViewById(R.id.url);
holder.mImage = (ImageView) convertView.findViewById(R.id.suggestionIcon);
convertView.setTag(holder);
} else {
holder = (SuggestionHolder) convertView.getTag();
}
HistoryItem web;
web = mFilteredList.get(position);
holder.mTitle.setText(web.getTitle());
holder.mUrl.setText(web.getUrl());
int imageId = R.drawable.ic_bookmark;
switch (web.getImageId()) {
case R.drawable.ic_bookmark: {
if (!mDarkTheme) {
imageId = R.drawable.ic_bookmark;
} else {
holder.mTitle.setTextColor(Color.WHITE);
imageId = R.drawable.ic_bookmark_dark;
}
break;
}
case R.drawable.ic_search: {
if (!mDarkTheme) {
imageId = R.drawable.ic_search;
} else {
holder.mTitle.setTextColor(Color.WHITE);
imageId = R.drawable.ic_search_dark;
}
break;
}
case R.drawable.ic_history: {
if (!mDarkTheme) {
imageId = R.drawable.ic_history;
} else {
holder.mTitle.setTextColor(Color.WHITE);
imageId = R.drawable.ic_history_dark;
}
break;
}
}
if (API < Build.VERSION_CODES.LOLLIPOP) {
holder.mImage.setImageDrawable(mContext.getResources().getDrawable(imageId));
} else {
holder.mImage.setImageDrawable(mContext.getResources().getDrawable(imageId, mTheme));
}
return convertView;
}
public void setContents(List<HistoryItem> list) {
mFilteredList.clear();
mFilteredList.addAll(list);
notifyDataSetChanged();
}
@Override
public Filter getFilter() {
if (mFilter == null) {
mFilter = new SearchFilter();
}
return mFilter;
}
private class SearchFilter extends Filter {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
if (constraint == null) {
return results;
}
String query = constraint.toString().toLowerCase(Locale.getDefault());
if (mUseGoogle && !mIncognito && !mIsExecuting) {
new RetrieveSearchSuggestions().execute(query);
}
int counter = 0;
mBookmarks.clear();
for (int n = 0; n < mAllBookmarks.size(); n++) {
if (counter >= 5) {
break;
}
if (mAllBookmarks.get(n).getTitle().toLowerCase(Locale.getDefault())
.startsWith(query)) {
mBookmarks.add(mAllBookmarks.get(n));
counter++;
} else if (mAllBookmarks.get(n).getUrl().contains(query)) {
mBookmarks.add(mAllBookmarks.get(n));
counter++;
}
}
if (mDatabaseHandler == null) {
mDatabaseHandler = HistoryDatabase.getInstance(mContext.getApplicationContext());
}
List<HistoryItem> historyList = mDatabaseHandler.findItemsContaining(constraint.toString());
mHistory.clear();
mHistory.addAll(historyList);
results.count = 1;
return results;
}
@Override
public CharSequence convertResultToString(Object resultValue) {
return ((HistoryItem) resultValue).getUrl();
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
mFilteredList.clear();
mFilteredList.addAll(getSuggestions());
notifyDataSetChanged();
}
}
private class SuggestionHolder {
ImageView mImage;
TextView mTitle;
TextView mUrl;
}
private class RetrieveSearchSuggestions extends AsyncTask<String, Void, List<HistoryItem>> {
private XmlPullParserFactory mFactory;
private XmlPullParser mXpp;
@Override
protected List<HistoryItem> doInBackground(String... arg0) {
mIsExecuting = true;
List<HistoryItem> filter = new ArrayList<>();
String query = arg0[0];
try {
query = query.replace(" ", "+");
URLEncoder.encode(query, ENCODING);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
File cache = downloadSuggestionsForQuery(query);
if (!cache.exists()) {
return filter;
}
InputStream fileInput = null;
try {
fileInput = new BufferedInputStream(new FileInputStream(cache));
if (mFactory == null) {
mFactory = XmlPullParserFactory.newInstance();
mFactory.setNamespaceAware(true);
}
if (mXpp == null) {
mXpp = mFactory.newPullParser();
}
mXpp.setInput(fileInput, ENCODING);
int eventType = mXpp.getEventType();
int counter = 0;
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_TAG && "suggestion".equals(mXpp.getName())) {
String suggestion = mXpp.getAttributeValue(null, "data");
filter.add(new HistoryItem(mSearchSubtitle + " \"" + suggestion + '"',
suggestion, R.drawable.ic_search));
counter++;
if (counter >= 5) {
break;
}
}
eventType = mXpp.next();
}
} catch (Exception e) {
return filter;
} finally {
Utils.close(fileInput);
}
return filter;
}
@Override
protected void onPostExecute(List<HistoryItem> result) {
mSuggestions.clear();
mSuggestions.addAll(result);
mFilteredList.clear();
mFilteredList.addAll(getSuggestions());
notifyDataSetChanged();
mIsExecuting = false;
}
}
private File downloadSuggestionsForQuery(String query) {
File cacheFile = new File(mContext.getCacheDir(), query.hashCode() + ".sgg");
if (System.currentTimeMillis() - INTERVAL_DAY < cacheFile.lastModified()) {
return cacheFile;
}
if (!isNetworkConnected(mContext)) {
return cacheFile;
}
try {
URL url = new URL("http://google.com/complete/search?q=" + query
+ "&output=toolbar&hl=en");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream in = connection.getInputStream();
if (in != null) {
FileOutputStream fos = new FileOutputStream(cacheFile);
int buffer;
while ((buffer = in.read()) != -1) {
fos.write(buffer);
}
fos.flush();
fos.close();
}
cacheFile.setLastModified(System.currentTimeMillis());
} catch (Exception e) {
e.printStackTrace();
}
return cacheFile;
}
private boolean isNetworkConnected(Context context) {
NetworkInfo networkInfo = getActiveNetworkInfo(context);
return networkInfo != null && networkInfo.isConnected();
}
private NetworkInfo getActiveNetworkInfo(Context context) {
ConnectivityManager connectivity = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivity == null) {
return null;
}
return connectivity.getActiveNetworkInfo();
}
//TODO Write simpler algorithm
private List<HistoryItem> getSuggestions() {
List<HistoryItem> filteredList = new ArrayList<>();
int suggestionsSize = mSuggestions.size();
int historySize = mHistory.size();
int bookmarkSize = mBookmarks.size();
int maxSuggestions = (bookmarkSize + historySize < 3) ? (5 - bookmarkSize - historySize)
: (bookmarkSize < 2) ? (4 - bookmarkSize) : (historySize < 1) ? 3 : 2;
int maxHistory = (suggestionsSize + bookmarkSize < 4) ? (5 - suggestionsSize - bookmarkSize)
: 1;
int maxBookmarks = (suggestionsSize + historySize < 3) ? (5 - suggestionsSize - historySize)
: 2;
for (int n = 0; n < bookmarkSize && n < maxBookmarks; n++) {
filteredList.add(mBookmarks.get(n));
}
for (int n = 0; n < historySize && n < maxHistory; n++) {
filteredList.add(mHistory.get(n));
}
for (int n = 0; n < suggestionsSize && n < maxSuggestions; n++) {
filteredList.add(mSuggestions.get(n));
}
return filteredList;
}
}

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

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

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

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

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

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

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

@ -230,7 +230,7 @@ public class HtmlFetcher { @@ -230,7 +230,7 @@ public class HtmlFetcher {
}
// 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
// return
// the resolved url relative to url!

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

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

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

@ -21,7 +21,7 @@ public class IntentUtils { @@ -21,7 +21,7 @@ public class IntentUtils {
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
"("
+ // begin group for schema

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

@ -0,0 +1,34 @@ @@ -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;
}
}

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

@ -5,7 +5,6 @@ package acr.browser.lightning.utils; @@ -5,7 +5,6 @@ package acr.browser.lightning.utils;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
@ -17,11 +16,14 @@ import android.graphics.BitmapFactory; @@ -17,11 +16,14 @@ import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Environment;
import android.support.annotation.StringRes;
import android.support.v7.app.AlertDialog;
import android.util.DisplayMetrics;
import android.util.Log;
import android.webkit.URLUtil;
import android.widget.Toast;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.net.URI;
@ -39,15 +41,15 @@ public final class Utils { @@ -39,15 +41,15 @@ public final class Utils {
}
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);
DownloadHandler.onDownloadStart(activity, url, userAgent, contentDisposition, null,
privateBrowsing);
DownloadHandler.onDownloadStart(activity, url, userAgent, contentDisposition, null
);
Log.i(Constants.TAG, "Downloading" + fileName);
}
public static Intent newEmailIntent(Context context, String address, String subject,
String body, String cc) {
public static Intent newEmailIntent(String address, String subject,
String body, String cc) {
Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_EMAIL, new String[] { address });
intent.putExtra(Intent.EXTRA_TEXT, body);
@ -63,11 +65,11 @@ public final class Utils { @@ -63,11 +65,11 @@ public final class Utils {
builder.setMessage(message)
.setCancelable(true)
.setPositiveButton(context.getResources().getString(R.string.action_ok),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
}
});
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
}
});
AlertDialog alert = builder.create();
alert.show();
}
@ -76,6 +78,10 @@ public final class Utils { @@ -76,6 +78,10 @@ public final class Utils {
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
*/
@ -237,4 +243,13 @@ public final class Utils { @@ -237,4 +243,13 @@ public final class Utils {
private static Bitmap mWebIconLight;
private static Bitmap mWebIconDark;
public static void close(Closeable closeable) {
if (closeable == null)
return;
try {
closeable.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

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

File diff suppressed because it is too large Load Diff

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

@ -1,10 +1,12 @@ @@ -1,10 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingLeft="4dp"
android:paddingStart="4dp">
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingEnd="4dp"
android:paddingLeft="4dp"
android:paddingRight="4dp"
android:paddingStart="4dp">
<LinearLayout
android:layout_width="match_parent"
@ -13,14 +15,14 @@ @@ -13,14 +15,14 @@
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/host"/>
android:text="@string/host" />
<EditText
android:id="@+id/proxyHost"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:inputType="text"/>
android:inputType="text" />
</LinearLayout>
<LinearLayout
@ -30,14 +32,14 @@ @@ -30,14 +32,14 @@
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/port"/>
android:text="@string/port" />
<EditText
android:id="@+id/proxyPort"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:inputType="number"/>
android:inputType="number" />
</LinearLayout>
</LinearLayout>

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

@ -1,6 +1,5 @@ @@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<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_height="wrap_content"
android:orientation="horizontal" >
@ -9,7 +8,6 @@ @@ -9,7 +8,6 @@
android:id="@+id/arrow_button"
android:layout_width="?attr/actionBarSize"
android:layout_height="?attr/actionBarSize"
android:layout_marginLeft="2dp"
android:layout_marginTop="2dp"
android:background="?attr/actionBarItemBackground"
android:clickable="true"

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

@ -3,22 +3,25 @@ @@ -3,22 +3,25 @@
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:clickable="false"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingBottom="3dp"
android:paddingEnd="6dp"
android:paddingLeft="6dp"
android:paddingTop="3dp"
android:gravity="center_vertical">
android:paddingRight="6dp"
android:paddingStart="6dp"
android:paddingTop="3dp">
<ImageView
android:id="@+id/suggestionIcon"
android:layout_width="25dp"
android:layout_height="25dp"/>
android:layout_height="25dp" />
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingLeft="5dp" >
android:paddingLeft="5dp">
<TextView
android:id="@+id/title"

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

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

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

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

Loading…
Cancel
Save