@Override public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) { convertView = LayoutInflater.from(parent.getContext()) .inflate(R.layout.item_toc_entry, parent, false); } Section section = (Section) getItem(position); TextView sectionHeading = (TextView) convertView.findViewById(R.id.page_toc_item_text); View sectionFiller = convertView.findViewById(R.id.page_toc_filler); LinearLayout.LayoutParams indentLayoutParameters = new LinearLayout.LayoutParams(sectionFiller.getLayoutParams()); indentLayoutParameters.width = (section.getLevel() - 1) * (int) (INDENTATION_WIDTH_DP * WikipediaApp.getInstance().getScreenDensity()); sectionFiller.setLayoutParams(indentLayoutParameters); sectionHeading.setText(Html.fromHtml(section.getHeading())); if (section.getLevel() > 1) { sectionHeading.setTextColor( WikipediaApp.getInstance() .getResources() .getColor(getThemedAttributeId(parentActivity, R.attr.toc_subsection_text_color))); } else { sectionHeading.setTextColor( WikipediaApp.getInstance() .getResources() .getColor(getThemedAttributeId(parentActivity, R.attr.toc_section_text_color))); } return convertView; }
/** * Called when an exception is thrown in the background process. Checks whether the exception is * an SSLException and, if so, prompts user to try again if the SSLException is the first. * * <p>Called on the UI Thread. * * <p>Default implementation just throws it as a RuntimeException, so exceptions are never * swallowed. Unless specific exceptions are handled. * * @param caught The exception that was thrown. */ @Override public void onCatch(Throwable caught) { if (Utils.throwableContainsSpecificType(caught, SSLException.class) && WikipediaApp.getInstance().incSslFailCount() < 2) { WikipediaApp.getInstance().setSslFallback(true); if (!isCancelled()) { NetworkUtils.toastNetworkFail(); } cancel(); return; } throw new RuntimeException(caught); }
public abstract class ApiTask<T> extends SaneAsyncTask<T> { private static final boolean VERBOSE = WikipediaApp.getInstance().isDevRelease(); private final Api api; public ApiTask(int concurrency, Api api) { super(concurrency); this.api = api; } @Override public T performTask() throws Throwable { RequestBuilder request = buildRequest(api); if (VERBOSE) { Log.v("ApiTask", buildUrl(api.getApiUrl().toString(), request.getParams())); } ApiResult result = makeRequest(request); return processResult(result); } /** * Called when an exception is thrown in the background process. Checks whether the exception is * an SSLException and, if so, prompts user to try again if the SSLException is the first. * * <p>Called on the UI Thread. * * <p>Default implementation just throws it as a RuntimeException, so exceptions are never * swallowed. Unless specific exceptions are handled. * * @param caught The exception that was thrown. */ @Override public void onCatch(Throwable caught) { if (Utils.throwableContainsSpecificType(caught, SSLException.class) && WikipediaApp.getInstance().incSslFailCount() < 2) { WikipediaApp.getInstance().setSslFallback(true); if (!isCancelled()) { NetworkUtils.toastNetworkFail(); } cancel(); return; } throw new RuntimeException(caught); } protected ApiResult makeRequest(RequestBuilder builder) throws ApiException { return builder.get(); } public abstract RequestBuilder buildRequest(Api api); public abstract T processResult(ApiResult result) throws Throwable; private String buildUrl(String url, Map<String, String> params) { Uri.Builder builder = new Uri.Builder().encodedPath(url); for (Map.Entry<String, String> param : params.entrySet()) { builder.appendQueryParameter(param.getKey(), param.getValue()); } return builder.build().toString(); } }
private void refreshOneSavedPage(@NonNull final PageTitle title) { getApiService(title) .pageCombo( title.getPrefixedText(), !WikipediaApp.getInstance().isImageDownloadEnabled(), new SaveOtherPageCallback(title) { @Override protected void onComplete() { if (!progressDialog.isShowing()) { isRefreshCancelled = true; // no longer attached to activity! return; } savedPagesCompleted++; progressDialog.setProgress(savedPagesCompleted); L.d("Count is " + savedPagesCompleted + " of " + savedPages.size()); if (savedPagesCompleted == savedPages.size()) { progressDialog.dismiss(); } } @Override protected void onError() { isRefreshCancelled = true; if (!progressDialog.isShowing()) { // no longer attached to activity! return; } progressDialog.dismiss(); getErrorDialog().show(); } }); }
public void setupToC(final Page page, Site site, boolean firstPage) { tocProgress.setVisibility(View.GONE); tocList.setVisibility(View.VISIBLE); headerView.setText(Html.fromHtml(page.getDisplayTitle())); headerView.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { scrollToSection(page.getSections().get(0)); wasClicked = true; funnel.logClick(0, page.getTitle().getDisplayText()); hide(); } }); tocList.setAdapter(new ToCAdapter(page), site.getLanguageCode()); tocList.setOnItemClickListener( new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Section section = (Section) parent.getAdapter().getItem(position); scrollToSection(section); wasClicked = true; funnel.logClick(position, section.getHeading()); hide(); } }); funnel = new ToCInteractionFunnel( WikipediaApp.getInstance(), site, page.getPageProperties().getPageId(), tocList.getAdapter().getCount()); if (!page.isMainPage() && !firstPage) { if (WikipediaApp.getInstance().getOnboardingStateMachine().isTocTutorialEnabled()) { showTocOnboarding(); } } }
@RunWith(AndroidJUnit4.class) public class LoginTaskTest { private static final Site TEST_WIKI_SITE = new Site("test.wikipedia.org"); private static final String SUCCESS = "Success"; private static final String USERNAME = getString(R.string.test_username); private static final String PASSWORD = getString(R.string.test_password); private final WikipediaApp app = WikipediaApp.getInstance(); private final TestLatch completionLatch = new TestLatch(); @Test public void testLogin() throws Throwable { runOnMainSync( new Runnable() { @Override public void run() { loginTestTask.execute(); } }); completionLatch.await(); } private LoginTask loginTestTask = new LoginTask(app, TEST_WIKI_SITE, USERNAME, PASSWORD) { @Override public void onFinish(LoginResult result) { super.onFinish(result); assertThat(result.getCode(), equalTo(SUCCESS)); app.getEditTokenStorage().get(TEST_WIKI_SITE, callback); } }; private EditTokenStorage.TokenRetrievedCallback callback = new EditTokenStorage.TokenRetrievedCallback() { @Override public void onTokenRetrieved(String token) { assertThat(token.equals("+\\"), is(false)); completionLatch.countDown(); } @Override public void onTokenFailed(Throwable caught) { throw new RuntimeException(caught); } }; private void runOnMainSync(Runnable r) { getInstrumentation().runOnMainSync(r); } private static String getString(@StringRes int id) { return getInstrumentation().getContext().getString(id); } }
public ToCHandler( final AppCompatActivity activity, final WikiDrawerLayout slidingPane, final CommunicationBridge bridge) { this.parentActivity = activity; this.bridge = bridge; this.slidingPane = slidingPane; this.tocList = (ConfigurableListView) slidingPane.findViewById(R.id.page_toc_list); ((FrameLayout.LayoutParams) tocList.getLayoutParams()) .setMargins(0, getContentTopOffsetPx(activity), 0, 0); this.tocProgress = (ProgressBar) slidingPane.findViewById(R.id.page_toc_in_progress); bridge.addListener( "currentSectionResponse", new CommunicationBridge.JSEventListener() { @Override public void onMessage(String messageType, JSONObject messagePayload) { int sectionID = messagePayload.optInt("sectionID"); Log.d("Wikipedia", "current section is " + sectionID); if (tocList.getAdapter() == null) { return; } int itemToSelect = 0; // Find the list item that corresponds to the returned sectionID. // Start with index 1 of the list adapter, since index 0 is the header view, // and won't have a Section object associated with it. // And end with the second-to-last section, since the last section is the // artificial Read More section, and unknown to the WebView. // The lead section (id 0) will automatically fall through the loop. for (int i = 1; i < tocList.getAdapter().getCount() - 1; i++) { if (((Section) tocList.getAdapter().getItem(i)).getId() <= sectionID) { itemToSelect = i; } else { break; } } tocList.setItemChecked(itemToSelect, true); tocList.smoothScrollToPosition(itemToSelect); } }); headerView = (TextView) LayoutInflater.from(tocList.getContext()) .inflate(R.layout.header_toc_list, null, false); tocList.addHeaderView(headerView); // create a dummy funnel, in case the drawer is pulled out before a page is loaded. funnel = new ToCInteractionFunnel( WikipediaApp.getInstance(), WikipediaApp.getInstance().getSite(), 0, 0); slidingPane.setDrawerListener( new DrawerLayout.SimpleDrawerListener() { private boolean sectionRequested = false; @Override public void onDrawerOpened(View drawerView) { super.onDrawerOpened(drawerView); parentActivity.supportInvalidateOptionsMenu(); funnel.logOpen(); wasClicked = false; } @Override public void onDrawerClosed(View drawerView) { super.onDrawerClosed(drawerView); parentActivity.supportInvalidateOptionsMenu(); if (!wasClicked) { funnel.logClose(); } sectionRequested = false; } @Override public void onDrawerSlide(View drawerView, float slideOffset) { super.onDrawerSlide(drawerView, slideOffset); // make sure the ActionBar is showing ((PageActivity) parentActivity).showToolbar(); ((PageActivity) parentActivity) .getSearchBarHideHandler() .setForceNoFade(slideOffset != 0); // request the current section to highlight, if we haven't yet if (!sectionRequested) { bridge.sendMessage("requestCurrentSection", new JSONObject()); sectionRequested = true; } } }); }
private void showTocOnboarding() { View tocButton = parentActivity.findViewById(R.id.floating_toc_button); ToolTipUtil.showToolTip( parentActivity, tocButton, R.layout.inflate_tool_tip_toc_button, ToolTip.Position.CENTER); WikipediaApp.getInstance().getOnboardingStateMachine().setTocTutorial(); }
// TODO: use getResources().getDimensionPixelSize()? Define leadImageWidth with px, not dp? public static int calculateLeadImageWidth() { Resources res = WikipediaApp.getInstance().getResources(); return (int) (res.getDimension(R.dimen.leadImageWidth) / res.getDisplayMetrics().density); }
public RbPageService(final Site site) { responseHeaderHandler = WikipediaApp.getInstance().getWikipediaZeroHandler(); webService = RbPageEndpointsCache.INSTANCE.getRbPageEndpoints(site); }