Merge "Import initial translations for 20 new locales."
diff --git a/res/layout/bookmarklistwidget.xml b/res/layout/bookmarklistwidget.xml
index ffaa0c3..983854c 100644
--- a/res/layout/bookmarklistwidget.xml
+++ b/res/layout/bookmarklistwidget.xml
@@ -19,7 +19,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
- android:background="#00000000"
+ android:background="@null"
android:focusable="true"
android:clickable="true">
<LinearLayout
@@ -28,7 +28,7 @@
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="8dip"
- android:background="#383847">
+ android:background="@color/bookmarkWidgetHeader">
<ImageView
android:id="@+id/logo"
android:layout_width="32dp"
@@ -40,15 +40,14 @@
android:layout_gravity="center_vertical"
android:text="@string/tab_bookmarks"
android:textAppearance="?android:attr/textAppearanceMedium"
- android:textColor="@color/white"
android:paddingLeft="8dip" />
</LinearLayout>
<ListView
android:id="@+id/bookmarks_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:background="#2b2b3c"
- android:cacheColorHint="#2b2b3c"
- android:dividerHeight="0dp"
- android:divider="#00000000" />
+ android:background="@color/bookmarkWidgetItemBackground"
+ android:cacheColorHint="@color/bookmarkWidgetItemBackground"
+ android:dividerHeight="1px"
+ android:divider="@color/bookmarkWidgetDivider" />
</LinearLayout>
diff --git a/res/layout/bookmarklistwidget_item.xml b/res/layout/bookmarklistwidget_item.xml
index 2257a26..9e41d39 100644
--- a/res/layout/bookmarklistwidget_item.xml
+++ b/res/layout/bookmarklistwidget_item.xml
@@ -19,9 +19,10 @@
android:id="@+id/list_item"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:minHeight="@dimen/widgetItemMinHeight"
android:orientation="horizontal"
android:padding="8dip"
- android:background="#383847">
+ android:background="@color/bookmarkWidgetFolderBackground">
<ImageView
android:id="@+id/thumb"
android:src="@drawable/browser_thumbnail"
@@ -35,7 +36,6 @@
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="@color/white"
android:paddingLeft="8dip"
android:maxLines="1"
android:scrollHorizontally="true"
diff --git a/res/menu/historycontext.xml b/res/menu/historycontext.xml
index bd4ede4..3eaeb20 100644
--- a/res/menu/historycontext.xml
+++ b/res/menu/historycontext.xml
@@ -15,6 +15,7 @@
-->
<menu xmlns:android="http://schemas.android.com/apk/res/android">
+ <group android:id="@+id/CONTEXT_MENU">
<item android:id="@+id/open_context_menu_id"
android:title="@string/contextmenu_openlink"/>
<item android:id="@+id/new_window_context_menu_id"
@@ -29,4 +30,5 @@
android:title="@string/remove_history_item"/>
<item android:id="@+id/homepage_context_menu_id"
android:title="@string/set_as_homepage"/>
+ </group>
</menu>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 822c3b4..5a5d255 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -24,4 +24,9 @@
<color name="black">#ff000000</color>
<color name="geolocation_permissions_prompt_background">#ffdddddd</color>
+
+ <color name="bookmarkWidgetHeader">#383847</color>
+ <color name="bookmarkWidgetDivider">#383847</color>
+ <color name="bookmarkWidgetItemBackground">#2b2b3c</color>
+ <color name="bookmarkWidgetFolderBackground">#A0383847</color>
</resources>
diff --git a/res/values/dimensions.xml b/res/values/dimensions.xml
index f550cf7..404b2ac 100644
--- a/res/values/dimensions.xml
+++ b/res/values/dimensions.xml
@@ -23,4 +23,5 @@
<dimen name="bookmarkThumbnailHeight">80dip</dimen>
<dimen name="add_bookmark_width">500dip</dimen>
<dimen name="folder_selector_height">300dip</dimen>
+ <dimen name="widgetItemMinHeight">48dip</dimen>
</resources>
diff --git a/res/values/integers.xml b/res/values/integers.xml
index c923805..4e029b1 100644
--- a/res/values/integers.xml
+++ b/res/values/integers.xml
@@ -21,4 +21,6 @@
<!-- The duration of the tab animations in millisecs -->
<integer name="tab_animation_duration">500</integer>
<integer name="max_width_crumb">200</integer>
+ <!-- The maximum number of most visited URLs in the history tab -->
+ <integer name="most_visits_limit">10</integer>
</resources>
diff --git a/src/com/android/browser/BrowserHistoryPage.java b/src/com/android/browser/BrowserHistoryPage.java
index 3b0292d..a3ce0b4 100644
--- a/src/com/android/browser/BrowserHistoryPage.java
+++ b/src/com/android/browser/BrowserHistoryPage.java
@@ -32,8 +32,10 @@
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
+import android.net.Uri;
import android.os.Bundle;
import android.provider.Browser;
+import android.provider.BrowserContract;
import android.provider.BrowserContract.History;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
@@ -47,6 +49,7 @@
import android.widget.ExpandableListView;
import android.widget.ExpandableListView.ExpandableListContextMenuInfo;
import android.widget.ExpandableListView.OnChildClickListener;
+import android.widget.TextView;
import android.widget.Toast;
/**
@@ -57,6 +60,7 @@
implements LoaderCallbacks<Cursor>, OnChildClickListener {
static final int LOADER_HISTORY = 1;
+ static final int LOADER_MOST_VISITED = 2;
BookmarksHistoryCallbacks mCallbacks;
ExpandableListView mList;
@@ -64,6 +68,7 @@
HistoryAdapter mAdapter;
boolean mDisableNewWindow;
HistoryItem mContextHeader;
+ String mMostVisitsLimit;
// Implementation of WebIconDatabase.IconListener
class IconReceiver implements IconListener {
@@ -83,6 +88,7 @@
History.TITLE, // 2
History.URL, // 3
History.FAVICON, // 4
+ History.VISITS // 5
};
static final int INDEX_ID = 0;
@@ -90,6 +96,7 @@
static final int INDEX_TITE = 2;
static final int INDEX_URL = 3;
static final int INDEX_FAVICON = 4;
+ static final int INDEX_VISITS = 5;
}
private void copy(CharSequence text) {
@@ -114,6 +121,16 @@
return loader;
}
+ case LOADER_MOST_VISITED: {
+ Uri uri = History.CONTENT_URI
+ .buildUpon()
+ .appendQueryParameter(BrowserContract.PARAM_LIMIT, mMostVisitsLimit)
+ .build();
+ CursorLoader loader = new CursorLoader(getActivity(), uri,
+ HistoryQuery.PROJECTION, null, null, History.VISITS + " DESC");
+ return loader;
+ }
+
default: {
throw new IllegalArgumentException();
}
@@ -129,20 +146,15 @@
// Add an empty view late, so it does not claim an empty
// history before the adapter is present
mList.setEmptyView(mEmptyView);
+ break;
+ }
- // Do not post the runnable if there is nothing in the list.
- if (mList.getExpandableListAdapter().getGroupCount() > 0) {
- mList.post(new Runnable() {
- @Override
- public void run() {
- // In case the history gets cleared before this
- // event happens
- if (mList.getExpandableListAdapter().getGroupCount() > 0) {
- mList.expandGroup(0);
- }
- }
- });
- }
+ case LOADER_MOST_VISITED: {
+ mAdapter.changeMostVisitedCursor(data);
+
+ // Add an empty view late, so it does not claim an empty
+ // history before the adapter is present
+ mList.setEmptyView(mEmptyView);
break;
}
@@ -160,6 +172,8 @@
Bundle args = getArguments();
mDisableNewWindow = args.getBoolean(BrowserBookmarksPage.EXTRA_DISABLE_WINDOW, false);
+ int mvlimit = getResources().getInteger(R.integer.most_visits_limit);
+ mMostVisitsLimit = Integer.toString(mvlimit);
}
@Override
@@ -177,6 +191,7 @@
// Start the loader
getLoaderManager().initLoader(LOADER_HISTORY, null, this);
+ getLoaderManager().initLoader(LOADER_MOST_VISITED, null, this);
// Register to receive icons in case they haven't all been loaded.
CombinedBookmarkHistoryView.getIconListenerSet().addListener(mIconReceiver);
@@ -188,6 +203,7 @@
super.onDestroy();
CombinedBookmarkHistoryView.getIconListenerSet().removeListener(mIconReceiver);
getLoaderManager().stopLoader(LOADER_HISTORY);
+ getLoaderManager().stopLoader(LOADER_MOST_VISITED);
}
@Override
@@ -329,11 +345,102 @@
}
private class HistoryAdapter extends DateSortedExpandableListAdapter {
+ private Cursor mMostVisited, mHistoryCursor;
+
HistoryAdapter(Context context) {
super(context, HistoryQuery.INDEX_DATE_LAST_VISITED);
}
@Override
+ public void changeCursor(Cursor cursor) {
+ mHistoryCursor = cursor;
+ super.changeCursor(cursor);
+ }
+
+ void changeMostVisitedCursor(Cursor cursor) {
+ if (mMostVisited == cursor) {
+ return;
+ }
+ if (mMostVisited != null) {
+ mMostVisited.unregisterDataSetObserver(mDataSetObserver);
+ mMostVisited.close();
+ }
+ mMostVisited = cursor;
+ mMostVisited.registerDataSetObserver(mDataSetObserver);
+ }
+
+ @Override
+ public long getChildId(int groupPosition, int childPosition) {
+ if (!mDataValid) return 0;
+ if (moveCursorToChildPosition(groupPosition, childPosition)) {
+ Cursor cursor = getCursor(groupPosition);
+ return cursor.getLong(HistoryQuery.INDEX_ID);
+ }
+ return 0;
+ }
+
+ @Override
+ public int getGroupCount() {
+ return super.getGroupCount() + (mMostVisited != null ? 1 : 0);
+ }
+
+ @Override
+ public int getChildrenCount(int groupPosition) {
+ if (groupPosition >= super.getGroupCount()) {
+ return mMostVisited.getCount();
+ }
+ return super.getChildrenCount(groupPosition);
+ }
+
+ @Override
+ public boolean isEmpty() {
+ if (!super.isEmpty()) {
+ return false;
+ }
+ return mMostVisited == null
+ || mMostVisited.isClosed()
+ || mMostVisited.getCount() == 0;
+ }
+
+ Cursor getCursor(int groupPosition) {
+ if (groupPosition >= super.getGroupCount()) {
+ return mMostVisited;
+ }
+ return mHistoryCursor;
+ }
+
+ @Override
+ public View getGroupView(int groupPosition, boolean isExpanded,
+ View convertView, ViewGroup parent) {
+ if (groupPosition >= super.getGroupCount()) {
+ if (!mDataValid) throw new IllegalStateException("Data is not valid");
+ TextView item;
+ if (null == convertView || !(convertView instanceof TextView)) {
+ LayoutInflater factory = LayoutInflater.from(getContext());
+ item = (TextView) factory.inflate(R.layout.history_header, null);
+ } else {
+ item = (TextView) convertView;
+ }
+ item.setText(R.string.tab_most_visited);
+ return item;
+ }
+ return super.getGroupView(groupPosition, isExpanded, convertView, parent);
+ }
+
+ @Override
+ boolean moveCursorToChildPosition(
+ int groupPosition, int childPosition) {
+ if (groupPosition >= super.getGroupCount()) {
+ if (mDataValid && !mMostVisited.isClosed()) {
+ mMostVisited.moveToPosition(childPosition);
+ return true;
+ }
+ return false;
+ }
+ return super.moveCursorToChildPosition(groupPosition, childPosition);
+ }
+
+ @Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
View convertView, ViewGroup parent) {
HistoryItem item;
@@ -354,10 +461,11 @@
return item;
}
- item.setName(getString(HistoryQuery.INDEX_TITE));
- String url = getString(HistoryQuery.INDEX_URL);
+ Cursor cursor = getCursor(groupPosition);
+ item.setName(cursor.getString(HistoryQuery.INDEX_TITE));
+ String url = cursor.getString(HistoryQuery.INDEX_URL);
item.setUrl(url);
- byte[] data = getBlob(HistoryQuery.INDEX_FAVICON);
+ byte[] data = cursor.getBlob(HistoryQuery.INDEX_FAVICON);
if (data != null) {
item.setFavicon(BitmapFactory.decodeByteArray(data, 0,
data.length));
diff --git a/src/com/android/browser/Controller.java b/src/com/android/browser/Controller.java
index 7d183f6..caaa2c2 100644
--- a/src/com/android/browser/Controller.java
+++ b/src/com/android/browser/Controller.java
@@ -1542,6 +1542,11 @@
}
public boolean onContextItemSelected(MenuItem item) {
+ // Let the History and Bookmark fragments handle menus they created.
+ if (item.getGroupId() == R.id.CONTEXT_MENU) {
+ return false;
+ }
+
// chording is not an issue with context menus, but we use the same
// options selector, so set mCanChord to true so we can access them.
mCanChord = true;
diff --git a/src/com/android/browser/OpenDownloadReceiver.java b/src/com/android/browser/OpenDownloadReceiver.java
index 0f0ba70..4277ff4 100644
--- a/src/com/android/browser/OpenDownloadReceiver.java
+++ b/src/com/android/browser/OpenDownloadReceiver.java
@@ -22,6 +22,8 @@
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
+import android.os.Handler;
+import android.os.HandlerThread;
/**
* This {@link BroadcastReceiver} handles clicks to notifications that
@@ -30,8 +32,14 @@
* a complete, successful download will open the file.
*/
public class OpenDownloadReceiver extends BroadcastReceiver {
+ private static Handler sAsyncHandler;
+ static {
+ HandlerThread thr = new HandlerThread("Open browser download async");
+ thr.start();
+ sAsyncHandler = new Handler(thr.getLooper());
+ }
@Override
- public void onReceive(Context context, Intent intent) {
+ public void onReceive(final Context context, Intent intent) {
String action = intent.getAction();
if (!DownloadManager.ACTION_NOTIFICATION_CLICKED.equals(action)) {
openDownloadsPage(context);
@@ -43,7 +51,19 @@
openDownloadsPage(context);
return;
}
- long id = ids[0];
+ final long id = ids[0];
+ final PendingResult result = goAsync();
+ Runnable worker = new Runnable() {
+ @Override
+ public void run() {
+ onReceiveAsync(context, id);
+ result.finish();
+ }
+ };
+ sAsyncHandler.post(worker);
+ }
+
+ private void onReceiveAsync(Context context, long id) {
DownloadManager manager = (DownloadManager) context.getSystemService(
Context.DOWNLOAD_SERVICE);
Uri uri = manager.getUriForDownloadedFile(id);
diff --git a/src/com/android/browser/widget/BookmarkListWidgetService.java b/src/com/android/browser/widget/BookmarkListWidgetService.java
index 1120536..14b52b7 100644
--- a/src/com/android/browser/widget/BookmarkListWidgetService.java
+++ b/src/com/android/browser/widget/BookmarkListWidgetService.java
@@ -233,7 +233,7 @@
views.setDrawableParameters(R.id.list_item, true, 0, -1, null, -1);
if (res.mIsFolder) {
if (folder != null && res.mId == folder.mId) {
- views.setDrawableParameters(R.id.list_item, true, 140, -1, null, -1);
+ views.setDrawableParameters(R.id.list_item, true, 255, -1, null, -1);
views.setImageViewResource(R.id.thumb, R.drawable.ic_back_normal);
} else {
views.setImageViewResource(R.id.thumb, R.drawable.ic_folder);