diff --git a/app/build.gradle b/app/build.gradle index 197e6b4d9..f400c035a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,4 +1,5 @@ apply plugin: 'com.android.application' +apply plugin: 'me.tatarka.retrolambda' apply plugin: 'jacoco-android' apply from: 'quality.gradle' apply plugin: 'com.getkeepsafe.dexcount' @@ -75,6 +76,11 @@ android { abortOnError false } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + //FIXME: Temporary fix for https://github.com/commons-app/apps-android-commons/issues/709 configurations.all { resolutionStrategy.force 'com.android.support:support-annotations:25.2.0' diff --git a/app/src/main/java/fr/free/nrw/commons/CommonsApplication.java b/app/src/main/java/fr/free/nrw/commons/CommonsApplication.java index b78bfdc6f..2af125032 100644 --- a/app/src/main/java/fr/free/nrw/commons/CommonsApplication.java +++ b/app/src/main/java/fr/free/nrw/commons/CommonsApplication.java @@ -197,8 +197,8 @@ public class CommonsApplication extends Application { AccountManager accountManager = AccountManager.get(this); Account[] allAccounts = accountManager.getAccountsByType(AccountUtil.accountType()); - for (int index = 0; index < allAccounts.length; index++) { - accountManager.removeAccount(allAccounts[index], null, null); + for (Account allAccount : allAccounts) { + accountManager.removeAccount(allAccount, null, null); } //TODO: fix preference manager diff --git a/app/src/main/java/fr/free/nrw/commons/WelcomeActivity.java b/app/src/main/java/fr/free/nrw/commons/WelcomeActivity.java index e35c7e6d0..f6c5999e9 100644 --- a/app/src/main/java/fr/free/nrw/commons/WelcomeActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/WelcomeActivity.java @@ -27,12 +27,7 @@ public class WelcomeActivity extends BaseActivity { pager.setAdapter(adapter); indicator.setViewPager(pager); - adapter.setCallback(new WelcomePagerAdapter.Callback() { - @Override - public void onYesClicked() { - finish(); - } - }); + adapter.setCallback(this::finish); } @Override diff --git a/app/src/main/java/fr/free/nrw/commons/auth/LoginActivity.java b/app/src/main/java/fr/free/nrw/commons/auth/LoginActivity.java index 9d9f021ea..aca419b9c 100644 --- a/app/src/main/java/fr/free/nrw/commons/auth/LoginActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/auth/LoginActivity.java @@ -26,6 +26,9 @@ import fr.free.nrw.commons.PageTitle; import fr.free.nrw.commons.contributions.ContributionsActivity; import timber.log.Timber; +import static android.view.KeyEvent.KEYCODE_ENTER; +import static android.view.inputmethod.EditorInfo.IME_ACTION_DONE; + public class LoginActivity extends AccountAuthenticatorActivity { @@ -63,18 +66,8 @@ public class LoginActivity extends AccountAuthenticatorActivity { twoFactorEdit.addTextChangedListener(textWatcher); passwordEdit.setOnEditorActionListener(newLoginInputActionListener()); - loginButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - performLogin(); - } - }); - signupButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - signUp(v); - } - }); + loginButton.setOnClickListener(this::performLogin); + signupButton.setOnClickListener(this::signUp); } private class LoginTextWatcher implements TextWatcher { @@ -98,20 +91,17 @@ public class LoginActivity extends AccountAuthenticatorActivity { } private TextView.OnEditorActionListener newLoginInputActionListener() { - return new TextView.OnEditorActionListener() { - @Override - public boolean onEditorAction(TextView textView, int actionId, KeyEvent keyEvent) { - if (loginButton.isEnabled()) { - if (actionId == EditorInfo.IME_ACTION_DONE) { - performLogin(); - return true; - } else if ((keyEvent != null) && keyEvent.getKeyCode() == KeyEvent.KEYCODE_ENTER) { - performLogin(); - return true; - } + return (textView, actionId, keyEvent) -> { + if (loginButton.isEnabled()) { + if (actionId == IME_ACTION_DONE) { + performLogin(textView); + return true; + } else if ((keyEvent != null) && keyEvent.getKeyCode() == KEYCODE_ENTER) { + performLogin(textView); + return true; } - return false; } + return false; }; } @@ -142,7 +132,7 @@ public class LoginActivity extends AccountAuthenticatorActivity { super.onDestroy(); } - private void performLogin() { + private void performLogin(View view) { Timber.d("Login to start!"); LoginTask task = getLoginTask(); task.execute(); diff --git a/app/src/main/java/fr/free/nrw/commons/category/CategorizationFragment.java b/app/src/main/java/fr/free/nrw/commons/category/CategorizationFragment.java index 3f467183d..d2d9f317f 100644 --- a/app/src/main/java/fr/free/nrw/commons/category/CategorizationFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/category/CategorizationFragment.java @@ -409,12 +409,9 @@ public class CategorizationFragment extends Fragment { categoriesNotFoundView = (TextView) rootView.findViewById(R.id.categoriesNotFound); categoriesSkip = (TextView) rootView.findViewById(R.id.categoriesExplanation); - categoriesSkip.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - getActivity().onBackPressed(); - getActivity().finish(); - } + categoriesSkip.setOnClickListener(view -> { + getActivity().onBackPressed(); + getActivity().finish(); }); ArrayList items; @@ -429,16 +426,13 @@ public class CategorizationFragment extends Fragment { categoriesAdapter = new CategoriesAdapter(getActivity(), items); categoriesList.setAdapter(categoriesAdapter); - categoriesList.setOnItemClickListener(new AdapterView.OnItemClickListener() { - @Override - public void onItemClick(AdapterView adapterView, View view, int index, long id) { - CheckedTextView checkedView = (CheckedTextView) view; - CategoryItem item = (CategoryItem) adapterView.getAdapter().getItem(index); - item.selected = !item.selected; - checkedView.setChecked(item.selected); - if (item.selected) { - updateCategoryCount(item.name); - } + categoriesList.setOnItemClickListener((adapterView, view, index, id) -> { + CheckedTextView checkedView = (CheckedTextView) view; + CategoryItem item = (CategoryItem) adapterView.getAdapter().getItem(index); + item.selected = !item.selected; + checkedView.setChecked(item.selected); + if (item.selected) { + updateCategoryCount(item.name); } }); @@ -463,15 +457,12 @@ public class CategorizationFragment extends Fragment { if (rootView != null) { rootView.setFocusableInTouchMode(true); rootView.requestFocus(); - rootView.setOnKeyListener(new View.OnKeyListener() { - @Override - public boolean onKey(View v, int keyCode, KeyEvent event) { - if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) { - backButtonDialog(); - return true; - } - return false; + rootView.setOnKeyListener((v, keyCode, event) -> { + if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) { + backButtonDialog(); + return true; } + return false; }); } } @@ -487,18 +478,10 @@ public class CategorizationFragment extends Fragment { builder.setMessage("Are you sure you want to go back? The image will not have any categories saved.") .setTitle("Warning"); - builder.setPositiveButton("No", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - //No need to do anything, user remains on categorization screen - } - }); - builder.setNegativeButton("Yes", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - getActivity().finish(); - } + builder.setPositiveButton("No", (dialog, id) -> { + //No need to do anything, user remains on categorization screen }); + builder.setNegativeButton("Yes", (dialog, id) -> getActivity().finish()); AlertDialog dialog = builder.create(); dialog.show(); @@ -537,20 +520,12 @@ public class CategorizationFragment extends Fragment { builder.setMessage("Images without categories are rarely usable. Are you sure you want to submit without selecting categories?") .setTitle("No Categories Selected"); - builder.setPositiveButton("No, go back", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - //Exit menuItem so user can select their categories - return; - } + builder.setPositiveButton("No, go back", (dialog, id) -> { + //Exit menuItem so user can select their categories }); - builder.setNegativeButton("Yes, submit", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - //Proceed to submission - onCategoriesSaveHandler.onCategoriesSave(selectedCategories); - return; - } + builder.setNegativeButton("Yes, submit", (dialog, id) -> { + //Proceed to submission + onCategoriesSaveHandler.onCategoriesSave(selectedCategories); }); AlertDialog dialog = builder.create(); diff --git a/app/src/main/java/fr/free/nrw/commons/concurrency/BackgroundPoolExceptionHandler.java b/app/src/main/java/fr/free/nrw/commons/concurrency/BackgroundPoolExceptionHandler.java index 2c730a0d1..489a45c4e 100644 --- a/app/src/main/java/fr/free/nrw/commons/concurrency/BackgroundPoolExceptionHandler.java +++ b/app/src/main/java/fr/free/nrw/commons/concurrency/BackgroundPoolExceptionHandler.java @@ -9,11 +9,8 @@ public class BackgroundPoolExceptionHandler implements ExceptionHandler { public void onException(@NonNull final Throwable t) { //Crash for debug build if (BuildConfig.DEBUG) { - Thread thread = new Thread(new Runnable() { - @Override - public void run() { - throw new RuntimeException(t); - } + Thread thread = new Thread(() -> { + throw new RuntimeException(t); }); thread.start(); } diff --git a/app/src/main/java/fr/free/nrw/commons/concurrency/ThreadFactoryMaker.java b/app/src/main/java/fr/free/nrw/commons/concurrency/ThreadFactoryMaker.java index 221ebef41..d535fe5bd 100644 --- a/app/src/main/java/fr/free/nrw/commons/concurrency/ThreadFactoryMaker.java +++ b/app/src/main/java/fr/free/nrw/commons/concurrency/ThreadFactoryMaker.java @@ -11,17 +11,13 @@ class ThreadFactoryMaker { private int count = 0; @Override - public Thread newThread(final Runnable runnable) { + public Thread newThread(@NonNull final Runnable runnable) { count++; - Runnable wrapperRunnable = new Runnable() { - @Override - public void run() { - Process.setThreadPriority(priority); - runnable.run(); - } + Runnable wrapperRunnable = () -> { + Process.setThreadPriority(priority); + runnable.run(); }; - Thread t = new Thread(wrapperRunnable, String.format("%s-%s", name, count)); - return t; + return new Thread(wrapperRunnable, String.format("%s-%s", name, count)); } }; } diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListFragment.java b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListFragment.java index 8025b94bf..c009243b9 100644 --- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListFragment.java @@ -29,6 +29,7 @@ import fr.free.nrw.commons.R; import fr.free.nrw.commons.nearby.NearbyActivity; import timber.log.Timber; +import static android.Manifest.permission.READ_EXTERNAL_STORAGE; import static android.app.Activity.RESULT_OK; public class ContributionsListFragment extends Fragment { @@ -110,11 +111,11 @@ public class ContributionsListFragment extends Fragment { // Here, thisActivity is the current activity if (ContextCompat.checkSelfPermission(getActivity(), - Manifest.permission.READ_EXTERNAL_STORAGE) + READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { // Should we show an explanation? - if (shouldShowRequestPermissionRationale(Manifest.permission.READ_EXTERNAL_STORAGE)) { + if (shouldShowRequestPermissionRationale(READ_EXTERNAL_STORAGE)) { // Show an explanation to the user *asynchronously* -- don't block // this thread waiting for the user's response! After the user @@ -122,15 +123,9 @@ public class ContributionsListFragment extends Fragment { new AlertDialog.Builder(getActivity()) .setMessage(getString(R.string.storage_permission_rationale)) - .setPositiveButton("OK", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - - requestPermissions( - new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, - 1); - dialog.dismiss(); - } + .setPositiveButton("OK", (dialog, which) -> { + requestPermissions(new String[]{READ_EXTERNAL_STORAGE}, 1); + dialog.dismiss(); }) .setNegativeButton("Cancel", null) .create() @@ -140,7 +135,7 @@ public class ContributionsListFragment extends Fragment { // No explanation needed, we can request the permission. - requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, + requestPermissions(new String[]{READ_EXTERNAL_STORAGE}, 1); // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/UploadCountClient.java b/app/src/main/java/fr/free/nrw/commons/contributions/UploadCountClient.java index 9667f9057..4a04e3888 100644 --- a/app/src/main/java/fr/free/nrw/commons/contributions/UploadCountClient.java +++ b/app/src/main/java/fr/free/nrw/commons/contributions/UploadCountClient.java @@ -14,10 +14,10 @@ import fr.free.nrw.commons.concurrency.BackgroundPoolExceptionHandler; import fr.free.nrw.commons.concurrency.ThreadPoolExecutorService; import timber.log.Timber; -public class UploadCountClient { +class UploadCountClient { private ThreadPoolExecutorService threadPoolExecutor; - public UploadCountClient() { + UploadCountClient() { threadPoolExecutor = new ThreadPoolExecutorService.Builder("bg-pool") .setPoolSize(Runtime.getRuntime().availableProcessors()) .setExceptionHandler(new BackgroundPoolExceptionHandler()) @@ -27,29 +27,26 @@ public class UploadCountClient { private static final String UPLOAD_COUNT_URL_TEMPLATE = "https://tools.wmflabs.org/urbanecmbot/uploadsbyuser/uploadsbyuser.py?user=%s"; - public ListenableFuture getUploadCount(final String userName) { + ListenableFuture getUploadCount(final String userName) { final SettableFuture future = SettableFuture.create(); - threadPoolExecutor.schedule(new Runnable() { - @Override - public void run() { - URL url; + threadPoolExecutor.schedule(() -> { + URL url; + try { + url = new URL(String.format(Locale.ENGLISH, UPLOAD_COUNT_URL_TEMPLATE, + new PageTitle(userName).getText())); + HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); try { - url = new URL(String.format(Locale.ENGLISH, UPLOAD_COUNT_URL_TEMPLATE, - new PageTitle(userName).getText())); - HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); - try { - BufferedReader bufferedReader = new BufferedReader(new - InputStreamReader(urlConnection.getInputStream())); - String uploadCount = bufferedReader.readLine(); - bufferedReader.close(); - future.set(Integer.parseInt(uploadCount)); - } finally { - urlConnection.disconnect(); - } - } catch (Exception e) { - Timber.e("Error getting upload count Error", e); - future.setException(e); + BufferedReader bufferedReader = new BufferedReader(new + InputStreamReader(urlConnection.getInputStream())); + String uploadCount = bufferedReader.readLine(); + bufferedReader.close(); + future.set(Integer.parseInt(uploadCount)); + } finally { + urlConnection.disconnect(); } + } catch (Exception e) { + Timber.e("Error getting upload count Error", e); + future.setException(e); } }); return future; diff --git a/app/src/main/java/fr/free/nrw/commons/media/MediaDetailFragment.java b/app/src/main/java/fr/free/nrw/commons/media/MediaDetailFragment.java index cb879395c..d739e9040 100644 --- a/app/src/main/java/fr/free/nrw/commons/media/MediaDetailFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/media/MediaDetailFragment.java @@ -119,12 +119,7 @@ public class MediaDetailFragment extends Fragment { licenseList = new LicenseList(getActivity()); // Progressively darken the image in the background when we scroll detail pane up - scrollListener = new ViewTreeObserver.OnScrollChangedListener() { - @Override - public void onScrollChanged() { - updateTheDarkness(); - } - }; + scrollListener = this::updateTheDarkness; view.getViewTreeObserver().addOnScrollChangedListener(scrollListener); // Layout layoutListener to size the spacer item relative to the available space. @@ -280,15 +275,12 @@ public class MediaDetailFragment extends Fragment { textView.setText(catName); if (categoriesLoaded && categoriesPresent) { - textView.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - String selectedCategoryTitle = "Category:" + catName; - Intent viewIntent = new Intent(); - viewIntent.setAction(Intent.ACTION_VIEW); - viewIntent.setData(new PageTitle(selectedCategoryTitle).getCanonicalUri()); - startActivity(viewIntent); - } + textView.setOnClickListener(view -> { + String selectedCategoryTitle = "Category:" + catName; + Intent viewIntent = new Intent(); + viewIntent.setAction(Intent.ACTION_VIEW); + viewIntent.setData(new PageTitle(selectedCategoryTitle).getCanonicalUri()); + startActivity(viewIntent); }); } return item; diff --git a/app/src/main/java/fr/free/nrw/commons/media/MediaDetailPagerFragment.java b/app/src/main/java/fr/free/nrw/commons/media/MediaDetailPagerFragment.java index d0b2236ca..271ac5c92 100644 --- a/app/src/main/java/fr/free/nrw/commons/media/MediaDetailPagerFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/media/MediaDetailPagerFragment.java @@ -72,12 +72,7 @@ public class MediaDetailPagerFragment extends Fragment implements ViewPager.OnPa public Fragment getItem(int i) { if (i == 0) { // See bug https://code.google.com/p/android/issues/detail?id=27526 - pager.postDelayed(new Runnable() { - @Override - public void run() { - getActivity().supportInvalidateOptionsMenu(); - } - }, 5); + pager.postDelayed(() -> getActivity().supportInvalidateOptionsMenu(), 5); } return MediaDetailFragment.forMedia(i, editable); } @@ -100,14 +95,11 @@ public class MediaDetailPagerFragment extends Fragment implements ViewPager.OnPa final int pageNumber = savedInstanceState.getInt("current-page"); // Adapter doesn't seem to be loading immediately. // Dear God, please forgive us for our sins - view.postDelayed(new Runnable() { - @Override - public void run() { - pager.setAdapter(adapter); - pager.setCurrentItem(pageNumber, false); - getActivity().supportInvalidateOptionsMenu(); - adapter.notifyDataSetChanged(); - } + view.postDelayed(() -> { + pager.setAdapter(adapter); + pager.setCurrentItem(pageNumber, false); + getActivity().supportInvalidateOptionsMenu(); + adapter.notifyDataSetChanged(); }, 100); } else { pager.setAdapter(adapter); @@ -196,13 +188,8 @@ public class MediaDetailPagerFragment extends Fragment implements ViewPager.OnPa if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !(ContextCompat.checkSelfPermission(getContext(), Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED)) { Snackbar.make(getView(), R.string.storage_permission_rationale, Snackbar.LENGTH_INDEFINITE) - .setAction(R.string.ok, new View.OnClickListener() { - @Override - public void onClick(View view) { - ActivityCompat.requestPermissions(getActivity(), - new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 1); - } - }).show(); + .setAction(R.string.ok, view -> ActivityCompat.requestPermissions(getActivity(), + new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 1)).show(); } else { final DownloadManager manager = (DownloadManager)getActivity().getSystemService(Context.DOWNLOAD_SERVICE); manager.enqueue(req); diff --git a/app/src/main/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApi.java b/app/src/main/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApi.java index bb2356dd6..9dd0f9939 100644 --- a/app/src/main/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApi.java +++ b/app/src/main/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApi.java @@ -351,12 +351,7 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi { @Override @NonNull public UploadResult uploadFile(String filename, InputStream file, long dataLength, String pageContents, String editSummary, final ProgressListener progressListener) throws IOException { - ApiResult result = api.upload(filename, file, dataLength, pageContents, editSummary, new in.yuvi.http.fluent.ProgressListener() { - @Override - public void onProgress(long transferred, long total) { - progressListener.onProgress(transferred, total); - } - }); + ApiResult result = api.upload(filename, file, dataLength, pageContents, editSummary, progressListener::onProgress); Log.e("WTF", "Result: "+result.toString()); diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyActivity.java b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyActivity.java index 3d26b22f1..d58eb3566 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyActivity.java @@ -2,7 +2,6 @@ package fr.free.nrw.commons.nearby; import android.Manifest; import android.content.Context; -import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageManager; import android.location.LocationManager; @@ -41,7 +40,8 @@ import timber.log.Timber; public class NearbyActivity extends NavigationBaseActivity { - @BindView(R.id.progressBar) ProgressBar progressBar; + @BindView(R.id.progressBar) + ProgressBar progressBar; private boolean isMapViewActive = false; private static final int LOCATION_REQUEST = 1; @@ -115,15 +115,11 @@ public class NearbyActivity extends NavigationBaseActivity { new AlertDialog.Builder(this) .setMessage(getString(R.string.location_permission_rationale)) - .setPositiveButton("OK", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - - ActivityCompat.requestPermissions(NearbyActivity.this, - new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, - LOCATION_REQUEST); - dialog.dismiss(); - } + .setPositiveButton("OK", (dialog, which) -> { + ActivityCompat.requestPermissions(NearbyActivity.this, + new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, + LOCATION_REQUEST); + dialog.dismiss(); }) .setNegativeButton("Cancel", null) .create() @@ -175,26 +171,19 @@ public class NearbyActivity extends NavigationBaseActivity { LocationManager manager = (LocationManager) getSystemService(LOCATION_SERVICE); if (!manager.isProviderEnabled(LocationManager.GPS_PROVIDER)) { Timber.d("GPS is not enabled"); - AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this); - alertDialogBuilder.setMessage(R.string.gps_disabled) + new AlertDialog.Builder(this) + .setMessage(R.string.gps_disabled) .setCancelable(false) .setPositiveButton(R.string.enable_gps, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - Intent callGPSSettingIntent = new Intent( - android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS); - Timber.d("Loaded settings page"); - startActivityForResult(callGPSSettingIntent, 1); - } - }); - alertDialogBuilder.setNegativeButton(R.string.menu_cancel_upload, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - dialog.cancel(); - } - }); - AlertDialog alert = alertDialogBuilder.create(); - alert.show(); + (dialog, id) -> { + Intent callGPSSettingIntent = new Intent( + android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS); + Timber.d("Loaded settings page"); + startActivityForResult(callGPSSettingIntent, 1); + }) + .setNegativeButton(R.string.menu_cancel_upload, (dialog, id) -> dialog.cancel()) + .create() + .show(); } else { Timber.d("GPS is enabled"); } @@ -257,7 +246,7 @@ public class NearbyActivity extends NavigationBaseActivity { private final Context mContext; - private NearbyAsyncTask (Context context) { + private NearbyAsyncTask(Context context) { mContext = context; } diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyAdapterFactory.java b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyAdapterFactory.java index 5fffcab2a..d5eb05851 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyAdapterFactory.java +++ b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyAdapterFactory.java @@ -1,5 +1,7 @@ package fr.free.nrw.commons.nearby; +import android.support.annotation.NonNull; + import com.pedrogomez.renderers.ListAdapteeCollection; import com.pedrogomez.renderers.RVRendererAdapter; import com.pedrogomez.renderers.RendererBuilder; @@ -10,7 +12,7 @@ import java.util.List; class NearbyAdapterFactory { private PlaceRenderer.PlaceClickedListener listener; - NearbyAdapterFactory(PlaceRenderer.PlaceClickedListener listener) { + NearbyAdapterFactory(@NonNull PlaceRenderer.PlaceClickedListener listener) { this.listener = listener; } diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyController.java b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyController.java index c5103117d..b08b99d72 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyController.java +++ b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyController.java @@ -52,13 +52,10 @@ public class NearbyController { distances.put(place, computeDistanceBetween(place.location, curLatLng)); } Collections.sort(places, - new Comparator() { - @Override - public int compare(Place lhs, Place rhs) { - double lhsDistance = distances.get(lhs); - double rhsDistance = distances.get(rhs); - return (int) (lhsDistance - rhsDistance); - } + (lhs, rhs) -> { + double lhsDistance = distances.get(lhs); + double rhsDistance = distances.get(rhs); + return (int) (lhsDistance - rhsDistance); } ); } diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyInfoDialog.java b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyInfoDialog.java index bb2d2fed9..1203d5a0d 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyInfoDialog.java +++ b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyInfoDialog.java @@ -63,15 +63,10 @@ public class NearbyInfoDialog extends OverlayDialog { overflowButton.setVisibility(showMenu() ? View.VISIBLE : View.GONE); - overflowButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - popupMenuListener(); - } - }); + overflowButton.setOnClickListener(this::popupMenuListener); } - private void popupMenuListener() { + private void popupMenuListener(View v) { PopupMenu popupMenu = new PopupMenu(getActivity(), overflowButton); popupMenu.inflate(R.menu.nearby_info_dialog_options); diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyListFragment.java b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyListFragment.java index ea7ce3478..00b8a2840 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyListFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyListFragment.java @@ -48,12 +48,7 @@ public class NearbyListFragment extends Fragment { View view = inflater.inflate(R.layout.fragment_nearby, container, false); recyclerView = (RecyclerView) view.findViewById(R.id.listView); recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); - adapterFactory = new NearbyAdapterFactory(new PlaceRenderer.PlaceClickedListener() { - @Override - public void placeClicked(Place place) { - NearbyInfoDialog.showYourself(getActivity(), place); - } - }); + adapterFactory = new NearbyAdapterFactory(place -> NearbyInfoDialog.showYourself(getActivity(), place)); return view; } diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyMapFragment.java b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyMapFragment.java index 54c1a565e..bc5830809 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyMapFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyMapFragment.java @@ -88,25 +88,19 @@ public class NearbyMapFragment extends android.support.v4.app.Fragment { // create map mapView = new MapView(getActivity(), options); mapView.onCreate(savedInstanceState); - mapView.getMapAsync(new OnMapReadyCallback() { - @Override - public void onMapReady(MapboxMap mapboxMap) { - mapboxMap.addMarkers(baseMarkerOptions); + mapView.getMapAsync(mapboxMap -> { + mapboxMap.addMarkers(baseMarkerOptions); - mapboxMap.setOnMarkerClickListener(new MapboxMap.OnMarkerClickListener() { - @Override - public boolean onMarkerClick(@NonNull Marker marker) { - if (marker instanceof NearbyMarker) { - NearbyMarker nearbyMarker = (NearbyMarker) marker; - Place place = nearbyMarker.getNearbyBaseMarker().getPlace(); - NearbyInfoDialog.showYourself(getActivity(), place); - } - return false; - } - }); + mapboxMap.setOnMarkerClickListener(marker -> { + if (marker instanceof NearbyMarker) { + NearbyMarker nearbyMarker = (NearbyMarker) marker; + Place place = nearbyMarker.getNearbyBaseMarker().getPlace(); + NearbyInfoDialog.showYourself(getActivity(), place); + } + return false; + }); - addCurrentLocationMarker(mapboxMap); - } + addCurrentLocationMarker(mapboxMap); }); if (PreferenceManager.getDefaultSharedPreferences(getActivity()).getBoolean("theme",true)) { mapView.setStyleUrl(getResources().getString(R.string.map_theme_dark)); diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/PlaceRenderer.java b/app/src/main/java/fr/free/nrw/commons/nearby/PlaceRenderer.java index 12e24f1ae..f4c8a5d61 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/PlaceRenderer.java +++ b/app/src/main/java/fr/free/nrw/commons/nearby/PlaceRenderer.java @@ -1,5 +1,6 @@ package fr.free.nrw.commons.nearby; +import android.support.annotation.NonNull; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -19,7 +20,7 @@ class PlaceRenderer extends Renderer { @BindView(R.id.icon) ImageView icon; private final PlaceClickedListener listener; - PlaceRenderer(PlaceClickedListener listener) { + PlaceRenderer(@NonNull PlaceClickedListener listener) { this.listener = listener; } @@ -35,14 +36,7 @@ class PlaceRenderer extends Renderer { @Override protected void hookListeners(View view) { - view.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - if (listener != null) { - listener.placeClicked(getContent()); - } - } - }); + view.setOnClickListener(v -> listener.placeClicked(getContent())); } @Override diff --git a/app/src/main/java/fr/free/nrw/commons/settings/SettingsFragment.java b/app/src/main/java/fr/free/nrw/commons/settings/SettingsFragment.java index bdac4a0f5..cfeda91d1 100644 --- a/app/src/main/java/fr/free/nrw/commons/settings/SettingsFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/settings/SettingsFragment.java @@ -28,21 +28,15 @@ public class SettingsFragment extends PreferenceFragment { licensePreference.setSummary(getString(Utils.licenseNameFor(licensePreference.getValue()))); // Keep summary updated when changing value - licensePreference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - preference.setSummary(getString(Utils.licenseNameFor((String) newValue))); - return true; - } + licensePreference.setOnPreferenceChangeListener((preference, newValue) -> { + preference.setSummary(getString(Utils.licenseNameFor((String) newValue))); + return true; }); CheckBoxPreference themePreference = (CheckBoxPreference) findPreference("theme"); - themePreference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - getActivity().recreate(); - return true; - } + themePreference.setOnPreferenceChangeListener((preference, newValue) -> { + getActivity().recreate(); + return true; }); final EditTextPreference uploadLimit = (EditTextPreference) findPreference("uploads"); @@ -51,36 +45,27 @@ public class SettingsFragment extends PreferenceFragment { int uploads = sharedPref.getInt(Prefs.UPLOADS_SHOWING, 100); uploadLimit.setText(uploads + ""); uploadLimit.setSummary(uploads + ""); - uploadLimit.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { - - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - int value = Integer.parseInt(newValue.toString()); - final SharedPreferences.Editor editor = sharedPref.edit(); - if (value > 500) { - new AlertDialog.Builder(getActivity()) - .setTitle(R.string.maximum_limit) - .setMessage(R.string.maximum_limit_alert) - .setPositiveButton(android.R.string.yes, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - } - }) - .setIcon(android.R.drawable.ic_dialog_alert) - .show(); - editor.putInt(Prefs.UPLOADS_SHOWING, 500); - editor.putBoolean(Prefs.IS_CONTRIBUTION_COUNT_CHANGED,true); - uploadLimit.setSummary(500 + ""); - uploadLimit.setText(500 + ""); - } else { - editor.putInt(Prefs.UPLOADS_SHOWING, Integer.parseInt(newValue.toString())); - editor.putBoolean(Prefs.IS_CONTRIBUTION_COUNT_CHANGED,true); - uploadLimit.setSummary(newValue.toString()); - } - editor.apply(); - return true; + uploadLimit.setOnPreferenceChangeListener((preference, newValue) -> { + int value = Integer.parseInt(newValue.toString()); + final SharedPreferences.Editor editor = sharedPref.edit(); + if (value > 500) { + new AlertDialog.Builder(getActivity()) + .setTitle(R.string.maximum_limit) + .setMessage(R.string.maximum_limit_alert) + .setPositiveButton(android.R.string.yes, (dialog, which) -> {}) + .setIcon(android.R.drawable.ic_dialog_alert) + .show(); + editor.putInt(Prefs.UPLOADS_SHOWING, 500); + editor.putBoolean(Prefs.IS_CONTRIBUTION_COUNT_CHANGED,true); + uploadLimit.setSummary(500 + ""); + uploadLimit.setText(500 + ""); + } else { + editor.putInt(Prefs.UPLOADS_SHOWING, Integer.parseInt(newValue.toString())); + editor.putBoolean(Prefs.IS_CONTRIBUTION_COUNT_CHANGED,true); + uploadLimit.setSummary(newValue.toString()); } - + editor.apply(); + return true; }); diff --git a/app/src/main/java/fr/free/nrw/commons/theme/NavigationBaseActivity.java b/app/src/main/java/fr/free/nrw/commons/theme/NavigationBaseActivity.java index a9c27e5e3..f689f04dd 100644 --- a/app/src/main/java/fr/free/nrw/commons/theme/NavigationBaseActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/theme/NavigationBaseActivity.java @@ -55,12 +55,7 @@ public class NavigationBaseActivity extends BaseActivity public void initBackButton() { int backStackEntryCount = getSupportFragmentManager().getBackStackEntryCount(); toggle.setDrawerIndicatorEnabled(backStackEntryCount == 0); - toggle.setToolbarNavigationClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - onBackPressed(); - } - }); + toggle.setToolbarNavigationClickListener(v -> onBackPressed()); } public void initBack() { @@ -118,25 +113,17 @@ public class NavigationBaseActivity extends BaseActivity new AlertDialog.Builder(this) .setMessage(R.string.logout_verification) .setCancelable(false) - .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - ((CommonsApplication) getApplicationContext()) - .clearApplicationData(NavigationBaseActivity.this); - Intent nearbyIntent = new Intent( - NavigationBaseActivity.this, LoginActivity.class); - nearbyIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); - nearbyIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - startActivity(nearbyIntent); - finish(); - } - }) - .setNegativeButton(R.string.no, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - dialog.cancel(); - } + .setPositiveButton(R.string.yes, (dialog, which) -> { + ((CommonsApplication) getApplicationContext()) + .clearApplicationData(NavigationBaseActivity.this); + Intent nearbyIntent = new Intent( + NavigationBaseActivity.this, LoginActivity.class); + nearbyIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); + nearbyIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(nearbyIntent); + finish(); }) + .setNegativeButton(R.string.no, (dialog, which) -> dialog.cancel()) .show(); return true; default: diff --git a/app/src/main/java/fr/free/nrw/commons/upload/ExistingFileAsync.java b/app/src/main/java/fr/free/nrw/commons/upload/ExistingFileAsync.java index cacc75596..09fed56ea 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/ExistingFileAsync.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/ExistingFileAsync.java @@ -72,21 +72,13 @@ public class ExistingFileAsync extends AsyncTask { AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setMessage(R.string.file_exists) .setTitle(R.string.warning); - builder.setPositiveButton(R.string.no, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - //Go back to ContributionsActivity - Intent intent = new Intent(context, ContributionsActivity.class); - context.startActivity(intent); - callback.onResult(Result.DUPLICATE_CANCELLED); - } - }); - builder.setNegativeButton(R.string.yes, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - callback.onResult(Result.DUPLICATE_PROCEED); - } + builder.setPositiveButton(R.string.no, (dialog, id) -> { + //Go back to ContributionsActivity + Intent intent = new Intent(context, ContributionsActivity.class); + context.startActivity(intent); + callback.onResult(Result.DUPLICATE_CANCELLED); }); + builder.setNegativeButton(R.string.yes, (dialog, id) -> callback.onResult(Result.DUPLICATE_PROCEED)); AlertDialog dialog = builder.create(); dialog.show(); diff --git a/app/src/main/java/fr/free/nrw/commons/upload/MultipleShareActivity.java b/app/src/main/java/fr/free/nrw/commons/upload/MultipleShareActivity.java index d7c807777..a3a1f8604 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/MultipleShareActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/MultipleShareActivity.java @@ -125,19 +125,16 @@ public class MultipleShareActivity Contribution up = photosList.get(i); final int uploadCount = i + 1; // Goddamn Java - uploadController.startUpload(up, new UploadController.ContributionUploadProgress() { - @Override - public void onUploadStarted(Contribution contribution) { - dialog.setProgress(uploadCount); - if(uploadCount == photosList.size()) { - dialog.dismiss(); - Toast startingToast = Toast.makeText( - CommonsApplication.getInstance(), - R.string.uploading_started, - Toast.LENGTH_LONG - ); - startingToast.show(); - } + uploadController.startUpload(up, contribution -> { + dialog.setProgress(uploadCount); + if (uploadCount == photosList.size()) { + dialog.dismiss(); + Toast startingToast = Toast.makeText( + CommonsApplication.getInstance(), + R.string.uploading_started, + Toast.LENGTH_LONG + ); + startingToast.show(); } }); } diff --git a/app/src/main/java/fr/free/nrw/commons/upload/MwVolleyApi.java b/app/src/main/java/fr/free/nrw/commons/upload/MwVolleyApi.java index 666b8cb31..f515f2d0c 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/MwVolleyApi.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/MwVolleyApi.java @@ -57,7 +57,7 @@ public class MwVolleyApi { Timber.d("URL: %s", apiUrl); JsonRequest request = new QueryRequest(apiUrl, - new LogResponseListener(), new LogResponseErrorListener()); + new LogResponseListener<>(), new LogResponseErrorListener()); getQueue().add(request); } diff --git a/app/src/main/java/fr/free/nrw/commons/upload/ShareActivity.java b/app/src/main/java/fr/free/nrw/commons/upload/ShareActivity.java index 7b9111841..8b09403f7 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/ShareActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/ShareActivity.java @@ -44,6 +44,9 @@ import fr.free.nrw.commons.modifications.TemplateRemoveModifier; import fr.free.nrw.commons.mwapi.EventLog; import timber.log.Timber; +import static fr.free.nrw.commons.upload.ExistingFileAsync.Result.DUPLICATE_PROCEED; +import static fr.free.nrw.commons.upload.ExistingFileAsync.Result.NO_DUPLICATE; + /** * Activity for the title/desc screen after image is selected. Also starts processing image * GPS coordinates or user location (if enabled in Settings) for category suggestions. @@ -133,12 +136,9 @@ public class ShareActivity Timber.d("Cache the categories found"); } - uploadController.startUpload(title, mediaUri, description, mimeType, source, decimalCoords, new UploadController.ContributionUploadProgress() { - @Override - public void onUploadStarted(Contribution contribution) { - ShareActivity.this.contribution = contribution; - showPostUpload(); - } + uploadController.startUpload(title, mediaUri, description, mimeType, source, decimalCoords, c -> { + ShareActivity.this.contribution = c; + showPostUpload(); }); } @@ -379,14 +379,10 @@ public class ShareActivity Timber.d("File SHA1 is: %s", fileSHA1); ExistingFileAsync fileAsyncTask = - new ExistingFileAsync(fileSHA1, this, new ExistingFileAsync.Callback() { - @Override - public void onResult(ExistingFileAsync.Result result) { - Timber.d("%s duplicate check: %s", mediaUri.toString(), result); - duplicateCheckPassed = - result == ExistingFileAsync.Result.DUPLICATE_PROCEED - || result == ExistingFileAsync.Result.NO_DUPLICATE; - } + new ExistingFileAsync(fileSHA1, this, result -> { + Timber.d("%s duplicate check: %s", mediaUri.toString(), result); + duplicateCheckPassed = (result == DUPLICATE_PROCEED + || result == NO_DUPLICATE); }); fileAsyncTask.execute(); } catch (IOException e) { @@ -401,17 +397,12 @@ public class ShareActivity } } - private Snackbar requestPermissionUsingSnackBar( - String rationale, final String[] perms, final int code) { + private Snackbar requestPermissionUsingSnackBar(String rationale, + final String[] perms, + final int code) { Snackbar snackbar = Snackbar.make(findViewById(android.R.id.content), rationale, - Snackbar.LENGTH_INDEFINITE) - .setAction(R.string.ok, new View.OnClickListener() { - @Override - public void onClick(View view) { - ActivityCompat.requestPermissions(ShareActivity.this, - perms, code); - } - }); + Snackbar.LENGTH_INDEFINITE).setAction(R.string.ok, + view -> ActivityCompat.requestPermissions(ShareActivity.this, perms, code)); snackbar.show(); return snackbar; } diff --git a/app/src/main/java/fr/free/nrw/commons/utils/ExecutorUtils.java b/app/src/main/java/fr/free/nrw/commons/utils/ExecutorUtils.java index 2cb93a058..df67cfea7 100644 --- a/app/src/main/java/fr/free/nrw/commons/utils/ExecutorUtils.java +++ b/app/src/main/java/fr/free/nrw/commons/utils/ExecutorUtils.java @@ -7,14 +7,11 @@ import java.util.concurrent.Executor; public class ExecutorUtils { - private static final Executor uiExecutor = new Executor() { - @Override - public void execute(Runnable command) { - if (Looper.myLooper() == Looper.getMainLooper()) { - command.run(); - } else { - new Handler(Looper.getMainLooper()).post(command); - } + private static final Executor uiExecutor = command -> { + if (Looper.myLooper() == Looper.getMainLooper()) { + command.run(); + } else { + new Handler(Looper.getMainLooper()).post(command); } }; diff --git a/app/src/main/java/fr/free/nrw/commons/utils/FileUtils.java b/app/src/main/java/fr/free/nrw/commons/utils/FileUtils.java index 0596327e3..4d50f32aa 100644 --- a/app/src/main/java/fr/free/nrw/commons/utils/FileUtils.java +++ b/app/src/main/java/fr/free/nrw/commons/utils/FileUtils.java @@ -42,8 +42,8 @@ public class FileUtils { if (file != null) { if (file.isDirectory()) { String[] children = file.list(); - for (int i = 0; i < children.length; i++) { - deletedAll = deleteFile(new File(file, children[i])) && deletedAll; + for (String child : children) { + deletedAll = deleteFile(new File(file, child)) && deletedAll; } } else { deletedAll = file.delete(); diff --git a/app/src/test/java/fr/free/nrw/commons/nearby/NearbyAdapterFactoryTest.java b/app/src/test/java/fr/free/nrw/commons/nearby/NearbyAdapterFactoryTest.java index e54e4d7f2..76125aa43 100644 --- a/app/src/test/java/fr/free/nrw/commons/nearby/NearbyAdapterFactoryTest.java +++ b/app/src/test/java/fr/free/nrw/commons/nearby/NearbyAdapterFactoryTest.java @@ -113,14 +113,6 @@ public class NearbyAdapterFactoryTest { assertEquals(PLACE, clickedPlace); } - @Test - public void clickViewHandlesMisconfiguredListener() { - NearbyAdapterFactory testObject = new NearbyAdapterFactory(null); - RVRendererAdapter result = testObject.create(Collections.singletonList(PLACE)); - RendererViewHolder viewHolder = renderComponent(result); - viewHolder.itemView.performClick(); - } - @NonNull private RendererViewHolder renderComponent(RVRendererAdapter result) { FrameLayout viewGroup = new FrameLayout(RuntimeEnvironment.application); diff --git a/build.gradle b/build.gradle index 4929fec36..ebdb2fa23 100644 --- a/build.gradle +++ b/build.gradle @@ -8,6 +8,7 @@ buildscript { classpath "com.android.tools.build:gradle:${project.gradleVersion}" classpath 'com.dicedmelon.gradle:jacoco-android:0.1.1' classpath 'com.getkeepsafe.dexcount:dexcount-gradle-plugin:0.7.1' + classpath 'me.tatarka:gradle-retrolambda:3.6.1' } }