From 3c9cd73bf08a51559219df2c718458a67b85a95a Mon Sep 17 00:00:00 2001 From: Stefano Pacifici Date: Thu, 27 Aug 2015 16:47:55 +0200 Subject: [PATCH] Refactoring: Bookmarks as Fragment 1. Incognito mode in another process 2. Bookmarks as a Fragement using Otto 3. Initial bookmarks as fragment implementation --- app/build.gradle | 1 + app/src/main/AndroidManifest.xml | 3 +- .../lightning/activity/BrowserActivity.java | 669 ++++-------------- .../lightning/activity/MainActivity.java | 5 + .../browser/lightning/bus/BookmarkEvents.java | 78 ++ .../browser/lightning/bus/BrowserEvents.java | 44 ++ .../browser/lightning/bus/BusProvider.java | 19 + .../controller/BrowserController.java | 2 +- .../lightning/database/BookmarkManager.java | 59 +- .../lightning/fragment/BookmarksFragment.java | 493 +++++++++++++ .../preference/PreferenceManager.java | 9 - .../lightning/utils/DownloadImageTask.java | 127 ++++ .../acr/browser/lightning/utils/Utils.java | 19 + .../browser/lightning/view/LightningView.java | 11 +- app/src/main/res/layout/activity_main.xml | 14 +- app/src/main/res/layout/bookmark_drawer.xml | 6 +- .../main/res/layout/dialog_edit_bookmark.xml | 29 + app/src/main/res/raw/default_bookmarks.dat | 5 + external/netcipher | 2 +- 19 files changed, 1001 insertions(+), 594 deletions(-) create mode 100644 app/src/main/java/acr/browser/lightning/bus/BookmarkEvents.java create mode 100644 app/src/main/java/acr/browser/lightning/bus/BrowserEvents.java create mode 100644 app/src/main/java/acr/browser/lightning/bus/BusProvider.java create mode 100644 app/src/main/java/acr/browser/lightning/fragment/BookmarksFragment.java create mode 100644 app/src/main/java/acr/browser/lightning/utils/DownloadImageTask.java create mode 100644 app/src/main/res/layout/dialog_edit_bookmark.xml create mode 100644 app/src/main/res/raw/default_bookmarks.dat diff --git a/app/build.gradle b/app/build.gradle index a0c6770..9cc5b1e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -48,6 +48,7 @@ dependencies { compile 'com.android.support:design:23.0.0' compile 'com.android.support:recyclerview-v7:23.0.0' compile 'org.jsoup:jsoup:1.8.1' + compile 'com.squareup:otto:1.3.8' // Only Lightning Plus needs the proxy libraries lightningPlusCompile 'net.i2p.android:client:0.7' lightningPlusCompile(project(':libnetcipher')) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 1cc2031..8d8ec38 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -110,7 +110,8 @@ android:label="@string/app_name" android:launchMode="singleTask" android:theme="@style/Theme.DarkTheme" - android:windowSoftInputMode="stateHidden" > + android:windowSoftInputMode="stateHidden" + android:process=":incognito"> diff --git a/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java b/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java index 3a5482b..0c55ee0 100644 --- a/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java +++ b/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java @@ -30,7 +30,6 @@ import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.media.MediaPlayer; import android.net.Uri; -import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; import android.os.Handler; @@ -65,7 +64,6 @@ import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; import android.view.Window; import android.view.WindowManager; -import android.view.animation.AccelerateInterpolator; import android.view.animation.Animation; import android.view.animation.Animation.AnimationListener; import android.view.animation.DecelerateInterpolator; @@ -86,26 +84,26 @@ import android.widget.FrameLayout; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.LinearLayout; -import android.widget.ListView; import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.TextView.OnEditorActionListener; import android.widget.VideoView; +import com.squareup.otto.Subscribe; + import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; -import java.io.InputStream; -import java.net.HttpURLConnection; import java.net.URI; import java.net.URISyntaxException; -import java.net.URL; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import acr.browser.lightning.R; +import acr.browser.lightning.bus.BookmarkEvents; +import acr.browser.lightning.bus.BrowserEvents; +import acr.browser.lightning.bus.BusProvider; import acr.browser.lightning.constant.BookmarkPage; import acr.browser.lightning.constant.Constants; import acr.browser.lightning.constant.HistoryPage; @@ -133,9 +131,8 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements private DrawerLayout mDrawerLayout; private FrameLayout mBrowserFrame; private FullscreenHolder mFullscreenContainer; - private ListView mDrawerListRight; private RecyclerView mDrawerListLeft; - private LinearLayout mDrawerLeft, mDrawerRight, mUiLayout, mToolbarLayout; + private ViewGroup mDrawerLeft, mDrawerRight, mUiLayout, mToolbarLayout; private RelativeLayout mSearchBar; // List @@ -147,12 +144,11 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements // Views private AnimatedProgressBar mProgressBar; private AutoCompleteTextView mSearch; - private ImageView mArrowImage, mBookmarkTitleImage, mBookmarkImage; + private ImageView mArrowImage; private VideoView mVideoView; private View mCustomView, mVideoProgressView; // Adapter - private BookmarkViewAdapter mBookmarkAdapter; private LightningViewAdapter mTabAdapter; private SearchAdapter mSearchAdapter; @@ -180,7 +176,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements private PreferenceManager mPreferences; // Image - private Bitmap mDefaultVideoPoster, mWebpageBitmap, mFolderBitmap; + private Bitmap mDefaultVideoPoster, mWebpageBitmap; private final ColorDrawable mBackground = new ColorDrawable(); private Drawable mDeleteIcon, mRefreshIcon, mSearchIcon, mIcon; private DrawerArrowDrawable mArrowDrawable; @@ -196,7 +192,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements private static final FrameLayout.LayoutParams COVER_SCREEN_PARAMS = new FrameLayout.LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); - abstract boolean isIncognito(); + public abstract boolean isIncognito(); abstract void initializeTabs(); @@ -241,11 +237,8 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements // Drawer stutters otherwise mDrawerLeft.setLayerType(View.LAYER_TYPE_HARDWARE, null); mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); - mDrawerRight = (LinearLayout) findViewById(R.id.right_drawer); + mDrawerRight = (ViewGroup) findViewById(R.id.right_drawer); mDrawerRight.setLayerType(View.LAYER_TYPE_HARDWARE, null); - mDrawerListRight = (ListView) findViewById(R.id.right_drawer_list); - mBookmarkTitleImage = (ImageView) findViewById(R.id.starIcon); - mBookmarkTitleImage.setColorFilter(mIconColor, PorterDuff.Mode.SRC_IN); ImageView tabTitleImage = (ImageView) findViewById(R.id.plusIcon); tabTitleImage.setColorFilter(mIconColor, PorterDuff.Mode.SRC_IN); @@ -257,7 +250,6 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements mDrawerLayout.setDrawerListener(new DrawerLocker()); mWebpageBitmap = ThemeUtils.getThemedBitmap(this, R.drawable.ic_webpage, mDarkTheme); - mFolderBitmap = ThemeUtils.getThemedBitmap(this, R.drawable.ic_folder, mDarkTheme); mHomepage = mPreferences.getHomepage(); @@ -283,11 +275,6 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements } mDrawerListLeft.setAdapter(mTabAdapter); -// mDrawerListLeft.setOnItemClickListener(new DrawerItemClickListener()); -// mDrawerListLeft.setOnItemLongClickListener(new DrawerItemLongClickListener()); - - mDrawerListRight.setOnItemClickListener(new BookmarkItemClickListener()); - mDrawerListRight.setOnItemLongClickListener(new BookmarkItemLongClickListener()); mHistoryDatabase = HistoryDatabase.getInstance(getApplicationContext()); @@ -324,12 +311,9 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements setupFrameLayoutButton(R.id.action_back, R.id.icon_back); setupFrameLayoutButton(R.id.action_forward, R.id.icon_forward); - setupFrameLayoutButton(R.id.action_add_bookmark, R.id.icon_star); setupFrameLayoutButton(R.id.action_toggle_desktop, R.id.icon_desktop); setupFrameLayoutButton(R.id.action_reading, R.id.icon_reading); - mBookmarkImage = (ImageView) findViewById(R.id.icon_star); - // create the search EditText in the ToolBar mSearch = (AutoCompleteTextView) actionBar.getCustomView().findViewById(R.id.search); mUntitledTitle = getString(R.string.untitled); @@ -358,38 +342,11 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements @Override public void run() { - mBookmarkManager = BookmarkManager.getInstance(mActivity.getApplicationContext()); - setBookmarkDataSet(mBookmarkManager.getBookmarksFromFolder(null, true), false); - if (mBookmarkList.isEmpty() && mPreferences.getDefaultBookmarks()) { - for (String[] array : BookmarkManager.DEFAULT_BOOKMARKS) { - HistoryItem bookmark = new HistoryItem(array[0], array[1]); - if (mBookmarkManager.addBookmark(bookmark)) { - mBookmarkList.add(bookmark); - } - } - Collections.sort(mBookmarkList, new BookmarkManager.SortIgnoreCase()); - mPreferences.setDefaultBookmarks(false); - } - mBookmarkAdapter = new BookmarkViewAdapter(mActivity, R.layout.bookmark_list_item, - mBookmarkList); - mDrawerListRight.setAdapter(mBookmarkAdapter); initializeSearchSuggestions(mSearch); } }).run(); - View view = findViewById(R.id.bookmark_back_button); - view.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - if (mBookmarkManager == null) - return; - if (!mBookmarkManager.isRootFolder()) { - setBookmarkDataSet(mBookmarkManager.getBookmarksFromFolder(null, true), true); - } - } - }); - mDrawerLayout.setDrawerShadow(R.drawable.drawer_right_shadow, GravityCompat.END); mDrawerLayout.setDrawerShadow(R.drawable.drawer_left_shadow, GravityCompat.START); @@ -811,7 +768,9 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements return true; case R.id.action_add_bookmark: if (mCurrentView != null && !mCurrentView.getUrl().startsWith(Constants.FILE)) { - addBookmark(mCurrentView.getTitle(), mCurrentView.getUrl()); + BusProvider.getInstance() + .post(new BrowserEvents.AddBookmark(mCurrentView.getTitle(), + mCurrentView.getUrl())); } return true; case R.id.action_find: @@ -827,75 +786,6 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements } } - /** - * refreshes the underlying list of the Bookmark adapter since the bookmark - * adapter doesn't always change when notifyDataChanged gets called. - */ - private void notifyBookmarkDataSetChanged() { - if (mBookmarkAdapter != null) - mBookmarkAdapter.notifyDataSetChanged(); - } - - private void addBookmark(String title, String url) { - HistoryItem bookmark = new HistoryItem(url, title); - if (mBookmarkManager.addBookmark(bookmark)) { - mBookmarkList.add(bookmark); - Collections.sort(mBookmarkList, new BookmarkManager.SortIgnoreCase()); - notifyBookmarkDataSetChanged(); - mSearchAdapter.refreshBookmarks(); - updateBookmarkIndicator(mCurrentView.getUrl()); - } - } - - private void setBookmarkDataSet(List items, boolean animate) { - mBookmarkList.clear(); - mBookmarkList.addAll(items); - notifyBookmarkDataSetChanged(); - final int resource; - if (mBookmarkManager.isRootFolder()) - resource = R.drawable.ic_action_star; - else - resource = R.drawable.ic_action_back; - - final Animation startRotation = new Animation() { - @Override - protected void applyTransformation(float interpolatedTime, Transformation t) { - mBookmarkTitleImage.setRotationY(90 * interpolatedTime); - } - }; - final Animation finishRotation = new Animation() { - @Override - protected void applyTransformation(float interpolatedTime, Transformation t) { - mBookmarkTitleImage.setRotationY((-90) + (90 * interpolatedTime)); - } - }; - startRotation.setAnimationListener(new AnimationListener() { - @Override - public void onAnimationStart(Animation animation) { - } - - @Override - public void onAnimationEnd(Animation animation) { - mBookmarkTitleImage.setImageResource(resource); - mBookmarkTitleImage.startAnimation(finishRotation); - } - - @Override - public void onAnimationRepeat(Animation animation) { - } - }); - startRotation.setInterpolator(new AccelerateInterpolator()); - finishRotation.setInterpolator(new DecelerateInterpolator()); - startRotation.setDuration(250); - finishRotation.setDuration(250); - - if (animate) { - mBookmarkTitleImage.startAnimation(startRotation); - } else { - mBookmarkTitleImage.setImageResource(resource); - } - } - /** * method that shows a dialog asking what string the user wishes to search * for. It highlights the text entered. @@ -995,146 +885,6 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements } } - private class BookmarkItemClickListener implements ListView.OnItemClickListener { - - @Override - public void onItemClick(AdapterView parent, View view, int position, long id) { - if (mBookmarkList.get(position).isFolder()) { - setBookmarkDataSet(mBookmarkManager.getBookmarksFromFolder(mBookmarkList.get(position).getTitle(), true), true); - return; - } - if (mCurrentView != null) { - mCurrentView.loadUrl(mBookmarkList.get(position).getUrl()); - } - // keep any jank from happening when the drawer is closed after the - // URL starts to load - final Handler handler = new Handler(); - handler.postDelayed(new Runnable() { - @Override - public void run() { - mDrawerLayout.closeDrawer(mDrawerRight); - } - }, 150); - } - } - - private class BookmarkItemLongClickListener implements ListView.OnItemLongClickListener { - - @Override - public boolean onItemLongClick(AdapterView arg0, View arg1, final int position, long arg3) { - longPressBookmarkLink(mBookmarkList.get(position).getUrl()); - return true; - } - - } - - /** - * Takes in the id of which bookmark was selected and shows a dialog that - * allows the user to rename and change the url of the bookmark - * - * @param id which id in the list was chosen - */ - private synchronized void editBookmark(final int id) { - final AlertDialog.Builder editBookmarkDialog = new AlertDialog.Builder(mActivity); - editBookmarkDialog.setTitle(R.string.title_edit_bookmark); - final EditText getTitle = new EditText(mActivity); - getTitle.setHint(R.string.hint_title); - getTitle.setText(mBookmarkList.get(id).getTitle()); - getTitle.setSingleLine(); - final EditText getUrl = new EditText(mActivity); - getUrl.setHint(R.string.hint_url); - getUrl.setText(mBookmarkList.get(id).getUrl()); - getUrl.setSingleLine(); - final AutoCompleteTextView getFolder = new AutoCompleteTextView(mActivity); - getFolder.setHint(R.string.folder); - getFolder.setText(mBookmarkList.get(id).getFolder()); - getFolder.setSingleLine(); - List folders = mBookmarkManager.getFolderTitles(); - ArrayAdapter suggestionsAdapter = new ArrayAdapter<>(this, android.R.layout.simple_dropdown_item_1line, folders); - getFolder.setThreshold(1); - getFolder.setAdapter(suggestionsAdapter); - LinearLayout layout = new LinearLayout(mActivity); - layout.setOrientation(LinearLayout.VERTICAL); - int padding = Utils.dpToPx(10); - layout.setPadding(padding, padding, padding, padding); - layout.addView(getTitle); - layout.addView(getUrl); - layout.addView(getFolder); - editBookmarkDialog.setView(layout); - editBookmarkDialog.setPositiveButton(getResources().getString(R.string.action_ok), - new DialogInterface.OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, int which) { - HistoryItem item = new HistoryItem(); - String currentFolder = mBookmarkList.get(id).getFolder(); - item.setTitle(getTitle.getText().toString()); - item.setUrl(getUrl.getText().toString()); - item.setUrl(getUrl.getText().toString()); - item.setFolder(getFolder.getText().toString()); - mBookmarkManager.editBookmark(mBookmarkList.get(id), item); - - List list = mBookmarkManager.getBookmarksFromFolder(currentFolder, true); - if (list.isEmpty()) { - setBookmarkDataSet(mBookmarkManager.getBookmarksFromFolder(null, true), true); - } else { - setBookmarkDataSet(list, false); - } - - if (mCurrentView != null && mCurrentView.getUrl().startsWith(Constants.FILE) - && mCurrentView.getUrl().endsWith(BookmarkPage.FILENAME)) { - openBookmarkPage(mWebView); - } - if (mCurrentView != null) { - updateBookmarkIndicator(mCurrentView.getUrl()); - } - } - }); - editBookmarkDialog.show(); - } - - /** - * Show a dialog to rename a folder - * - * @param id the position of the HistoryItem (folder) in the bookmark list - */ - private synchronized void renameFolder(final int id) { - final AlertDialog.Builder editFolderDialog = new AlertDialog.Builder(mActivity); - editFolderDialog.setTitle(R.string.title_rename_folder); - final EditText getTitle = new EditText(mActivity); - getTitle.setHint(R.string.hint_title); - getTitle.setText(mBookmarkList.get(id).getTitle()); - getTitle.setSingleLine(); - LinearLayout layout = new LinearLayout(mActivity); - layout.setOrientation(LinearLayout.VERTICAL); - int padding = Utils.dpToPx(10); - layout.setPadding(padding, padding, padding, padding); - layout.addView(getTitle); - editFolderDialog.setView(layout); - editFolderDialog.setPositiveButton(getResources().getString(R.string.action_ok), - new DialogInterface.OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, int which) { - String oldTitle = mBookmarkList.get(id).getTitle(); - String newTitle = getTitle.getText().toString(); - - mBookmarkManager.renameFolder(oldTitle, newTitle); - - setBookmarkDataSet(mBookmarkManager.getBookmarksFromFolder(null, true), false); - - if (mCurrentView != null && mCurrentView.getUrl().startsWith(Constants.FILE) - && mCurrentView.getUrl().endsWith(BookmarkPage.FILENAME)) { - openBookmarkPage(mWebView); - } - if (mCurrentView != null) { - updateBookmarkIndicator(mCurrentView.getUrl()); - } - } - }); - editFolderDialog.show(); - } - /** * displays the WebView contained in the LightningView Also handles the * removal of previous views @@ -1196,7 +946,9 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements } }, 150); - updateBookmarkIndicator(mWebView.getUrl()); + // Should update the bookmark status in BookmarksFragment + BusProvider.getInstance() + .post(new BrowserEvents.CurrentPageUrl(mCurrentView.getUrl())); // new Handler().postDelayed(new Runnable() { // @Override @@ -1222,7 +974,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements source = intent.getExtras().getString("SOURCE"); } if (num == 1) { - mCurrentView.loadUrl(url); + loadUrlInCurrentView(url); } else if (url != null) { if (url.startsWith(Constants.FILE)) { Utils.showSnackbar(this, R.string.message_blocked_local); @@ -1233,6 +985,16 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements } } + private void loadUrlInCurrentView(final String url) { + if (mCurrentView == null) { + // This is a problem, probably an assert will be better than a return + return; + } + + mCurrentView.loadUrl(url); + BusProvider.getInstance().post(new BrowserEvents.CurrentPageUrl(url)); + } + @Override public void closeEmptyTab() { if (mWebView != null && mWebView.copyBackForwardList().getSize() == 0) { @@ -1405,11 +1167,8 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements if (mDrawerLayout.isDrawerOpen(mDrawerLeft)) { mDrawerLayout.closeDrawer(mDrawerLeft); } else if (mDrawerLayout.isDrawerOpen(mDrawerRight)) { - if (!mBookmarkManager.isRootFolder()) { - setBookmarkDataSet(mBookmarkManager.getBookmarksFromFolder(null, true), true); - } else { - mDrawerLayout.closeDrawer(mDrawerRight); - } + BusProvider.getInstance() + .post(new BrowserEvents.UserPressedBack()); } else { if (mCurrentView != null) { Log.d(Constants.TAG, "onBackPressed"); @@ -1444,6 +1203,8 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements } catch (IllegalArgumentException e) { e.printStackTrace(); } + + BusProvider.getInstance().unregister(busEventListener); } void saveOpenTabs() { @@ -1493,7 +1254,6 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements mCurrentView.onResume(); } mHistoryDatabase = HistoryDatabase.getInstance(getApplicationContext()); - setBookmarkDataSet(mBookmarkManager.getBookmarksFromFolder(null, true), false); initializePreferences(); for (int n = 0; n < mWebViewList.size(); n++) { if (mWebViewList.get(n) != null) { @@ -1508,6 +1268,8 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements IntentFilter filter = new IntentFilter(); filter.addAction(NETWORK_BROADCAST_ACTION); registerReceiver(mNetworkReceiver, filter); + + BusProvider.getInstance().register(busEventListener); } /** @@ -1522,7 +1284,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements query = query.trim(); mCurrentView.stopLoading(); if (mCurrentView != null) { - mCurrentView.loadUrl(UrlUtils.smartUrlFilter(query, true, searchUrl)); + loadUrlInCurrentView(UrlUtils.smartUrlFilter(query, true, searchUrl)); } } @@ -1722,163 +1484,6 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements }); } - public class BookmarkViewAdapter extends ArrayAdapter { - - final Context context; - List data = null; - final int layoutResourceId; - final Bitmap folderIcon; - - public BookmarkViewAdapter(Context context, int layoutResourceId, List data) { - super(context, layoutResourceId, data); - this.layoutResourceId = layoutResourceId; - this.context = context; - this.data = data; - this.folderIcon = mFolderBitmap; - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - View row = convertView; - BookmarkViewHolder holder; - - if (row == null) { - LayoutInflater inflater = ((Activity) context).getLayoutInflater(); - row = inflater.inflate(layoutResourceId, parent, false); - - holder = new BookmarkViewHolder(); - holder.txtTitle = (TextView) row.findViewById(R.id.textBookmark); - holder.favicon = (ImageView) row.findViewById(R.id.faviconBookmark); - row.setTag(holder); - } else { - holder = (BookmarkViewHolder) row.getTag(); - } - - ViewCompat.jumpDrawablesToCurrentState(row); - - HistoryItem web = data.get(position); - holder.txtTitle.setText(web.getTitle()); - holder.favicon.setImageBitmap(mWebpageBitmap); - if (web.isFolder()) { - holder.favicon.setImageBitmap(this.folderIcon); - } else if (web.getBitmap() == null) { - getImage(holder.favicon, web); - } else { - holder.favicon.setImageBitmap(web.getBitmap()); - } - return row; - } - - class BookmarkViewHolder { - TextView txtTitle; - ImageView favicon; - } - } - - private void getImage(ImageView image, HistoryItem web) { - new DownloadImageTask(image, web).execute(web.getUrl()); - } - - private class DownloadImageTask extends AsyncTask { - - final ImageView bmImage; - final HistoryItem mWeb; - - public DownloadImageTask(ImageView bmImage, HistoryItem web) { - this.bmImage = bmImage; - this.mWeb = web; - } - - protected Bitmap doInBackground(String... urls) { - String url = urls[0]; - Bitmap mIcon = null; - // unique path for each url that is bookmarked. - String hash = String.valueOf(Utils.getDomainName(url).hashCode()); - File image = new File(mActivity.getCacheDir(), hash + ".png"); - String urldisplay; - try { - urldisplay = Utils.getProtocol(url) + getDomainName(url) + "/favicon.ico"; - } catch (URISyntaxException e) { - e.printStackTrace(); - urldisplay = "https://www.google.com/s2/favicons?domain_url=" + url; - } - // checks to see if the image exists - if (!image.exists()) { - FileOutputStream fos = null; - InputStream in = null; - try { - // if not, download it... - URL urlDownload = new URL(urldisplay); - HttpURLConnection connection = (HttpURLConnection) urlDownload.openConnection(); - connection.setDoInput(true); - connection.connect(); - in = connection.getInputStream(); - - if (in != null) { - mIcon = BitmapFactory.decodeStream(in); - } - // ...and cache it - if (mIcon != null) { - fos = new FileOutputStream(image); - mIcon.compress(Bitmap.CompressFormat.PNG, 100, fos); - fos.flush(); - Log.d(Constants.TAG, "Downloaded: " + urldisplay); - } - - } catch (Exception e) { - e.printStackTrace(); - } finally { - Utils.close(in); - Utils.close(fos); - } - } else { - // if it exists, retrieve it from the cache - mIcon = BitmapFactory.decodeFile(image.getPath()); - } - if (mIcon == null) { - InputStream in = null; - FileOutputStream fos = null; - try { - // if not, download it... - URL urlDownload = new URL("https://www.google.com/s2/favicons?domain_url=" - + url); - HttpURLConnection connection = (HttpURLConnection) urlDownload.openConnection(); - connection.setDoInput(true); - connection.connect(); - in = connection.getInputStream(); - - if (in != null) { - mIcon = BitmapFactory.decodeStream(in); - } - // ...and cache it - if (mIcon != null) { - fos = new FileOutputStream(image); - mIcon.compress(Bitmap.CompressFormat.PNG, 100, fos); - fos.flush(); - } - - } catch (Exception e) { - e.printStackTrace(); - } finally { - Utils.close(in); - Utils.close(fos); - } - } - if (mIcon == null) { - return mWebpageBitmap; - } else { - return mIcon; - } - } - - protected void onPostExecute(Bitmap result) { - Bitmap fav = Utils.padFavicon(result); - bmImage.setImageBitmap(fav); - mWeb.setBitmap(fav); - notifyBookmarkDataSetChanged(); - } - } - private static String getDomainName(String url) throws URISyntaxException { URI uri = new URI(url); String domain = uri.getHost(); @@ -1893,6 +1498,8 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements if (url == null || mSearch == null || mSearch.hasFocus()) { return; } + BusProvider.getInstance() + .post(new BrowserEvents.CurrentPageUrl(url)); if (shortUrl && !url.startsWith(Constants.FILE)) { switch (mPreferences.getUrlBoxContentChoice()) { case 0: // Default, show only the domain @@ -2006,7 +1613,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements @Override public void run() { - mCurrentView.loadUrl(HistoryPage.getHistoryPage(mActivity)); + loadUrlInCurrentView(HistoryPage.getHistoryPage(mActivity)); mSearch.setText(""); } @@ -2494,12 +2101,13 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements longPressHistoryLink(newUrl); } } else if (currentUrl.endsWith(BookmarkPage.FILENAME)) { + /* TODO Wtf is this? if (url != null) { longPressBookmarkLink(url); } else if (result != null && result.getExtra() != null) { final String newUrl = result.getExtra(); longPressBookmarkLink(newUrl); - } + } */ } } else { if (url != null) { @@ -2523,103 +2131,6 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements } } - private void longPressFolder(String url) { - String title; - if (url.startsWith(Constants.FILE)) { - // We are getting the title from the url - // Strip '-bookmarks.html' from the end of the url - title = url.substring(0, url.length() - BookmarkPage.FILENAME.length() - 1); - - // Strip the beginning of the url off and leave only the title - title = title.substring(Constants.FILE.length() + mActivity.getFilesDir().toString().length() + 1); - } else if (url.startsWith(Constants.FOLDER)) { - title = url.substring(Constants.FOLDER.length()); - } else { - title = url; - } - final int position = BookmarkManager.getIndexOfBookmark(mBookmarkList, Constants.FOLDER + title); - if (position == -1) { - return; - } - DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - switch (which) { - case DialogInterface.BUTTON_POSITIVE: - renameFolder(position); - break; - - case DialogInterface.BUTTON_NEGATIVE: - mBookmarkManager.deleteFolder(mBookmarkList.get(position).getTitle()); - - setBookmarkDataSet(mBookmarkManager.getBookmarksFromFolder(null, true), false); - - if (mCurrentView != null && mCurrentView.getUrl().startsWith(Constants.FILE) - && mCurrentView.getUrl().endsWith(BookmarkPage.FILENAME)) { - openBookmarkPage(mWebView); - } - if (mCurrentView != null) { - updateBookmarkIndicator(mCurrentView.getUrl()); - } - break; - } - } - }; - - AlertDialog.Builder builder = new AlertDialog.Builder(mActivity); - builder.setTitle(R.string.action_folder) - .setMessage(R.string.dialog_folder) - .setCancelable(true) - .setPositiveButton(R.string.action_rename, dialogClickListener) - .setNegativeButton(R.string.action_delete, dialogClickListener) - .show(); - } - - private void longPressBookmarkLink(final String url) { - if (url.startsWith(Constants.FILE) || url.startsWith(Constants.FOLDER)) { - longPressFolder(url); - return; - } - final int position = BookmarkManager.getIndexOfBookmark(mBookmarkList, url); - if (position == -1) { - return; - } - DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - switch (which) { - case DialogInterface.BUTTON_POSITIVE: - newTab(mBookmarkList.get(position).getUrl(), false); - mDrawerLayout.closeDrawers(); - break; - case DialogInterface.BUTTON_NEGATIVE: - if (mBookmarkManager.deleteBookmark(mBookmarkList.get(position))) { - mBookmarkList.remove(position); - notifyBookmarkDataSetChanged(); - mSearchAdapter.refreshBookmarks(); - openBookmarks(); - if (mCurrentView != null) { - updateBookmarkIndicator(mCurrentView.getUrl()); - } - } - break; - case DialogInterface.BUTTON_NEUTRAL: - editBookmark(position); - break; - } - } - }; - - AlertDialog.Builder builder = new AlertDialog.Builder(mActivity); - builder.setTitle(R.string.action_bookmarks) - .setMessage(R.string.dialog_bookmark) - .setCancelable(true) - .setPositiveButton(R.string.action_new_tab, dialogClickListener) - .setNegativeButton(R.string.action_delete, dialogClickListener) - .setNeutralButton(R.string.action_edit, dialogClickListener) - .show(); - } - private void longPressHistoryLink(final String url) { DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() { @Override @@ -2637,7 +2148,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements case DialogInterface.BUTTON_NEUTRAL: if (mCurrentView != null) { - mCurrentView.loadUrl(url); + loadUrlInCurrentView(url); } break; } @@ -2664,7 +2175,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements break; case DialogInterface.BUTTON_NEGATIVE: - mCurrentView.loadUrl(url); + loadUrlInCurrentView(url); break; case DialogInterface.BUTTON_NEUTRAL: @@ -2697,7 +2208,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements break; case DialogInterface.BUTTON_NEGATIVE: - mCurrentView.loadUrl(url); + loadUrlInCurrentView(url); break; case DialogInterface.BUTTON_NEUTRAL: @@ -2758,17 +2269,6 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements } } - @Override - public void updateBookmarkIndicator(String url) { - if (url == null || !mBookmarkManager.isBookmark(url)) { - mBookmarkImage.setImageResource(R.drawable.ic_action_star); - mBookmarkImage.setColorFilter(mIconColor, PorterDuff.Mode.SRC_IN); - } else { - mBookmarkImage.setImageResource(R.drawable.ic_bookmark); - mBookmarkImage.setColorFilter(ThemeUtils.getAccentColor(this), PorterDuff.Mode.SRC_IN); - } - } - @Override public void onClick(View v) { switch (v.getId()) { @@ -2820,11 +2320,6 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements mCurrentView.reload(); closeDrawers(); break; - case R.id.action_add_bookmark: - if (mCurrentView != null && !mCurrentView.getUrl().startsWith(Constants.FILE)) { - addBookmark(mCurrentView.getTitle(), mCurrentView.getUrl()); - } - break; } } @@ -2870,4 +2365,84 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements PermissionsManager.getInstance().notifyPermissionsChange(permissions); super.onRequestPermissionsResult(requestCode, permissions, grantResults); } + + private final Object busEventListener = new Object() { + /** + * Load the given bookmark in the current tab, used by the the + * {@link acr.browser.lightning.fragment.BookmarksFragment} + * @param event The event as it comes from the bus + */ + @Subscribe + public void loadBookmarkInCurrentTab(final BookmarkEvents.Clicked event) { + loadUrlInCurrentView(event.bookmark.getUrl()); + // keep any jank from happening when the drawer is closed after the + // URL starts to load + final Handler handler = new Handler(); + handler.postDelayed(new Runnable() { + @Override + public void run() { + mDrawerLayout.closeDrawer(mDrawerRight); + } + }, 150); + } + + /** + * Load the given bookmark in a new tab, used by the the + * {@link acr.browser.lightning.fragment.BookmarksFragment} + * @param event The event as it comes from the bus + */ + @Subscribe + public void loadBookmarkInNewTab(final BookmarkEvents.AsNewTab event) { + newTab(event.bookmark.getUrl(), true); + mDrawerLayout.closeDrawers(); + } + + /** + * When receive a {@link acr.browser.lightning.bus.BookmarkEvents.WantToBookmarkCurrentPage} + * message this receiver answer firing the + * {@link acr.browser.lightning.bus.BrowserEvents.AddBookmark} message + * + * @param event basically a marker + */ + @Subscribe + public void bookmarkCurrentPage(final BookmarkEvents.WantToBookmarkCurrentPage event) { + BusProvider.getInstance() + .post(new BrowserEvents + .AddBookmark(mCurrentView.getTitle(), mCurrentView.getUrl())); + } + + /** + * This message is received when a bookmark was added by the + * {@link acr.browser.lightning.fragment.BookmarksFragment} + * + * @param event a marker + */ + @Subscribe + public void bookmarkAdded(final BookmarkEvents.Added event) { + mSearchAdapter.refreshBookmarks(); + } + + /** + * Notify the browser that a bookmark was deleted + * + * @param event + */ + @Subscribe + public void bookmarkDeleted(final BookmarkEvents.Deleted event) { + BusProvider.getInstance() + .post(new BrowserEvents.CurrentPageUrl(mCurrentView.getUrl())); + } + + /** + * The {@link acr.browser.lightning.fragment.BookmarksFragment} send this message on reply + * to {@link acr.browser.lightning.bus.BrowserEvents.UserPressedBack} message if the + * fragement is showing the boomarks root folder. + * + * @param event a marker + */ + @Subscribe + public void closeBookmarks(final BookmarkEvents.CloseBookmarks event) { + mDrawerLayout.closeDrawer(mDrawerRight); + } + }; } diff --git a/app/src/main/java/acr/browser/lightning/activity/MainActivity.java b/app/src/main/java/acr/browser/lightning/activity/MainActivity.java index 32a867d..7234951 100644 --- a/app/src/main/java/acr/browser/lightning/activity/MainActivity.java +++ b/app/src/main/java/acr/browser/lightning/activity/MainActivity.java @@ -6,7 +6,10 @@ import android.view.Menu; import android.webkit.CookieManager; import android.webkit.CookieSyncManager; +import com.squareup.otto.Subscribe; + import acr.browser.lightning.R; +import acr.browser.lightning.bus.BookmarkEvents; import acr.browser.lightning.preference.PreferenceManager; @SuppressWarnings("deprecation") @@ -60,4 +63,6 @@ public class MainActivity extends BrowserActivity { closeDrawers(); moveTaskToBack(true); } + + } diff --git a/app/src/main/java/acr/browser/lightning/bus/BookmarkEvents.java b/app/src/main/java/acr/browser/lightning/bus/BookmarkEvents.java new file mode 100644 index 0000000..8e60c47 --- /dev/null +++ b/app/src/main/java/acr/browser/lightning/bus/BookmarkEvents.java @@ -0,0 +1,78 @@ +package acr.browser.lightning.bus; + +import acr.browser.lightning.database.HistoryItem; + +/** + * Created by Stefano Pacifici on 26/08/15. + */ +public final class BookmarkEvents { + + private BookmarkEvents() { + // No instances + } + + /** + * A bookmark was clicked + */ + public final static class Clicked { + public final HistoryItem bookmark; + + public Clicked(final HistoryItem bookmark) { + this.bookmark = bookmark; + } + } + + /** + * The user ask to open the bookmark as new tab + */ + public final static class AsNewTab { + public final HistoryItem bookmark; + + public AsNewTab(final HistoryItem bookmark) { + this.bookmark = bookmark; + } + } + + /** + * The user ask to delete the selected bookmark + */ + public static class Deleted { + public final HistoryItem item; + + public Deleted(final HistoryItem item) { + this.item = item; + } + } + + /** + * The user ask to bookmark the currently displayed page + */ + public static class WantToBookmarkCurrentPage { + } + + /** + * The bookmark was added + */ + public static class Added { + public final HistoryItem item; + + public Added(final HistoryItem item) { + this.item = item; + } + } + + /** + * The {@link acr.browser.lightning.fragment.BookmarksFragment} want to know the url (and title) + * of the currently shown web page. + */ + public static class WantInfoAboutCurrentPage { + } + + /** + * Sended by the {@link acr.browser.lightning.fragment.BookmarksFragment} when it wants to close + * itself (generally in reply to a {@link acr.browser.lightning.bus.BrowserEvents.UserPressedBack} + * event. + */ + public static class CloseBookmarks { + } +} diff --git a/app/src/main/java/acr/browser/lightning/bus/BrowserEvents.java b/app/src/main/java/acr/browser/lightning/bus/BrowserEvents.java new file mode 100644 index 0000000..15ff373 --- /dev/null +++ b/app/src/main/java/acr/browser/lightning/bus/BrowserEvents.java @@ -0,0 +1,44 @@ +package acr.browser.lightning.bus; + +/** + * Created by Stefano Pacifici on 26/08/15. + */ +public final class BrowserEvents { + + private BrowserEvents() { + // No instances + } + + /** + * Used to reply to the {@link acr.browser.lightning.fragment.BookmarksFragment} message + * {@link acr.browser.lightning.bus.BookmarkEvents.WantToBookmarkCurrentPage}. The interaction + * result is a new bookmark added. + */ + public static class AddBookmark { + public final String title, url; + + public AddBookmark(final String title, final String url) { + this.title = title; + this.url = url; + } + } + + /** + * Used to reply to {@link acr.browser.lightning.fragment.BookmarksFragment} message + * {@link acr.browser.lightning.bus.BookmarkEvents.WantInfoAboutCurrentPage}. This is generally + * used to update the {@link acr.browser.lightning.fragment.BookmarksFragment} interface. + */ + public static class CurrentPageUrl { + public final String url; + + public CurrentPageUrl(final String url) { + this.url = url; + } + } + + /** + * Notify the BookmarksFragment and TabsFragment that the user pressed the back button + */ + public static class UserPressedBack { + } +} diff --git a/app/src/main/java/acr/browser/lightning/bus/BusProvider.java b/app/src/main/java/acr/browser/lightning/bus/BusProvider.java new file mode 100644 index 0000000..530b183 --- /dev/null +++ b/app/src/main/java/acr/browser/lightning/bus/BusProvider.java @@ -0,0 +1,19 @@ +package acr.browser.lightning.bus; + +import com.squareup.otto.Bus; + +/** + * Created by Stefano Pacifici on 25/08/15. + */ +public class BusProvider { + + private static final Bus bus = new Bus(); + + public static Bus getInstance() { + return bus; + } + + private BusProvider() { + // No instances + } +} diff --git a/app/src/main/java/acr/browser/lightning/controller/BrowserController.java b/app/src/main/java/acr/browser/lightning/controller/BrowserController.java index b5d6afa..21750a8 100644 --- a/app/src/main/java/acr/browser/lightning/controller/BrowserController.java +++ b/app/src/main/java/acr/browser/lightning/controller/BrowserController.java @@ -56,6 +56,6 @@ public interface BrowserController { boolean proxyIsNotReady(); - void updateBookmarkIndicator(String url); + // void updateBookmarkIndicator(String url); } diff --git a/app/src/main/java/acr/browser/lightning/database/BookmarkManager.java b/app/src/main/java/acr/browser/lightning/database/BookmarkManager.java index 87f4be4..fb6f0a9 100644 --- a/app/src/main/java/acr/browser/lightning/database/BookmarkManager.java +++ b/app/src/main/java/acr/browser/lightning/database/BookmarkManager.java @@ -6,6 +6,7 @@ import android.database.Cursor; import android.os.Environment; import android.provider.Browser; import android.support.annotation.NonNull; +import android.util.Log; import org.json.JSONException; import org.json.JSONObject; @@ -13,9 +14,12 @@ import org.json.JSONObject; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; +import java.io.FileInputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -32,6 +36,8 @@ import acr.browser.lightning.utils.Utils; public class BookmarkManager { + private static final String TAG = BookmarkManager.class.getSimpleName(); + private final Context mContext; private static final String TITLE = "title"; private static final String URL = "url"; @@ -251,24 +257,36 @@ public class BookmarkManager { * @return returns a list of bookmarks that can be sorted */ public synchronized List getAllBookmarks(boolean sort) { - List bookmarks = new ArrayList<>(); - File bookmarksFile = new File(mContext.getFilesDir(), FILE_BOOKMARKS); + final List bookmarks = new ArrayList<>(); + final File bookmarksFile = new File(mContext.getFilesDir(), FILE_BOOKMARKS); + BufferedReader bookmarksReader = null; try { - bookmarksReader = new BufferedReader(new FileReader(bookmarksFile)); + final InputStream inputStream; + if (bookmarksFile.exists() && bookmarksFile.isFile()) { + inputStream = new FileInputStream(bookmarksFile); + } else { + inputStream = mContext.getResources().openRawResource(R.raw.default_bookmarks); + } + bookmarksReader = + new BufferedReader(new InputStreamReader(inputStream)); 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(); + try { + 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 (JSONException e) { + Log.e(TAG, "Can't parse line " + line, e); + } + } + } catch (IOException e) { + Log.e(TAG, "Error reading the bookmarks file", e); } finally { Utils.close(bookmarksReader); } @@ -498,17 +516,4 @@ public class BookmarkManager { } } - - 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 - }; } diff --git a/app/src/main/java/acr/browser/lightning/fragment/BookmarksFragment.java b/app/src/main/java/acr/browser/lightning/fragment/BookmarksFragment.java new file mode 100644 index 0000000..2367c15 --- /dev/null +++ b/app/src/main/java/acr/browser/lightning/fragment/BookmarksFragment.java @@ -0,0 +1,493 @@ +package acr.browser.lightning.fragment; + +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.graphics.Bitmap; +import android.graphics.PorterDuff; +import android.os.Bundle; +import android.support.annotation.IdRes; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.support.v4.view.ViewCompat; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.animation.AccelerateInterpolator; +import android.view.animation.Animation; +import android.view.animation.DecelerateInterpolator; +import android.view.animation.Transformation; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.AdapterView.OnItemLongClickListener; +import android.widget.ArrayAdapter; +import android.widget.AutoCompleteTextView; +import android.widget.EditText; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.TextView; + +import com.squareup.otto.Bus; +import com.squareup.otto.Subscribe; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import acr.browser.lightning.R; +import acr.browser.lightning.activity.BrowserActivity; +import acr.browser.lightning.bus.BookmarkEvents; +import acr.browser.lightning.bus.BrowserEvents; +import acr.browser.lightning.bus.BusProvider; +import acr.browser.lightning.database.BookmarkManager; +import acr.browser.lightning.database.HistoryItem; +import acr.browser.lightning.preference.PreferenceManager; +import acr.browser.lightning.utils.DownloadImageTask; +import acr.browser.lightning.utils.ThemeUtils; +import acr.browser.lightning.utils.Utils; + +import static android.support.v7.app.AlertDialog.Builder; + +/** + * Created by Stefano Pacifici on 25/08/15. Based on Anthony C. Restaino's code. + */ +public class BookmarksFragment extends Fragment implements View.OnClickListener, View.OnLongClickListener { + + // Managers + private BookmarkManager mBookmarkManager; + + // Adapter + private BookmarkViewAdapter mBookmarkAdapter; + + // Preloaded images + private Bitmap mWebpageBitmap, mFolderBitmap; + + // Bookmarks + private List mBookmarks = new ArrayList<>(); + + // Views + private ListView mBookmarksListView; + private ImageView mBookmarkTitleImage, mBookmarkImage; + + // Colors + private int mIconColor; + + // Init asynchronously the bookmark manager + private final Runnable initBookmarkManager = new Runnable() { + @Override + public void run() { + final Context context = getContext(); + mBookmarkManager = BookmarkManager.getInstance(context.getApplicationContext()); + mBookmarkAdapter = new BookmarkViewAdapter(context, mBookmarks); + setBookmarkDataSet(mBookmarkManager.getBookmarksFromFolder(null, true), false); + mBookmarksListView.setAdapter(mBookmarkAdapter); + } + }; + + // Handle bookmark click + private final OnItemClickListener itemClickListener = new OnItemClickListener() { + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + final HistoryItem item = mBookmarks.get(position); + if (item.isFolder()) { + setBookmarkDataSet(mBookmarkManager.getBookmarksFromFolder(item.getTitle(), true), + true); + } else { + BusProvider.getInstance().post(new BookmarkEvents.Clicked(item)); + } + } + }; + + private final OnItemLongClickListener itemLongClickListener = new OnItemLongClickListener() { + @Override + public boolean onItemLongClick(AdapterView parent, View view, int position, long id) { + final HistoryItem item = mBookmarks.get(position); + handleLongPress(item, position); + return true; + } + }; + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + final View view = inflater.inflate(R.layout.bookmark_drawer, container, false); + mBookmarksListView = (ListView) view.findViewById(R.id.right_drawer_list); + mBookmarksListView.setOnItemClickListener(itemClickListener); + mBookmarksListView.setOnItemLongClickListener(itemLongClickListener); + mBookmarkTitleImage = (ImageView) view.findViewById(R.id.starIcon); + mBookmarkImage = (ImageView) view.findViewById(R.id.icon_star); + final View backView = view.findViewById(R.id.bookmark_back_button); + backView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (mBookmarkManager == null) + return; + if (!mBookmarkManager.isRootFolder()) { + setBookmarkDataSet(mBookmarkManager.getBookmarksFromFolder(null, true), true); + } + } + }); + + // Must be called here, only here we have a reference to the ListView + new Thread(initBookmarkManager).run(); + return view; + } + + @Override + public void onActivityCreated(@Nullable Bundle savedInstanceState) { + // TODO this code depend way too much on BrowserActivity + super.onActivityCreated(savedInstanceState); + final BrowserActivity activity = (BrowserActivity) getActivity(); + final PreferenceManager preferenceManager =PreferenceManager.getInstance(); + boolean darkTheme = preferenceManager.getUseTheme() != 0 || activity.isIncognito(); + mWebpageBitmap = ThemeUtils.getThemedBitmap(activity, R.drawable.ic_webpage, darkTheme); + mFolderBitmap = ThemeUtils.getThemedBitmap(activity, R.drawable.ic_folder, darkTheme); + mIconColor = darkTheme ? ThemeUtils.getIconDarkThemeColor(activity) : + ThemeUtils.getIconLightThemeColor(activity); + setupFrameLayoutButton(getView(), R.id.action_add_bookmark, R.id.icon_star); + mBookmarkTitleImage.setColorFilter(mIconColor, PorterDuff.Mode.SRC_IN); + } + + @Override + public void onStart() { + super.onStart(); + BusProvider.getInstance().register(this); + } + + @Override + public void onStop() { + super.onStop(); + BusProvider.getInstance().unregister(this); + } + + @Subscribe + public void addBookmark(final BrowserEvents.AddBookmark event) { + final HistoryItem item = new HistoryItem(event.url, event.title); + if (mBookmarkManager.addBookmark(item)) { + mBookmarks.add(item); + Collections.sort(mBookmarks, new BookmarkManager.SortIgnoreCase()); + mBookmarkAdapter.notifyDataSetChanged(); + BusProvider.getInstance() + .post(new BookmarkEvents.Added(item)); + updateBookmarkIndicator(event.url); + } + } + + @Subscribe + public void currentPageInfo(final BrowserEvents.CurrentPageUrl event) { + updateBookmarkIndicator(event.url); + } + + private void updateBookmarkIndicator(final String url) { + if (!mBookmarkManager.isBookmark(url)) { + mBookmarkImage.setImageResource(R.drawable.ic_action_star); + mBookmarkImage.setColorFilter(mIconColor, PorterDuff.Mode.SRC_IN); + } else { + mBookmarkImage.setImageResource(R.drawable.ic_bookmark); + mBookmarkImage.setColorFilter(ThemeUtils.getAccentColor(getContext()), PorterDuff.Mode.SRC_IN); + } + } + + @Subscribe + public void userPressedBack(final BrowserEvents.UserPressedBack event) { + if (mBookmarkManager.isRootFolder()) { + BusProvider.getInstance() + .post(new BookmarkEvents.CloseBookmarks()); + } else { + setBookmarkDataSet(mBookmarkManager.getBookmarksFromFolder(null, true), true); + } + } + + private void setBookmarkDataSet(List items, boolean animate) { + mBookmarks.clear(); + mBookmarks.addAll(items); + mBookmarkAdapter.notifyDataSetChanged(); + final int resource; + if (mBookmarkManager.isRootFolder()) + resource = R.drawable.ic_action_star; + else + resource = R.drawable.ic_action_back; + + final Animation startRotation = new Animation() { + @Override + protected void applyTransformation(float interpolatedTime, Transformation t) { + mBookmarkTitleImage.setRotationY(90 * interpolatedTime); + } + }; + final Animation finishRotation = new Animation() { + @Override + protected void applyTransformation(float interpolatedTime, Transformation t) { + mBookmarkTitleImage.setRotationY((-90) + (90 * interpolatedTime)); + } + }; + startRotation.setAnimationListener(new Animation.AnimationListener() { + @Override + public void onAnimationStart(Animation animation) { + } + + @Override + public void onAnimationEnd(Animation animation) { + mBookmarkTitleImage.setImageResource(resource); + mBookmarkTitleImage.startAnimation(finishRotation); + } + + @Override + public void onAnimationRepeat(Animation animation) { + } + }); + startRotation.setInterpolator(new AccelerateInterpolator()); + finishRotation.setInterpolator(new DecelerateInterpolator()); + startRotation.setDuration(250); + finishRotation.setDuration(250); + + if (animate) { + mBookmarkTitleImage.startAnimation(startRotation); + } else { + mBookmarkTitleImage.setImageResource(resource); + } + } + + // TODO this is basically a copy/paste from BrowserActivity, should be changed + private void setupFrameLayoutButton(@NonNull View view, @IdRes int buttonId, @IdRes int imageId) { + FrameLayout frameButton = (FrameLayout) view.findViewById(buttonId); + frameButton.setOnClickListener(this); + frameButton.setOnLongClickListener(this); + ImageView buttonImage = (ImageView) view.findViewById(imageId); + buttonImage.setColorFilter(mIconColor, PorterDuff.Mode.SRC_IN); + } + + private void handleLongPress(final HistoryItem item, final int position) { + if (item.isFolder()) { + longPressFolder(item, position); + return; + } else { + final Bus bus = BusProvider.getInstance(); + final DialogInterface.OnClickListener dialogClickListener = + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + switch (which) { + case DialogInterface.BUTTON_POSITIVE: + bus.post(new BookmarkEvents.AsNewTab(item)); + break; + case DialogInterface.BUTTON_NEGATIVE: + if (mBookmarkManager.deleteBookmark(item)) { + mBookmarks.remove(position); + mBookmarkAdapter.notifyDataSetChanged(); + bus.post(new BookmarkEvents.Deleted(item)); + } + break; + case DialogInterface.BUTTON_NEUTRAL: + editBookmark(item, position); + break; + } + } + }; + + AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); + builder.setTitle(R.string.action_bookmarks) + .setMessage(R.string.dialog_bookmark) + .setCancelable(true) + .setPositiveButton(R.string.action_new_tab, dialogClickListener) + .setNegativeButton(R.string.action_delete, dialogClickListener) + .setNeutralButton(R.string.action_edit, dialogClickListener) + .show(); + } + } + + private void longPressFolder(final HistoryItem item, final int position) { + final DialogInterface.OnClickListener dialogClickListener = + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + switch (which) { + case DialogInterface.BUTTON_POSITIVE: + renameFolder(item, position); + break; + + case DialogInterface.BUTTON_NEGATIVE: + mBookmarkManager.deleteFolder(item.getTitle()); + setBookmarkDataSet(mBookmarkManager.getBookmarksFromFolder(null, true), false); + BusProvider.getInstance().post(new BookmarkEvents.Deleted(item)); + /* TODO Restore Bookmarkpage + if (mCurrentView != null && mCurrentView.getUrl().startsWith(Constants.FILE) + && mCurrentView.getUrl().endsWith(BookmarkPage.FILENAME)) { + openBookmarkPage(mWebView); + }*/ + break; + } + } + }; + + Builder builder = new Builder(getContext()); + builder.setTitle(R.string.action_folder) + .setMessage(R.string.dialog_folder) + .setCancelable(true) + .setPositiveButton(R.string.action_rename, dialogClickListener) + .setNegativeButton(R.string.action_delete, dialogClickListener) + .show(); + } + + /** + * Takes in the id of which bookmark was selected and shows a dialog that + * allows the user to rename and change the url of the bookmark + * + * @param item the bookmark + * @param position the position inside the adapter + */ + private synchronized void editBookmark(final HistoryItem item, final int position) { + final Builder editBookmarkDialog = new Builder(getContext()); + editBookmarkDialog.setTitle(R.string.title_edit_bookmark); + final View dialogLayout = View.inflate(getContext(), R.layout.dialog_edit_bookmark, null); + final EditText getTitle = (EditText) dialogLayout.findViewById(R.id.bookmark_title); + getTitle.setText(item.getTitle()); + final EditText getUrl = (EditText) dialogLayout.findViewById(R.id.bookmark_url); + getUrl.setText(item.getUrl()); + final AutoCompleteTextView getFolder = + (AutoCompleteTextView) dialogLayout.findViewById(R.id.bookmark_folder); + getFolder.setHint(R.string.folder); + getFolder.setText(item.getFolder()); + final List folders = mBookmarkManager.getFolderTitles(); + final ArrayAdapter suggestionsAdapter = new ArrayAdapter<>(getContext(), + android.R.layout.simple_dropdown_item_1line, folders); + getFolder.setThreshold(1); + getFolder.setAdapter(suggestionsAdapter); + editBookmarkDialog.setView(dialogLayout); + editBookmarkDialog.setPositiveButton(getResources().getString(R.string.action_ok), + new DialogInterface.OnClickListener() { + + @Override + public void onClick(DialogInterface dialog, int which) { + HistoryItem editedItem = new HistoryItem(); + String currentFolder = item.getFolder(); + editedItem.setTitle(getTitle.getText().toString()); + editedItem.setUrl(getUrl.getText().toString()); + editedItem.setUrl(getUrl.getText().toString()); + editedItem.setFolder(getFolder.getText().toString()); + mBookmarkManager.editBookmark(item, editedItem); + + List list = mBookmarkManager.getBookmarksFromFolder(currentFolder, true); + if (list.isEmpty()) { + setBookmarkDataSet(mBookmarkManager.getBookmarksFromFolder(null, true), true); + } else { + setBookmarkDataSet(list, false); + } + BusProvider.getInstance() + .post(new BookmarkEvents.WantInfoAboutCurrentPage()); + /* TODO Restore BookmarkPage + if (mCurrentView != null && mCurrentView.getUrl().startsWith(Constants.FILE) + && mCurrentView.getUrl().endsWith(BookmarkPage.FILENAME)) { + openBookmarkPage(mWebView); + }*/ + } + }); + editBookmarkDialog.show(); + } + + /** + * Show a dialog to rename a folder + * + * @param id the position of the HistoryItem (folder) in the bookmark list + */ + private synchronized void renameFolder(final HistoryItem item, final int id) { + final Context context = getContext(); + final Builder editFolderDialog = new Builder(context); + editFolderDialog.setTitle(R.string.title_rename_folder); + final EditText getTitle = new EditText(context); + getTitle.setHint(R.string.hint_title); + getTitle.setText(item.getTitle()); + getTitle.setSingleLine(); + LinearLayout layout = new LinearLayout(context); + layout.setOrientation(LinearLayout.VERTICAL); + int padding = Utils.dpToPx(10); + layout.setPadding(padding, padding, padding, padding); + layout.addView(getTitle); + editFolderDialog.setView(layout); + editFolderDialog.setPositiveButton(getResources().getString(R.string.action_ok), + new DialogInterface.OnClickListener() { + + @Override + public void onClick(DialogInterface dialog, int which) { + String oldTitle = item.getTitle(); + String newTitle = getTitle.getText().toString(); + + mBookmarkManager.renameFolder(oldTitle, newTitle); + + setBookmarkDataSet(mBookmarkManager.getBookmarksFromFolder(null, true), false); + /* TODO Restore Bookmarkpage + if (mCurrentView != null && mCurrentView.getUrl().startsWith(Constants.FILE) + && mCurrentView.getUrl().endsWith(BookmarkPage.FILENAME)) { + openBookmarkPage(mWebView); + }*/ + } + }); + editFolderDialog.show(); + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.action_add_bookmark: + BusProvider.getInstance().post(new BookmarkEvents.WantToBookmarkCurrentPage()); + break; + default: + break; + } + } + + @Override + public boolean onLongClick(View v) { + return false; + } + + private class BookmarkViewAdapter extends ArrayAdapter { + + final Context context; + + public BookmarkViewAdapter(Context context, List data) { + super(context, R.layout.bookmark_list_item, data); + this.context = context; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + View row = convertView; + BookmarkViewHolder holder; + + if (row == null) { + LayoutInflater inflater = LayoutInflater.from(context); + row = inflater.inflate(R.layout.bookmark_list_item, parent, false); + + holder = new BookmarkViewHolder(); + holder.txtTitle = (TextView) row.findViewById(R.id.textBookmark); + holder.favicon = (ImageView) row.findViewById(R.id.faviconBookmark); + row.setTag(holder); + } else { + holder = (BookmarkViewHolder) row.getTag(); + } + + ViewCompat.jumpDrawablesToCurrentState(row); + + HistoryItem web = mBookmarks.get(position); + holder.txtTitle.setText(web.getTitle()); + holder.favicon.setImageBitmap(mWebpageBitmap); + if (web.isFolder()) { + holder.favicon.setImageBitmap(mFolderBitmap); + } else if (web.getBitmap() == null) { + new DownloadImageTask(holder.favicon, web, mWebpageBitmap).execute(); + } else { + holder.favicon.setImageBitmap(web.getBitmap()); + } + return row; + } + + class BookmarkViewHolder { + TextView txtTitle; + ImageView favicon; + } + } + +} diff --git a/app/src/main/java/acr/browser/lightning/preference/PreferenceManager.java b/app/src/main/java/acr/browser/lightning/preference/PreferenceManager.java index d2aa0c2..2f93a6e 100644 --- a/app/src/main/java/acr/browser/lightning/preference/PreferenceManager.java +++ b/app/src/main/java/acr/browser/lightning/preference/PreferenceManager.java @@ -44,7 +44,6 @@ public class PreferenceManager { public static final String INVERT_COLORS = "invertColors"; public static final String READING_TEXT_SIZE = "readingTextSize"; public static final String THEME = "Theme"; - public static final String DEFAULT_BOOKMARKS = "defaultBookmarks"; public static final String TEXT_ENCODING = "textEncoding"; public static final String CLEAR_WEBSTORAGE_EXIT = "clearWebStorageExit"; public static final String SHOW_TABS_IN_DRAWER = "showTabsInDrawer"; @@ -117,10 +116,6 @@ public class PreferenceManager { return mPrefs.getBoolean(Name.COOKIES, true); } - public boolean getDefaultBookmarks() { - return mPrefs.getBoolean(Name.DEFAULT_BOOKMARKS, true); - } - public String getDownloadDirectory() { return mPrefs.getString(Name.DOWNLOAD_DIRECTORY, Environment.DIRECTORY_DOWNLOADS); } @@ -317,10 +312,6 @@ public class PreferenceManager { putBoolean(Name.COOKIES, enable); } - public void setDefaultBookmarks(boolean show) { - putBoolean(Name.DEFAULT_BOOKMARKS, show); - } - public void setDownloadDirectory(String directory) { putString(Name.DOWNLOAD_DIRECTORY, directory); } diff --git a/app/src/main/java/acr/browser/lightning/utils/DownloadImageTask.java b/app/src/main/java/acr/browser/lightning/utils/DownloadImageTask.java new file mode 100644 index 0000000..5bca4a6 --- /dev/null +++ b/app/src/main/java/acr/browser/lightning/utils/DownloadImageTask.java @@ -0,0 +1,127 @@ +package acr.browser.lightning.utils; + +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.net.Uri; +import android.os.AsyncTask; +import android.support.annotation.NonNull; +import android.util.Log; +import android.widget.ImageView; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URISyntaxException; +import java.net.URL; + +import acr.browser.lightning.constant.Constants; +import acr.browser.lightning.database.HistoryItem; + +/** + * Created by Stefano Pacifici on 25/08/15. + */ +public class DownloadImageTask extends AsyncTask { + + final ImageView bmImage; + final HistoryItem mWeb; + final File mCacheDir; + final String mUrl; + final Bitmap mDefaultBitmap; + + public DownloadImageTask(@NonNull ImageView bmImage, @NonNull HistoryItem web, + @NonNull Bitmap defaultBitmap) { + assert bmImage != null; + assert web != null; + assert defaultBitmap != null; + this.bmImage = bmImage; + this.mWeb = web; + this.mCacheDir = bmImage.getContext().getCacheDir(); + this.mUrl = web.getUrl(); + this.mDefaultBitmap = defaultBitmap; + } + + protected Bitmap doInBackground(Void... params) { + Bitmap mIcon = null; + // unique path for each url that is bookmarked. + final Uri uri = Uri.parse(mUrl); + + final String hash = "" + Utils.hash(uri.getHost()); + final File image = new File(mCacheDir, hash + ".png"); + final Uri urldisplay = Uri.fromParts(uri.getScheme(), uri.getHost(), "favicon.ico"); + // checks to see if the image exists + if (!image.exists()) { + FileOutputStream fos = null; + InputStream in = null; + try { + // if not, download it... + final URL urlDownload = new URL(urldisplay.toString()); + final HttpURLConnection connection = (HttpURLConnection) urlDownload.openConnection(); + connection.setDoInput(true); + connection.connect(); + in = connection.getInputStream(); + + if (in != null) { + mIcon = BitmapFactory.decodeStream(in); + } + // ...and cache it + if (mIcon != null) { + fos = new FileOutputStream(image); + mIcon.compress(Bitmap.CompressFormat.PNG, 100, fos); + fos.flush(); + Log.d(Constants.TAG, "Downloaded: " + urldisplay); + } + + } catch (Exception e) { + e.printStackTrace(); + } finally { + Utils.close(in); + Utils.close(fos); + } + } else { + // if it exists, retrieve it from the cache + mIcon = BitmapFactory.decodeFile(image.getPath()); + } + if (mIcon == null) { + InputStream in = null; + FileOutputStream fos = null; + try { + // if not, download it... + final URL urlDownload = new URL("https://www.google.com/s2/favicons?domain_url=" + + uri.toString()); + final HttpURLConnection connection = (HttpURLConnection) urlDownload.openConnection(); + connection.setDoInput(true); + connection.connect(); + in = connection.getInputStream(); + + if (in != null) { + mIcon = BitmapFactory.decodeStream(in); + } + // ...and cache it + if (mIcon != null) { + fos = new FileOutputStream(image); + mIcon.compress(Bitmap.CompressFormat.PNG, 100, fos); + fos.flush(); + } + + } catch (Exception e) { + e.printStackTrace(); + } finally { + Utils.close(in); + Utils.close(fos); + } + } + if (mIcon == null) { + return mDefaultBitmap; + } else { + return mIcon; + } + } + + protected void onPostExecute(Bitmap result) { + final Bitmap fav = Utils.padFavicon(result); + bmImage.setImageBitmap(fav); + mWeb.setBitmap(fav); + // notifyBookmarkDataSetChanged(); + } +} diff --git a/app/src/main/java/acr/browser/lightning/utils/Utils.java b/app/src/main/java/acr/browser/lightning/utils/Utils.java index 837bdeb..4825c1b 100644 --- a/app/src/main/java/acr/browser/lightning/utils/Utils.java +++ b/app/src/main/java/acr/browser/lightning/utils/Utils.java @@ -34,8 +34,11 @@ import android.webkit.URLUtil; import java.io.Closeable; import java.io.File; import java.io.IOException; +import java.math.BigInteger; import java.net.URI; import java.net.URISyntaxException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; import java.text.SimpleDateFormat; import java.util.Date; @@ -309,4 +312,20 @@ public final class Utils { canvas.drawPath(wallpath, paint); } + /** + * Calculate the SHA-1 hash of the given string + * @param str the string to hash + * @return the long representation of the hash + */ + public static long hash(final String str) { + try { + final MessageDigest digest = MessageDigest.getInstance("SHA-1"); + final byte[] bytes = digest.digest(str.getBytes()); + final BigInteger intRepr = new BigInteger(bytes); + return intRepr.longValue(); + } catch (NoSuchAlgorithmException e) { + Log.e(Constants.TAG, "The device has not SHA-1 support", e); + return 0; + } + } } diff --git a/app/src/main/java/acr/browser/lightning/view/LightningView.java b/app/src/main/java/acr/browser/lightning/view/LightningView.java index e7d06c0..1511aec 100644 --- a/app/src/main/java/acr/browser/lightning/view/LightningView.java +++ b/app/src/main/java/acr/browser/lightning/view/LightningView.java @@ -56,6 +56,8 @@ import java.io.IOException; import java.net.URISyntaxException; import acr.browser.lightning.R; +import acr.browser.lightning.bus.BrowserEvents; +import acr.browser.lightning.bus.BusProvider; import acr.browser.lightning.constant.Constants; import acr.browser.lightning.constant.StartPage; import acr.browser.lightning.controller.BrowserController; @@ -98,6 +100,7 @@ public class LightningView { private PermissionsManager mPermissionsManager; private static final String[] PERMISSIONS = new String[]{Manifest.permission.ACCESS_FINE_LOCATION}; + @SuppressLint("NewApi") public LightningView(Activity activity, String url, boolean darkTheme, boolean isIncognito) { mActivity = activity; @@ -175,6 +178,7 @@ public class LightningView { * if you don't have a reference to them * @param context the context in which the WebView was created */ + @SuppressLint("NewApi") public synchronized void initializePreferences(@Nullable WebSettings settings, Context context) { if (settings == null && mWebView == null) { return; @@ -293,6 +297,7 @@ public class LightningView { * @param settings the WebSettings object to use. * @param context the Context which was used to construct the WebView. */ + @SuppressLint("NewApi") private void initializeSettings(WebSettings settings, Context context) { if (API < Build.VERSION_CODES.JELLY_BEAN_MR2) { settings.setAppCacheMaxSize(Long.MAX_VALUE); @@ -347,6 +352,7 @@ public class LightningView { mToggleDesktop = !mToggleDesktop; } + @SuppressLint("NewApi") public void setUserAgent(Context context, int choice) { if (mWebView == null) return; WebSettings settings = mWebView.getSettings(); @@ -526,6 +532,7 @@ public class LightningView { } } + @SuppressLint("NewApi") public synchronized void find(String text) { if (mWebView != null) { if (API >= Build.VERSION_CODES.JELLY_BEAN_MR1) { @@ -645,11 +652,11 @@ public class LightningView { return null; } + @SuppressLint("NewApi") @Override public void onPageFinished(WebView view, String url) { if (view.isShown()) { mBrowserController.updateUrl(url, true); - mBrowserController.updateBookmarkIndicator(url); view.postInvalidate(); } if (view.getTitle() == null || view.getTitle().isEmpty()) { @@ -667,7 +674,6 @@ public class LightningView { public void onPageStarted(WebView view, String url, Bitmap favicon) { if (isShown()) { mBrowserController.updateUrl(url, false); - mBrowserController.updateBookmarkIndicator(url); mBrowserController.showActionBar(); } mTitle.setFavicon(mWebpageBitmap); @@ -723,6 +729,7 @@ public class LightningView { private boolean mIsRunning = false; private float mZoomScale = 0.0f; + @SuppressLint("NewApi") @Override public void onScaleChanged(final WebView view, final float oldScale, final float newScale) { if (view.isShown() && mTextReflow && API >= android.os.Build.VERSION_CODES.KITKAT) { diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index db9476a..6ba6418 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -27,7 +27,19 @@ - + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/bookmark_drawer.xml b/app/src/main/res/layout/bookmark_drawer.xml index 0a5e553..b84bedd 100644 --- a/app/src/main/res/layout/bookmark_drawer.xml +++ b/app/src/main/res/layout/bookmark_drawer.xml @@ -1,13 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/raw/default_bookmarks.dat b/app/src/main/res/raw/default_bookmarks.dat new file mode 100644 index 0000000..4607c15 --- /dev/null +++ b/app/src/main/res/raw/default_bookmarks.dat @@ -0,0 +1,5 @@ +{"url": "https://twitter.com/RestainoAnthony", "title": "The Developer", "folder": "", "order": 0} +{"url": "https://www.facebook.com/", "title": "Facebook", "folder": "", "order": 2} +{"url": "https://twitter.com", "title": "Twitter", "folder": "", "order": 3} +{"url": "https://www.google.com/", "title": "Google", "folder": "", "order": 4} +{"url": "https://www.yahoo.com/", "title": "Yahoo", "folder": "", "order": 5} diff --git a/external/netcipher b/external/netcipher index be23314..442d282 160000 --- a/external/netcipher +++ b/external/netcipher @@ -1 +1 @@ -Subproject commit be233148c1c644b77b4f90089c82d85a50940c57 +Subproject commit 442d282b07940a9992f54fcf61c44e12472cca83