Niedzielski has uploaded a new change for review. https://gerrit.wikimedia.org/r/227633
Change subject: ~50KiB ...................................................................... ~50KiB Change-Id: I5eacc8c07844253974cba6eb479bbcc8c5a2fa4f --- M wikipedia/build.gradle M wikipedia/proguard-rules.pro M wikipedia/res/values/preference_keys.xml M wikipedia/src/main/java/org/wikipedia/NavDrawerFragment.java M wikipedia/src/main/java/org/wikipedia/Site.java A wikipedia/src/main/java/org/wikipedia/data/GsonMarshaller.java A wikipedia/src/main/java/org/wikipedia/data/GsonUnmarshaller.java A wikipedia/src/main/java/org/wikipedia/data/TabUnmarshaller.java M wikipedia/src/main/java/org/wikipedia/nearby/NearbyFragment.java M wikipedia/src/main/java/org/wikipedia/page/HtmlPageLoadStrategy.java M wikipedia/src/main/java/org/wikipedia/page/JsonPageLoadStrategy.java M wikipedia/src/main/java/org/wikipedia/page/PageActivity.java M wikipedia/src/main/java/org/wikipedia/page/PageBackStackItem.java M wikipedia/src/main/java/org/wikipedia/page/PageInfoDialog.java M wikipedia/src/main/java/org/wikipedia/page/PageLoadStrategy.java M wikipedia/src/main/java/org/wikipedia/page/PageProperties.java M wikipedia/src/main/java/org/wikipedia/page/PageViewFragmentInternal.java M wikipedia/src/main/java/org/wikipedia/page/bottomcontent/BottomContentHandler.java M wikipedia/src/main/java/org/wikipedia/page/tabs/Tab.java M wikipedia/src/main/java/org/wikipedia/search/SearchArticlesFragment.java M wikipedia/src/main/java/org/wikipedia/settings/Prefs.java 21 files changed, 236 insertions(+), 166 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/apps/android/wikipedia refs/changes/33/227633/1 diff --git a/wikipedia/build.gradle b/wikipedia/build.gradle index a950b19..d560a57 100644 --- a/wikipedia/build.gradle +++ b/wikipedia/build.gradle @@ -127,6 +127,7 @@ compile 'com.android.support:appcompat-v7:22.2.1' // includes support-v4 compile 'com.android.support:design:22.2.1' compile 'com.android.support:percent:22.2.0' + compile 'com.google.code.gson:gson:2.3.1' compile 'com.squareup.okhttp:okhttp-urlconnection:2.4.0' compile 'com.squareup.okhttp:okhttp:2.4.0' compile 'com.squareup:otto:1.3.6' diff --git a/wikipedia/proguard-rules.pro b/wikipedia/proguard-rules.pro index b0e4737..439f2f0 100644 --- a/wikipedia/proguard-rules.pro +++ b/wikipedia/proguard-rules.pro @@ -85,3 +85,21 @@ # Our code: -keep class org.wikipedia.** {*;} -keep class org.mediawiki.api.json.** {*;} + +##---------------Begin: proguard configuration for Gson ---------- +# https://github.com/google/gson/blob/master/examples/android-proguard-example/proguard.cfg +# Gson uses generic type information stored in a class file when working with fields. Proguard +# removes such information by default, so configure it to keep all of it. +#-keepattributes Signature (already specified) + +# For using GSON @Expose annotation (already specified) +#-keepattributes *Annotation* + +# Gson specific classes +-keep class sun.misc.Unsafe { *; } +#-keep class com.google.gson.stream.** { *; } + +# Application classes that will be serialized/deserialized over Gson +-keep class com.google.gson.examples.android.model.** { *; } + +##---------------End: proguard configuration for Gson ---------- diff --git a/wikipedia/res/values/preference_keys.xml b/wikipedia/res/values/preference_keys.xml index 2de5ee6..b0e674c 100644 --- a/wikipedia/res/values/preference_keys.xml +++ b/wikipedia/res/values/preference_keys.xml @@ -31,4 +31,5 @@ <string name="preference_key_more_like_search_enabled">moreLikeSearchEnabled</string> <string name="preference_key_show_developer_settings">showDeveloperSettings</string> <string name="preference_key_last_run_time_format">%s-lastrun</string> + <string name="preference_key_tabs">tabs</string> </resources> diff --git a/wikipedia/src/main/java/org/wikipedia/NavDrawerFragment.java b/wikipedia/src/main/java/org/wikipedia/NavDrawerFragment.java index 8605550..1fef961 100644 --- a/wikipedia/src/main/java/org/wikipedia/NavDrawerFragment.java +++ b/wikipedia/src/main/java/org/wikipedia/NavDrawerFragment.java @@ -91,7 +91,8 @@ return; } HistoryEntry historyEntry = new HistoryEntry(title, HistoryEntry.SOURCE_RANDOM); - ((PageActivity) getActivity()).displayNewPage(title, historyEntry, false, true); + ((PageActivity) getActivity()).displayNewPage(title, historyEntry, + PageActivity.TabPosition.CURRENT_TAB, true); } @Override @@ -185,7 +186,7 @@ Intent intent = new Intent(); switch (view.getId()) { case R.id.nav_item_today: - ((PageActivity)getActivity()).displayMainPage(); + ((PageActivity)getActivity()).displayMainPageInCurrentTab(); break; case R.id.nav_item_history: ((PageActivity)getActivity()).pushFragment(new HistoryFragment()); @@ -233,7 +234,7 @@ if (!isAdded()) { return; } - ((PageActivity)getActivity()).displayMainPage(true); + ((PageActivity)getActivity()).displayMainPageInForegroundTab(); // and update any instances of our Featured Page widget, since it will // change with the currently selected language. Intent widgetIntent = new Intent(getActivity(), WidgetProviderFeaturedPage.class); diff --git a/wikipedia/src/main/java/org/wikipedia/Site.java b/wikipedia/src/main/java/org/wikipedia/Site.java index f2c58bc..baa2434 100644 --- a/wikipedia/src/main/java/org/wikipedia/Site.java +++ b/wikipedia/src/main/java/org/wikipedia/Site.java @@ -41,10 +41,6 @@ return "/w/" + script; } - public String getResourceLoaderPath() { - return getScriptPath("load.php"); - } - public String getApiDomain() { return WikipediaApp.getInstance().getSslFallback() ? domain : urlToMobileSite(domain); } diff --git a/wikipedia/src/main/java/org/wikipedia/data/GsonMarshaller.java b/wikipedia/src/main/java/org/wikipedia/data/GsonMarshaller.java new file mode 100644 index 0000000..23bdf3d --- /dev/null +++ b/wikipedia/src/main/java/org/wikipedia/data/GsonMarshaller.java @@ -0,0 +1,13 @@ +package org.wikipedia.data; + +import com.google.gson.Gson; + +public final class GsonMarshaller { + private static final Gson DEFAULT_GSON = new Gson(); + + public static String marshal(Object object) { + return DEFAULT_GSON.toJson(object); + } + + private GsonMarshaller() { } +} \ No newline at end of file diff --git a/wikipedia/src/main/java/org/wikipedia/data/GsonUnmarshaller.java b/wikipedia/src/main/java/org/wikipedia/data/GsonUnmarshaller.java new file mode 100644 index 0000000..0f1f087 --- /dev/null +++ b/wikipedia/src/main/java/org/wikipedia/data/GsonUnmarshaller.java @@ -0,0 +1,35 @@ +package org.wikipedia.data; + +import android.support.annotation.NonNull; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; + +import java.util.Collection; + +public final class GsonUnmarshaller { + private static final Gson DEFAULT_GSON = new Gson(); + + /** @return Unmarshalled object. */ + public static <T> T unmarshal(Class<T> clazz, @NonNull String json) { + return unmarshal(DEFAULT_GSON, clazz, json); + } + + /** @return Unmarshalled collection of objects. */ + public static <T extends Collection<?>> T unmarshal(TypeToken<T> typeToken, @NonNull String json) { + return unmarshal(DEFAULT_GSON, typeToken, json); + } + + /** @return Unmarshalled object. */ + public static <T> T unmarshal(@NonNull Gson gson, Class<T> clazz, @NonNull String json) { + return gson.fromJson(json, clazz); + } + + /** @return Unmarshalled collection of objects. */ + public static <T extends Collection<?>> T unmarshal(@NonNull Gson gson, TypeToken<T> typeToken, @NonNull String json) { + // From the manual: "Fairly hideous... Unfortunately, no way to get around this in Java". + return gson.fromJson(json, typeToken.getType()); + } + + private GsonUnmarshaller() { } +} \ No newline at end of file diff --git a/wikipedia/src/main/java/org/wikipedia/data/TabUnmarshaller.java b/wikipedia/src/main/java/org/wikipedia/data/TabUnmarshaller.java new file mode 100644 index 0000000..f66bb70 --- /dev/null +++ b/wikipedia/src/main/java/org/wikipedia/data/TabUnmarshaller.java @@ -0,0 +1,17 @@ +package org.wikipedia.data; + +import com.google.gson.reflect.TypeToken; + +import org.wikipedia.page.tabs.Tab; + +import java.util.List; + +public final class TabUnmarshaller { + private static final TypeToken<List<Tab>> TYPE_TOKEN = new TypeToken<List<Tab>>() { }; + + public static List<Tab> unmarshal(String json) { + return GsonUnmarshaller.unmarshal(TYPE_TOKEN, json); + } + + private TabUnmarshaller() { } +} \ No newline at end of file diff --git a/wikipedia/src/main/java/org/wikipedia/nearby/NearbyFragment.java b/wikipedia/src/main/java/org/wikipedia/nearby/NearbyFragment.java index 95e0cac..2bf2e8c 100644 --- a/wikipedia/src/main/java/org/wikipedia/nearby/NearbyFragment.java +++ b/wikipedia/src/main/java/org/wikipedia/nearby/NearbyFragment.java @@ -237,12 +237,14 @@ @Override public void onOpenLink(PageTitle title, HistoryEntry entry) { - ((PageActivity)getActivity()).displayNewPage(title, entry, false, false); + ((PageActivity)getActivity()).displayNewPage(title, entry, + PageActivity.TabPosition.CURRENT_TAB, false); } @Override public void onOpenInNewTab(PageTitle title, HistoryEntry entry) { - ((PageActivity)getActivity()).displayNewPage(title, entry, true, false); + ((PageActivity)getActivity()).displayNewPage(title, entry, + PageActivity.TabPosition.NEW_TAB_BACKGROUND, false); } }; diff --git a/wikipedia/src/main/java/org/wikipedia/page/HtmlPageLoadStrategy.java b/wikipedia/src/main/java/org/wikipedia/page/HtmlPageLoadStrategy.java index c167016..b416f68 100644 --- a/wikipedia/src/main/java/org/wikipedia/page/HtmlPageLoadStrategy.java +++ b/wikipedia/src/main/java/org/wikipedia/page/HtmlPageLoadStrategy.java @@ -14,7 +14,6 @@ import android.content.Intent; import android.graphics.Bitmap; import android.net.http.SslError; -import android.os.Bundle; import android.support.annotation.NonNull; import android.webkit.SslErrorHandler; import android.webkit.WebResourceRequest; @@ -23,6 +22,7 @@ import android.webkit.WebViewClient; import java.util.ArrayList; +import java.util.List; /** * Our new page load strategy, which loads the page via webView#loadUrl. @@ -93,7 +93,7 @@ } @Override - public void onActivityCreated(Bundle savedInstanceState) { + public void onActivityCreated(@NonNull List<PageBackStackItem> backStack) { setupSpecificMessageHandlers(); webView.setWebViewClient(new WebViewClient() { @@ -195,11 +195,6 @@ } @Override - public void onSaveInstanceState(Bundle outState) { - // nothing to do here - } - - @Override public void backFromEditing(Intent data) { // Retrieve section ID from intent, and find correct section, so we know where to scroll to // sectionTargetFromIntent = data.getIntExtra(EditSectionActivity.EXTRA_SECTION_ID, 0); @@ -266,7 +261,7 @@ } @Override - public void setBackStack(ArrayList<PageBackStackItem> backStack) { + public void setBackStack(@NonNull List<PageBackStackItem> backStack) { // TODO: implement switching of backstacks from multiple tabs. } diff --git a/wikipedia/src/main/java/org/wikipedia/page/JsonPageLoadStrategy.java b/wikipedia/src/main/java/org/wikipedia/page/JsonPageLoadStrategy.java index af704a2..ca51ba6 100644 --- a/wikipedia/src/main/java/org/wikipedia/page/JsonPageLoadStrategy.java +++ b/wikipedia/src/main/java/org/wikipedia/page/JsonPageLoadStrategy.java @@ -34,7 +34,6 @@ import android.content.Intent; import android.content.res.Resources; import android.os.Build; -import android.os.Bundle; import android.support.annotation.NonNull; import android.util.Log; import android.view.View; @@ -74,7 +73,7 @@ * Since the list consists of Parcelable objects, it can be saved and restored from the * savedInstanceState of the fragment. */ - private ArrayList<PageBackStackItem> backStack; + @NonNull private List<PageBackStackItem> backStack; /** * Sequence number to maintain synchronization when loading page content asynchronously @@ -114,7 +113,7 @@ } @Override - public void setBackStack(@NonNull ArrayList<PageBackStackItem> backStack) { + public void setBackStack(@NonNull List<PageBackStackItem> backStack) { this.backStack = backStack; } @@ -135,18 +134,12 @@ } @Override - public void onActivityCreated(Bundle savedInstanceState) { + public void onActivityCreated(@NonNull List<PageBackStackItem> backStack) { setupSpecificMessageHandlers(); currentSequenceNum = 0; - if (savedInstanceState != null) { - ArrayList<PageBackStackItem> tmpBackStack - = savedInstanceState.getParcelableArrayList("backStack"); - if (tmpBackStack != null) { // avoid setting backStack to null - backStack = tmpBackStack; - } - } + this.backStack = backStack; // if we already have pages in the backstack (whether it's from savedInstanceState, or // from being stored in the activity's fragment backstack), then load the topmost page @@ -218,13 +211,6 @@ bottomContentHandler = new BottomContentHandler(fragment, bridge, webView, fragment.getLinkHandler(), (ViewGroup) fragment.getView().findViewById(R.id.bottom_content_container)); - } - - @Override - public void onSaveInstanceState(Bundle outState) { - // update the topmost entry in the back stack - updateCurrentBackStackItem(); - outState.putParcelableArrayList("backStack", backStack); } @Override diff --git a/wikipedia/src/main/java/org/wikipedia/page/PageActivity.java b/wikipedia/src/main/java/org/wikipedia/page/PageActivity.java index fc365fa..cf5e594 100644 --- a/wikipedia/src/main/java/org/wikipedia/page/PageActivity.java +++ b/wikipedia/src/main/java/org/wikipedia/page/PageActivity.java @@ -64,6 +64,11 @@ import android.widget.TextView; public class PageActivity extends ThemedActionBarActivity { + public enum TabPosition { + CURRENT_TAB, + NEW_TAB_BACKGROUND, + NEW_TAB_FOREGROUND + } public static final String ACTION_PAGE_FOR_TITLE = "org.wikipedia.page_for_title"; public static final String EXTRA_PAGETITLE = "org.wikipedia.pagetitle"; public static final String EXTRA_HISTORYENTRY = "org.wikipedia.history.historyentry"; @@ -246,7 +251,7 @@ if (languageChanged) { app.resetSite(); - displayMainPage(); + displayMainPageInForegroundTab(); } // If we're coming back from a Theme change, we'll need to "restore" our state based on @@ -269,7 +274,7 @@ //multiple various exceptions may be thrown in the above few lines, so just catch all. Log.e("PageActivity", "Error while instantiating fragment.", e); //don't let the user see a blank screen, so just request the main page... - displayMainPage(); + displayMainPageInCurrentTab(); } } else if (savedInstanceState == null) { // if there's no savedInstanceState, and we're not coming back from a Theme change, @@ -407,16 +412,11 @@ new WidgetsFunnel(app).logSearchWidgetTap(); openSearch(); } else if (intent.hasExtra(EXTRA_FEATURED_ARTICLE_FROM_WIDGET)) { - displayMainPage(); - // Log that the user tapped on the featured article widget // Instantiate the funnel anonymously to save on memory overhead new WidgetsFunnel(app).logFeaturedArticleWidgetTap(); - } else { - // Unrecognized Intent was handled, or the user opened the app by tapping on the icon. - // Let us load the main page! - displayMainPage(); } + displayMainPageIfNoTabs(); } private void handleShareIntent(Intent intent) { @@ -461,10 +461,7 @@ * @return True if currently searching, false otherwise. */ public boolean isSearching() { - if (searchFragment == null) { - return false; - } - return searchFragment.isSearchActive(); + return searchFragment != null && searchFragment.isSearchActive(); } /** @@ -548,7 +545,14 @@ * @param entry HistoryEntry associated with this page. */ public void displayNewPage(PageTitle title, HistoryEntry entry) { - displayNewPage(title, entry, false, false); + displayNewPage(title, entry, TabPosition.CURRENT_TAB, false); + } + + public void displayNewPage(PageTitle title, + HistoryEntry entry, + TabPosition position, + boolean allowStateLoss) { + displayNewPage(title, entry, position, allowStateLoss, false); } /** @@ -556,11 +560,16 @@ * fragment manager. Useful for when this function is called from an AsyncTask result. * @param title Title of the page to load. * @param entry HistoryEntry associated with this page. - * @param inNewTab Whether to open this page in a new tab. + * @param position Whether to open this page in the current tab, a new background tab, or new + * foreground tab. * @param allowStateLoss Whether to allow state loss. + * @param mustBeEmpty If true, and a tab exists already, do nothing. */ - public void displayNewPage(final PageTitle title, final HistoryEntry entry, - final boolean inNewTab, boolean allowStateLoss) { + public void displayNewPage(final PageTitle title, + final HistoryEntry entry, + final TabPosition position, + boolean allowStateLoss, + final boolean mustBeEmpty) { ACRA.getErrorReporter().putCustomData("api", title.getSite().getApiDomain()); ACRA.getErrorReporter().putCustomData("title", title.toString()); @@ -584,7 +593,7 @@ if (!frag.getCurrentTab().getBackStack().isEmpty() && frag.getCurrentTab().getBackStack() .get(frag.getCurrentTab().getBackStack().size() - 1).getTitle() - .equals(title)) { + .equals(title) || mustBeEmpty && !frag.getCurrentTab().getBackStack().isEmpty()) { //if we have a section to scroll to, then pass it to the fragment if (!TextUtils.isEmpty(title.getFragment())) { frag.scrollToSection(title.getFragment()); @@ -592,32 +601,44 @@ return; } frag.closeFindInPage(); - if (inNewTab) { - frag.openInNewTabFromMenu(title, entry); - } else { + if (position == TabPosition.CURRENT_TAB) { frag.displayNewPage(title, entry, false, true); + } else if (position == TabPosition.NEW_TAB_BACKGROUND) { + frag.openInNewBackgroundTabFromMenu(title, entry); + } else { + frag.openInNewForegroundTabFromMenu(title, entry); } app.getSessionFunnel().pageViewed(entry); } }); } - /** - * Go directly to the Main Page of the current Wiki. - */ - public void displayMainPage() { - displayMainPage(false); + public void displayMainPageInCurrentTab() { + displayMainPage(false, TabPosition.CURRENT_TAB, false); + } + + public void displayMainPageInForegroundTab() { + displayMainPage(true, TabPosition.NEW_TAB_FOREGROUND, false); + } + + public void displayMainPageIfNoTabs() { + displayMainPage(false, TabPosition.CURRENT_TAB, true); } /** * Go directly to the Main Page of the current Wiki, optionally allowing state loss of the * fragment manager. Useful for when this function is called from an AsyncTask result. - * @param allowStateLoss Whether to allow state loss. + * @param allowStateLoss Allows the {@link android.support.v4.app.FragmentManager} commit to be + * executed after an activity's state is saved. This is dangerous because + * the commit can be lost if the activity needs to later be restored from + * its state, so this should only be used for cases where it is okay for + * the UI state to change unexpectedly on the user. + * @param mustBeEmpty If true, and a tab exists already, do nothing. */ - public void displayMainPage(boolean allowStateLoss) { + public void displayMainPage(boolean allowStateLoss, TabPosition position, boolean mustBeEmpty) { PageTitle title = new PageTitle(MainPageNameData.valueFor(app.getAppOrSystemLanguageCode()), app.getPrimarySite()); HistoryEntry historyEntry = new HistoryEntry(title, HistoryEntry.SOURCE_MAIN_PAGE); - displayNewPage(title, historyEntry, false, allowStateLoss); + displayNewPage(title, historyEntry, position, allowStateLoss, mustBeEmpty); } public void showThemeChooser() { diff --git a/wikipedia/src/main/java/org/wikipedia/page/PageBackStackItem.java b/wikipedia/src/main/java/org/wikipedia/page/PageBackStackItem.java index 59cf0af..bd7565b 100644 --- a/wikipedia/src/main/java/org/wikipedia/page/PageBackStackItem.java +++ b/wikipedia/src/main/java/org/wikipedia/page/PageBackStackItem.java @@ -1,10 +1,8 @@ package org.wikipedia.page; import org.wikipedia.history.HistoryEntry; -import android.os.Parcel; -import android.os.Parcelable; -public class PageBackStackItem implements Parcelable { +public class PageBackStackItem { private final PageTitle title; public PageTitle getTitle() { return title; @@ -27,33 +25,4 @@ this.title = title; this.historyEntry = historyEntry; } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeParcelable(title, flags); - dest.writeParcelable(historyEntry, flags); - dest.writeInt(scrollY); - } - - private PageBackStackItem(Parcel in) { - title = in.readParcelable(PageTitle.class.getClassLoader()); - historyEntry = in.readParcelable(HistoryEntry.class.getClassLoader()); - scrollY = in.readInt(); - } - - public static final Parcelable.Creator<PageBackStackItem> CREATOR - = new Parcelable.Creator<PageBackStackItem>() { - public PageBackStackItem createFromParcel(Parcel in) { - return new PageBackStackItem(in); - } - - public PageBackStackItem[] newArray(int size) { - return new PageBackStackItem[size]; - } - }; -} +} \ No newline at end of file diff --git a/wikipedia/src/main/java/org/wikipedia/page/PageInfoDialog.java b/wikipedia/src/main/java/org/wikipedia/page/PageInfoDialog.java index e8b67bc..ec83a0e 100644 --- a/wikipedia/src/main/java/org/wikipedia/page/PageInfoDialog.java +++ b/wikipedia/src/main/java/org/wikipedia/page/PageInfoDialog.java @@ -98,7 +98,7 @@ @Override public void onOpenInNewTab(PageTitle title, HistoryEntry entry) { dismiss(); - activity.displayNewPage(title, entry, true, false); + activity.displayNewPage(title, entry, PageActivity.TabPosition.NEW_TAB_BACKGROUND, false); } }; diff --git a/wikipedia/src/main/java/org/wikipedia/page/PageLoadStrategy.java b/wikipedia/src/main/java/org/wikipedia/page/PageLoadStrategy.java index 0d91268..a15f975 100644 --- a/wikipedia/src/main/java/org/wikipedia/page/PageLoadStrategy.java +++ b/wikipedia/src/main/java/org/wikipedia/page/PageLoadStrategy.java @@ -8,8 +8,9 @@ import org.wikipedia.views.SwipeRefreshLayoutWithScroll; import android.content.Intent; -import android.os.Bundle; -import java.util.ArrayList; +import android.support.annotation.NonNull; + +import java.util.List; /** * Defines interaction between PageViewFragmentInternal and an implementation that loads a page @@ -21,9 +22,7 @@ CommunicationBridge bridge, SearchBarHideHandler searchBarHideHandler, LeadImagesHandler leadImagesHandler); - void onActivityCreated(Bundle savedInstanceState); - - void onSaveInstanceState(Bundle outState); + void onActivityCreated(@NonNull List<PageBackStackItem> backStack); void backFromEditing(Intent data); @@ -41,7 +40,7 @@ void setEditHandler(EditHandler editHandler); - void setBackStack(ArrayList<PageBackStackItem> backStack); + void setBackStack(@NonNull List<PageBackStackItem> backStack); void updateCurrentBackStackItem(); diff --git a/wikipedia/src/main/java/org/wikipedia/page/PageProperties.java b/wikipedia/src/main/java/org/wikipedia/page/PageProperties.java index 90f32c0..4762af7 100644 --- a/wikipedia/src/main/java/org/wikipedia/page/PageProperties.java +++ b/wikipedia/src/main/java/org/wikipedia/page/PageProperties.java @@ -248,7 +248,6 @@ json.put("image", imageObject); } } catch (JSONException e) { - // Goddamn it Java throw new RuntimeException(e); } diff --git a/wikipedia/src/main/java/org/wikipedia/page/PageViewFragmentInternal.java b/wikipedia/src/main/java/org/wikipedia/page/PageViewFragmentInternal.java index ae8710b..9864877 100755 --- a/wikipedia/src/main/java/org/wikipedia/page/PageViewFragmentInternal.java +++ b/wikipedia/src/main/java/org/wikipedia/page/PageViewFragmentInternal.java @@ -68,6 +68,7 @@ import com.appenguin.onboarding.ToolTip; import java.util.ArrayList; +import java.util.List; import java.util.concurrent.TimeUnit; import javax.net.ssl.SSLException; @@ -75,9 +76,6 @@ // TODO: USE ACRA.getErrorReporter().handleSilentException() if we move to automated crash reporting? public class PageViewFragmentInternal extends Fragment implements BackPressedHandler { - private static final String TAG = "PageViewFragment"; - private static final String TAB_LIST_KEY = "tabList"; - public static final int SUBSTATE_NONE = 0; public static final int SUBSTATE_PAGE_SAVED = 1; public static final int SUBSTATE_SAVED_PAGE_LOADED = 2; @@ -94,7 +92,7 @@ * savedInstanceState of the fragment. */ @NonNull - private ArrayList<Tab> tabList = new ArrayList<>(); + private final List<Tab> tabList = new ArrayList<>(); @NonNull private TabFunnel tabFunnel = new TabFunnel(); @@ -192,6 +190,8 @@ } else { pageLoadStrategy = new JsonPageLoadStrategy(); } + + initTabs(); } public View onCreateView(LayoutInflater inflater, ViewGroup container, @@ -233,15 +233,6 @@ super.onActivityCreated(savedInstanceState); setHasOptionsMenu(true); connectionIssueFunnel = new ConnectionIssueFunnel(app); - - if (savedInstanceState != null) { - //noinspection ConstantConditions - tabList = savedInstanceState.getParcelableArrayList(TAB_LIST_KEY); - } - - if (tabList.isEmpty()) { - tabList.add(new Tab()); - } updateFontSize(); @@ -346,9 +337,8 @@ contextMenuListener); pageLoadStrategy.setup(model, this, refreshView, webView, bridge, searchBarHideHandler, - leadImagesHandler); - pageLoadStrategy.setBackStack(getCurrentTab().getBackStack()); - pageLoadStrategy.onActivityCreated(savedInstanceState); + leadImagesHandler); + pageLoadStrategy.onActivityCreated(getCurrentTab().getBackStack()); } private void initWebViewListeners() { @@ -407,7 +397,8 @@ @Override public void onOpenInNewTab(PageTitle title, HistoryEntry entry) { - ((PageActivity) getActivity()).displayNewPage(title, entry, true, false); + ((PageActivity) getActivity()).displayNewPage(title, entry, + PageActivity.TabPosition.NEW_TAB_BACKGROUND, false); } }; @@ -471,7 +462,7 @@ // just load the main page into a new tab... PageTitle newTitle = new PageTitle(MainPageNameData.valueFor(app.getAppLanguageCode()), app.getPrimarySite()); HistoryEntry newEntry = new HistoryEntry(newTitle, HistoryEntry.SOURCE_INTERNAL_LINK); - openInNewTab(newTitle, newEntry); + openInNewBackgroundTab(newTitle, newEntry); tabFunnel.logCreateNew(tabList.size()); } @@ -496,10 +487,9 @@ }; @Override - public void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - pageLoadStrategy.onSaveInstanceState(outState); - outState.putParcelableArrayList(TAB_LIST_KEY, tabList); + public void onPause() { + super.onPause(); + Prefs.setTabs(tabList); } @Override @@ -516,8 +506,19 @@ tabsProvider.invalidate(); } - public void openInNewTabFromMenu(PageTitle title, HistoryEntry entry) { - openInNewTab(title, entry); + public void openInNewBackgroundTabFromMenu(PageTitle title, HistoryEntry entry) { + openInNewTabFromMenu(title, entry, getBackgroundTabPosition()); + } + + public void openInNewForegroundTabFromMenu(PageTitle title, HistoryEntry entry) { + openInNewTabFromMenu(title, entry, getForegroundTabPosition()); + displayNewPage(title, entry, false, false); + } + + public void openInNewTabFromMenu(PageTitle title, + HistoryEntry entry, + int position) { + openInNewTab(title, entry, position); tabFunnel.logOpenInNew(tabList.size()); } @@ -587,15 +588,27 @@ webView.getSettings().setDefaultFontSize((int) app.getFontSize(getActivity().getWindow())); } - private void openInNewTab(PageTitle title, HistoryEntry entry) { + private void openInNewBackgroundTab(PageTitle title, HistoryEntry entry) { + openInNewTab(title, entry, getBackgroundTabPosition()); + } + + private void openInNewTab(PageTitle title, HistoryEntry entry, int position) { // create a new tab Tab tab = new Tab(); // put this tab behind the current tab - tabList.add(Math.max(0, tabList.size() - 1), tab); + tabList.add(position, tab); // add the requested page to its backstack tab.getBackStack().add(new PageBackStackItem(title, entry)); // and... that should be it. tabsProvider.showAndHideTabs(); + } + + private int getBackgroundTabPosition() { + return Math.max(0, getForegroundTabPosition() - 1); + } + + private int getForegroundTabPosition() { + return tabList.size(); } private void setupMessageHandlers() { @@ -1064,4 +1077,14 @@ } }, TimeUnit.SECONDS.toMillis(1)); } + + private void initTabs() { + if (Prefs.hasTabs()) { + tabList.addAll(Prefs.getTabs()); + } + + if (tabList.isEmpty()) { + tabList.add(new Tab()); + } + } } diff --git a/wikipedia/src/main/java/org/wikipedia/page/bottomcontent/BottomContentHandler.java b/wikipedia/src/main/java/org/wikipedia/page/bottomcontent/BottomContentHandler.java index 054b505..aa7c352 100644 --- a/wikipedia/src/main/java/org/wikipedia/page/bottomcontent/BottomContentHandler.java +++ b/wikipedia/src/main/java/org/wikipedia/page/bottomcontent/BottomContentHandler.java @@ -382,7 +382,7 @@ @Override public void onOpenInNewTab(PageTitle title, HistoryEntry entry) { - activity.displayNewPage(title, entry, true, false); + activity.displayNewPage(title, entry, PageActivity.TabPosition.NEW_TAB_BACKGROUND, false); funnel.logSuggestionClicked(pageTitle, readMoreItems.getPageTitles(), lastPosition); } }; diff --git a/wikipedia/src/main/java/org/wikipedia/page/tabs/Tab.java b/wikipedia/src/main/java/org/wikipedia/page/tabs/Tab.java index 00af63a..818f586 100644 --- a/wikipedia/src/main/java/org/wikipedia/page/tabs/Tab.java +++ b/wikipedia/src/main/java/org/wikipedia/page/tabs/Tab.java @@ -1,45 +1,17 @@ package org.wikipedia.page.tabs; import org.wikipedia.page.PageBackStackItem; -import android.os.Parcel; -import android.os.Parcelable; import android.support.annotation.NonNull; import java.util.ArrayList; +import java.util.List; -public class Tab implements Parcelable { - private final ArrayList<PageBackStackItem> backStack; - public Tab() { - backStack = new ArrayList<>(); - } + +public class Tab { + @NonNull private final List<PageBackStackItem> backStack = new ArrayList<>(); @NonNull - public ArrayList<PageBackStackItem> getBackStack() { + public List<PageBackStackItem> getBackStack() { return backStack; } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeList(backStack); - } - - private Tab(Parcel in) { - backStack = (ArrayList<PageBackStackItem>) in.readArrayList(Tab.class.getClassLoader()); - } - - public static final Parcelable.Creator<Tab> CREATOR - = new Parcelable.Creator<Tab>() { - public Tab createFromParcel(Parcel in) { - return new Tab(in); - } - - public Tab[] newArray(int size) { - return new Tab[size]; - } - }; } diff --git a/wikipedia/src/main/java/org/wikipedia/search/SearchArticlesFragment.java b/wikipedia/src/main/java/org/wikipedia/search/SearchArticlesFragment.java index e6fa4a1..e81cee1 100644 --- a/wikipedia/src/main/java/org/wikipedia/search/SearchArticlesFragment.java +++ b/wikipedia/src/main/java/org/wikipedia/search/SearchArticlesFragment.java @@ -413,7 +413,9 @@ // selected a page to navigate to. launchedFromWidget = false; closeSearch(); - ((PageActivity)getActivity()).displayNewPage(title, historyEntry, inNewTab, false); + ((PageActivity)getActivity()).displayNewPage(title, historyEntry, inNewTab + ? PageActivity.TabPosition.NEW_TAB_BACKGROUND + : PageActivity.TabPosition.CURRENT_TAB, false); } private void addRecentSearch(String title) { diff --git a/wikipedia/src/main/java/org/wikipedia/settings/Prefs.java b/wikipedia/src/main/java/org/wikipedia/settings/Prefs.java index 963d87c..551d0df 100644 --- a/wikipedia/src/main/java/org/wikipedia/settings/Prefs.java +++ b/wikipedia/src/main/java/org/wikipedia/settings/Prefs.java @@ -5,7 +5,13 @@ import org.wikipedia.R; import org.wikipedia.WikipediaApp; +import org.wikipedia.data.GsonMarshaller; +import org.wikipedia.data.TabUnmarshaller; +import org.wikipedia.page.tabs.Tab; import org.wikipedia.theme.Theme; + +import java.util.Collections; +import java.util.List; import static org.wikipedia.settings.PrefsIoUtil.contains; import static org.wikipedia.settings.PrefsIoUtil.getBoolean; @@ -203,6 +209,21 @@ setString(R.string.preference_key_remote_config, json); } + public static void setTabs(@NonNull List<Tab> tabs) { + setString(R.string.preference_key_tabs, GsonMarshaller.marshal(tabs)); + } + + @NonNull + public static List<Tab> getTabs() { + return hasTabs() + ? TabUnmarshaller.unmarshal(getString(R.string.preference_key_tabs, "{}")) + : Collections.<Tab>emptyList(); + } + + public static boolean hasTabs() { + return contains(R.string.preference_key_tabs); + } + public static int getTextSizeMultiplier() { return getInt(R.string.preference_key_text_size_multiplier, 0); } @@ -231,7 +252,6 @@ setBoolean(R.string.preference_key_exp_json_page_load, enabled); } - @NonNull public static long getLastRunTime(@NonNull String task) { return getLong(getLastRunTimeKey(task), 0); } -- To view, visit https://gerrit.wikimedia.org/r/227633 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I5eacc8c07844253974cba6eb479bbcc8c5a2fa4f Gerrit-PatchSet: 1 Gerrit-Project: apps/android/wikipedia Gerrit-Branch: master Gerrit-Owner: Niedzielski <sniedziel...@wikimedia.org> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits