Bug 882715 - Implement history/last tabs buttons in VisitedPage (r=bnicholson)
authorLucas Rocha <lucasr@mozilla.com>
Mon, 08 Jul 2013 23:05:51 +0100
changeset 143390 d239a58564cb
parent 143389 6c702f748e20
child 143391 5dd5b41a64b8
push id25130
push userlrocha@mozilla.com
push dateWed, 21 Aug 2013 09:41:27 +0000
treeherdermozilla-central@b2486721572e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbnicholson
bugs882715
milestone25.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 882715 - Implement history/last tabs buttons in VisitedPage (r=bnicholson)
mobile/android/base/BrowserApp.java
mobile/android/base/Makefile.in
mobile/android/base/home/HomeFragment.java
mobile/android/base/home/HomePager.java
mobile/android/base/home/VisitedPage.java
mobile/android/base/locales/en-US/android_strings.dtd
mobile/android/base/resources/layout/home_visited_page.xml
mobile/android/base/resources/values/styles.xml
mobile/android/base/strings.xml.in
--- a/mobile/android/base/BrowserApp.java
+++ b/mobile/android/base/BrowserApp.java
@@ -1426,16 +1426,23 @@ abstract public class BrowserApp extends
             return;
         }
 
         final Tab tab = Tabs.getInstance().getSelectedTab();
         if (tab != null && isAboutHome(tab)) {
             return;
         }
 
+        // Hide any visible homepager subpages
+        final FragmentManager fm = getSupportFragmentManager();
+        final Fragment subPage = fm.findFragmentByTag(HomePager.SUBPAGE_TAG);
+        if (subPage != null) {
+            fm.beginTransaction().remove(subPage).commitAllowingStateLoss();
+        }
+
         // FIXME: do animation if animate is true
         mHomePager.hide();
 
         mBrowserToolbar.setShadowVisibility(true);
         mBrowserToolbar.setNextFocusDownId(R.id.layer_view);
 
         // Refresh toolbar height to possibly restore the toolbar padding
         refreshToolbarHeight();
--- a/mobile/android/base/Makefile.in
+++ b/mobile/android/base/Makefile.in
@@ -466,16 +466,17 @@ RES_LAYOUT = \
   res/layout/find_in_page_content.xml \
   res/layout/font_size_preference.xml \
   res/layout/gecko_app.xml \
   res/layout/home_bookmarks_page.xml \
   res/layout/home_item_row.xml \
   res/layout/home_header_row.xml \
   res/layout/home_list_with_title.xml \
   res/layout/home_search_item_row.xml \
+  res/layout/home_visited_page.xml \
   res/layout/web_app.xml \
   res/layout/launch_app_list.xml \
   res/layout/launch_app_listitem.xml \
   res/layout/menu_action_bar.xml \
   res/layout/menu_item_action_view.xml \
   res/layout/menu_popup.xml \
   res/layout/notification_icon_text.xml \
   res/layout/notification_progress.xml \
--- a/mobile/android/base/home/HomeFragment.java
+++ b/mobile/android/base/home/HomeFragment.java
@@ -41,16 +41,22 @@ class HomeFragment extends Fragment {
     private static final String LOGTAG="GeckoHomeFragment";
 
     // Share MIME type.
     private static final String SHARE_MIME_TYPE = "text/plain";
 
     // URL to Title replacement regex.
     private static final String REGEX_URL_TO_TITLE = "^([a-z]+://)?(www\\.)?";
 
+    protected void showSubPage(Fragment subPage) {
+        getActivity().getSupportFragmentManager().beginTransaction()
+                .addToBackStack(null).replace(R.id.home_pager_container, subPage, HomePager.SUBPAGE_TAG)
+                .commitAllowingStateLoss();
+    }
+
     @Override
     public void onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo menuInfo) {
         if (!(menuInfo instanceof HomeContextMenuInfo)) {
             return;
         }
 
         HomeContextMenuInfo info = (HomeContextMenuInfo) menuInfo;
 
--- a/mobile/android/base/home/HomePager.java
+++ b/mobile/android/base/home/HomePager.java
@@ -17,16 +17,19 @@ import android.support.v4.view.ViewPager
 import android.util.AttributeSet;
 import android.view.ViewGroup;
 
 import java.util.ArrayList;
 import java.util.EnumMap;
 import java.util.EnumSet;
 
 public class HomePager extends ViewPager {
+    // Subpage fragment tag
+    public static final String SUBPAGE_TAG = "home_pager_subpage";
+
     private final Context mContext;
     private volatile boolean mLoaded;
 
     // List of pages in order.
     private enum Page {
         VISITED,
         BOOKMARKS,
         READING_LIST
--- a/mobile/android/base/home/VisitedPage.java
+++ b/mobile/android/base/home/VisitedPage.java
@@ -38,16 +38,22 @@ public class VisitedPage extends HomeFra
     private static final int FAVICONS_LOADER_ID = 1;
 
     // Adapter for the list of search results
     private VisitedAdapter mAdapter;
 
     // The view shown by the fragment.
     private ListView mList;
 
+    // Empty message view
+    private View mEmptyMessage;
+
+    // Buttons container
+    private View mButtonsContainer;
+
     // Callbacks used for the search and favicon cursor loaders
     private CursorLoaderCallbacks mCursorLoaderCallbacks;
 
     // On URL open listener
     private OnUrlOpenListener mUrlOpenListener;
 
     public VisitedPage() {
         mUrlOpenListener = null;
@@ -69,46 +75,66 @@ public class VisitedPage extends HomeFra
     public void onDetach() {
         super.onDetach();
 
         mUrlOpenListener = null;
     }
 
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
-        // All list views are styled to look the same with a global activity theme.
-        // If the style of the list changes, inflate it from an XML.
-        mList = new HomeListView(container.getContext());
-        return mList;
+        return inflater.inflate(R.layout.home_visited_page, container, false);
     }
 
     @Override
     public void onViewCreated(View view, Bundle savedInstanceState) {
         super.onViewCreated(view, savedInstanceState);
 
+        mList = (HomeListView) view.findViewById(R.id.visited_list);
+
         mList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
             @Override
             public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                 final Cursor c = mAdapter.getCursor();
                 if (c == null || !c.moveToPosition(position)) {
                     return;
                 }
 
                 final String url = c.getString(c.getColumnIndexOrThrow(URLColumns.URL));
                 mUrlOpenListener.onUrlOpen(url);
             }
         });
 
         registerForContextMenu(mList);
+
+        mEmptyMessage = view.findViewById(R.id.empty_message);
+        mButtonsContainer = view.findViewById(R.id.buttons_container);
+
+        final View historyButton = view.findViewById(R.id.history_button);
+        historyButton.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                showHistoryPage();
+            }
+        });
+
+        final View tabsButton = view.findViewById(R.id.tabs_button);
+        tabsButton.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                showTabsPage();
+            }
+        });
     }
 
     @Override
     public void onDestroyView() {
         super.onDestroyView();
         mList = null;
+        mButtonsContainer = null;
+        mEmptyMessage = null;
     }
 
     @Override
     public void onActivityCreated(Bundle savedInstanceState) {
         super.onActivityCreated(savedInstanceState);
 
         // Intialize the search adapter
         mAdapter = new VisitedAdapter(getActivity(), null);
@@ -116,16 +142,26 @@ public class VisitedPage extends HomeFra
 
         // Create callbacks before the initial loader is started
         mCursorLoaderCallbacks = new CursorLoaderCallbacks();
 
         // Reconnect to the loader only if present
         getLoaderManager().initLoader(FRECENCY_LOADER_ID, null, mCursorLoaderCallbacks);
     }
 
+    private void showHistoryPage() {
+        final HistoryPage historyPage = HistoryPage.newInstance();
+        showSubPage(historyPage);
+    }
+
+    private void showTabsPage() {
+        final LastTabsPage lastTabsPage = LastTabsPage.newInstance();
+        showSubPage(lastTabsPage);
+    }
+
     private static class FrecencyCursorLoader extends SimpleCursorLoader {
         // Max number of search results
         private static final int SEARCH_LIMIT = 50;
 
         public FrecencyCursorLoader(Context context) {
             super(context);
         }
 
@@ -167,16 +203,23 @@ public class VisitedPage extends HomeFra
             return null;
         }
 
         @Override
         public void onLoadFinished(Loader<Cursor> loader, Cursor c) {
             final int loaderId = loader.getId();
             switch(loaderId) {
             case FRECENCY_LOADER_ID:
+                // Only set empty view once cursor is loaded to avoid
+                // flashing the empty message before loading.
+                mList.setEmptyView(mEmptyMessage);
+
+                final int buttonsVisibility = (c.getCount() == 0 ? View.GONE : View.VISIBLE);
+                mButtonsContainer.setVisibility(buttonsVisibility);
+
                 mAdapter.swapCursor(c);
 
                 FaviconsLoader.restartFromCursor(getLoaderManager(), FAVICONS_LOADER_ID,
                         mCursorLoaderCallbacks, c);
                 break;
 
             case FAVICONS_LOADER_ID:
                 // Causes the listview to recreate its children and use the
--- a/mobile/android/base/locales/en-US/android_strings.dtd
+++ b/mobile/android/base/locales/en-US/android_strings.dtd
@@ -269,16 +269,17 @@ size. -->
 <!ENTITY abouthome_addons_title "Add-ons for your &brandShortName;">
 <!ENTITY abouthome_addons_browse "Browse all &brandShortName; add-ons">
 <!ENTITY abouthome_last_tabs_title "Your tabs from last time">
 <!ENTITY abouthome_last_tabs_open "Open all tabs from last time">
 <!ENTITY abouthome_top_sites_title "Top sites">
 <!ENTITY abouthome_topsites_edit "Edit">
 <!ENTITY abouthome_topsites_pin "Pin Site">
 <!ENTITY abouthome_topsites_unpin "Unpin Site">
+<!ENTITY abouthome_visited_empty "Websites you visited go here">
 
 <!-- Localization note (abouthome_about_sync3, abouthome_about_apps2): The
      chevron (ex: "»"; unicode= U+00BB) is used as an arrow to show that
      clicking this text in the promotions box will perform some action. Note
      that a non-breaking space (unicode= U+00A0) should be used between this
      character and the remainder of the string to prevent word wrap. -->
 <!ENTITY abouthome_about_sync3 "Set up Firefox Sync to access bookmarks, history and tabs from your other devices&#x00A0;»">
 <!ENTITY abouthome_about_apps3 "Get apps from the Firefox Marketplace and discover the best the Web has to offer&#x00A0;»">
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/resources/layout/home_visited_page.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:layout_width="fill_parent"
+              android:layout_height="fill_parent"
+              android:orientation="vertical">
+
+    <TextView android:id="@+id/empty_message"
+              style="@style/AboutHome.EmptyMessage"
+              android:layout_width="fill_parent"
+              android:layout_height="fill_parent"
+              android:text="@string/abouthome_visited_empty"
+              android:visibility="gone"/>
+
+    <org.mozilla.gecko.home.HomeListView
+            android:id="@+id/visited_list"
+            android:layout_width="fill_parent"
+            android:layout_height="fill_parent"
+            android:layout_weight="1"/>
+
+    <LinearLayout android:id="@+id/buttons_container"
+                  android:layout_width="fill_parent"
+                  android:layout_height="wrap_content"
+                  android:orientation="vertical"
+                  android:background="@color/background_light"
+                  android:visibility="gone">
+
+        <Button android:id="@+id/history_button"
+                style="@style/AboutHome.PageButton"
+                android:text="@string/history_title"/>
+
+        <View android:layout_width="fill_parent"
+              android:layout_height="1dip"
+              android:background="#FFD1D5DA"/>
+
+        <Button android:id="@+id/tabs_button"
+                style="@style/AboutHome.PageButton"
+                android:text="@string/abouthome_last_tabs_title"/>
+
+    </LinearLayout>
+
+</LinearLayout>
\ No newline at end of file
--- a/mobile/android/base/resources/values/styles.xml
+++ b/mobile/android/base/resources/values/styles.xml
@@ -497,16 +497,35 @@
     </style>
 
     <style name="AboutHome.LastTabRow.Url">
         <item name="android:textSize">12sp</item>
         <item name="android:singleLine">true</item>
         <item name="android:textColor">@color/abouthome_section_subtitle</item>
     </style>
 
+    <style name="AboutHome.EmptyMessage">
+        <item name="android:textAppearance">@style/AboutHome.TextAppearance.PageTitle</item>
+        <item name="android:gravity">center</item>
+        <item name="android:focusable">false</item>
+        <item name="android:paddingLeft">10dip</item>
+        <item name="android:paddingRight">10dip</item>
+    </style>
+
+    <style name="AboutHome.PageButton">
+        <item name="android:layout_width">fill_parent</item>
+        <item name="android:layout_height">40dip</item>
+        <item name="android:textAppearance">@style/AboutHome.TextAppearance.PageTitle</item>
+        <item name="android:background">@drawable/action_bar_button</item>
+        <item name="android:focusable">true</item>
+        <item name="android:gravity">center|left</item>
+        <item name="android:paddingLeft">10dip</item>
+        <item name="android:paddingRight">10dip</item>
+    </style>
+
     <style name="AboutHome.PageTitle">
         <item name="android:layout_width">fill_parent</item>
         <item name="android:layout_height">32dp</item>
         <item name="android:textAppearance">@style/AboutHome.TextAppearance.PageTitle</item>
         <item name="android:background">@color/background_light</item>
         <item name="android:focusable">false</item>
         <item name="android:gravity">center|left</item>
         <item name="android:paddingLeft">10dip</item>
--- a/mobile/android/base/strings.xml.in
+++ b/mobile/android/base/strings.xml.in
@@ -244,16 +244,18 @@
   <string name="abouthome_about_apps">&abouthome_about_apps3;</string>
   <string name="abouthome_sync_bold_name">&abouthome_sync_bold_name;</string>
   <string name="abouthome_apps_bold_name">&abouthome_apps_bold_name2;</string>
   
   <string name="abouthome_topsites_edit">&abouthome_topsites_edit;</string>
   <string name="abouthome_topsites_pin">&abouthome_topsites_pin;</string>
   <string name="abouthome_topsites_unpin">&abouthome_topsites_unpin;</string>
 
+  <string name="abouthome_visited_empty">&abouthome_visited_empty;</string>
+
   <string name="filepicker_title">&filepicker_title;</string>
   <string name="filepicker_audio_title">&filepicker_audio_title;</string>
   <string name="filepicker_image_title">&filepicker_image_title;</string>
   <string name="filepicker_video_title">&filepicker_video_title;</string>
 
   <!-- Default bookmarks. Use bookmarks titles shared with XUL from mobile's
        profile/bookmarks.inc. Don't expose the URLs to L10N. -->
   <string name="bookmarkdefaults_title_aboutfirefox">@bookmarks_aboutBrowser@</string>