diff --git a/app/src/main/java/fr/free/nrw/commons/achievements/AchievementsActivity.java b/app/src/main/java/fr/free/nrw/commons/achievements/AchievementsActivity.java index d04d2b7b1d..b2b14f3c94 100644 --- a/app/src/main/java/fr/free/nrw/commons/achievements/AchievementsActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/achievements/AchievementsActivity.java @@ -185,6 +185,7 @@ void shareScreen(Bitmap bitmap) { * which then calls parseJson when results are fetched */ private void setAchievements() { + progressBar.setVisibility(View.VISIBLE); if (checkAccount()) { compositeDisposable.add(mediaWikiApi .getAchievements(Objects.requireNonNull(sessionManager.getCurrentAccount()).name) @@ -195,17 +196,23 @@ private void setAchievements() { if (response != null) { setUploadCount(Achievements.from(response)); } else { - onError(); + showSnackBarWithRetry(); } }, t -> { Timber.e(t, "Fetching achievements statistics failed"); - onError(); + showSnackBarWithRetry(); } )); } } + private void showSnackBarWithRetry() { + progressBar.setVisibility(View.GONE); + ViewUtil.showDismissibleSnackBar(findViewById(android.R.id.content), + R.string.achievements_fetch_failed, R.string.retry, view -> setAchievements()); + } + /** * Shows a generic error toast when error occurs while loading achievements or uploads */ diff --git a/app/src/main/java/fr/free/nrw/commons/auth/AuthenticatedActivity.java b/app/src/main/java/fr/free/nrw/commons/auth/AuthenticatedActivity.java index b7c639f246..1bfcb77277 100644 --- a/app/src/main/java/fr/free/nrw/commons/auth/AuthenticatedActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/auth/AuthenticatedActivity.java @@ -64,7 +64,7 @@ protected void showBlockStatus() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .filter(result -> result) - .subscribe(result -> ViewUtil.showSnackbar(findViewById(android.R.id.content), R.string.block_notification) + .subscribe(result -> ViewUtil.showShortSnackbar(findViewById(android.R.id.content), R.string.block_notification) ); } } diff --git a/app/src/main/java/fr/free/nrw/commons/bookmarks/pictures/BookmarkPicturesController.java b/app/src/main/java/fr/free/nrw/commons/bookmarks/pictures/BookmarkPicturesController.java index cca5867bb1..9bd2613a1f 100644 --- a/app/src/main/java/fr/free/nrw/commons/bookmarks/pictures/BookmarkPicturesController.java +++ b/app/src/main/java/fr/free/nrw/commons/bookmarks/pictures/BookmarkPicturesController.java @@ -36,7 +36,7 @@ List loadBookmarkedPictures() { for (Bookmark bookmark : bookmarks) { List tmpMedias = mediaWikiApi.searchImages(bookmark.getMediaName(), 0); for (Media m : tmpMedias) { - if (m.getCreator().equals(bookmark.getMediaCreator())) { + if (m.getCreator().trim().equals(bookmark.getMediaCreator().trim())) { medias.add(m); break; } diff --git a/app/src/main/java/fr/free/nrw/commons/bookmarks/pictures/BookmarkPicturesFragment.java b/app/src/main/java/fr/free/nrw/commons/bookmarks/pictures/BookmarkPicturesFragment.java index 90b3ef4574..a416433099 100644 --- a/app/src/main/java/fr/free/nrw/commons/bookmarks/pictures/BookmarkPicturesFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/bookmarks/pictures/BookmarkPicturesFragment.java @@ -129,7 +129,7 @@ private void handleNoInternet() { statusTextView.setVisibility(VISIBLE); statusTextView.setText(getString(R.string.no_internet)); } else { - ViewUtil.showSnackbar(parentLayout, R.string.no_internet); + ViewUtil.showShortSnackbar(parentLayout, R.string.no_internet); } } @@ -140,7 +140,7 @@ private void handleNoInternet() { private void handleError(Throwable throwable) { Timber.e(throwable, "Error occurred while loading images inside a category"); try{ - ViewUtil.showSnackbar(parentLayout, R.string.error_loading_images); + ViewUtil.showShortSnackbar(parentLayout, R.string.error_loading_images); initErrorView(); }catch (Exception e){ e.printStackTrace(); diff --git a/app/src/main/java/fr/free/nrw/commons/category/CategoryImagesListFragment.java b/app/src/main/java/fr/free/nrw/commons/category/CategoryImagesListFragment.java index 1ead687017..1b91927e5b 100644 --- a/app/src/main/java/fr/free/nrw/commons/category/CategoryImagesListFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/category/CategoryImagesListFragment.java @@ -124,7 +124,7 @@ private void handleNoInternet() { statusTextView.setVisibility(VISIBLE); statusTextView.setText(getString(R.string.no_internet)); } else { - ViewUtil.showSnackbar(parentLayout, R.string.no_internet); + ViewUtil.showShortSnackbar(parentLayout, R.string.no_internet); } } @@ -135,7 +135,7 @@ private void handleNoInternet() { private void handleError(Throwable throwable) { Timber.e(throwable, "Error occurred while loading images inside a category"); try{ - ViewUtil.showSnackbar(parentLayout, R.string.error_loading_images); + ViewUtil.showShortSnackbar(parentLayout, R.string.error_loading_images); initErrorView(); }catch (Exception e){ e.printStackTrace(); diff --git a/app/src/main/java/fr/free/nrw/commons/category/SubCategoryListFragment.java b/app/src/main/java/fr/free/nrw/commons/category/SubCategoryListFragment.java index 984d87fae4..476fde975d 100644 --- a/app/src/main/java/fr/free/nrw/commons/category/SubCategoryListFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/category/SubCategoryListFragment.java @@ -135,10 +135,10 @@ private void handleSuccess(List subCategoryList) { private void handleError(Throwable throwable) { if (!isParentCategory){ Timber.e(throwable, "Error occurred while loading queried subcategories"); - ViewUtil.showSnackbar(categoriesRecyclerView,R.string.error_loading_categories); + ViewUtil.showShortSnackbar(categoriesRecyclerView,R.string.error_loading_categories); }else { Timber.e(throwable, "Error occurred while loading queried parentcategories"); - ViewUtil.showSnackbar(categoriesRecyclerView,R.string.error_loading_categories); + ViewUtil.showShortSnackbar(categoriesRecyclerView,R.string.error_loading_categories); } } @@ -161,6 +161,6 @@ private void initEmptyView() { */ private void handleNoInternet() { progressBar.setVisibility(GONE); - ViewUtil.showSnackbar(categoriesRecyclerView, R.string.no_internet); + ViewUtil.showShortSnackbar(categoriesRecyclerView, R.string.no_internet); } } diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/MainActivity.java b/app/src/main/java/fr/free/nrw/commons/contributions/MainActivity.java index 9b8035e5d5..24f47e3f01 100644 --- a/app/src/main/java/fr/free/nrw/commons/contributions/MainActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/contributions/MainActivity.java @@ -1,5 +1,6 @@ package fr.free.nrw.commons.contributions; +import android.app.AlertDialog; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; @@ -119,22 +120,19 @@ private void addTabsAndFragments() { // Set custom view to add nearby info icon next to text View nearbyTabLinearLayout = LayoutInflater.from(this).inflate(R.layout.custom_nearby_tab_layout, null); - View nearbyInfoPopupWindowLayout = LayoutInflater.from(this).inflate(R.layout.nearby_info_popup_layout, null); ImageView nearbyInfo = nearbyTabLinearLayout.findViewById(R.id.nearby_info_image); tabLayout.getTabAt(1).setCustomView(nearbyTabLinearLayout); nearbyInfo.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { - /*new AlertDialog.Builder(MainActivity.this) + new AlertDialog.Builder(MainActivity.this) .setTitle(R.string.title_activity_nearby) .setMessage(R.string.showcase_view_whole_nearby_activity) .setCancelable(true) .setNeutralButton(android.R.string.ok, (dialog, id) -> dialog.cancel()) .create() - .show();*/ - String popupText = getResources().getString(R.string.showcase_view_whole_nearby_activity); - ViewUtil.displayPopupWindow(nearbyInfo, MainActivity.this, nearbyInfoPopupWindowLayout, popupText); + .show(); } }); diff --git a/app/src/main/java/fr/free/nrw/commons/di/NetworkingModule.java b/app/src/main/java/fr/free/nrw/commons/di/NetworkingModule.java index 953b7ecee5..e894f8ab92 100644 --- a/app/src/main/java/fr/free/nrw/commons/di/NetworkingModule.java +++ b/app/src/main/java/fr/free/nrw/commons/di/NetworkingModule.java @@ -9,6 +9,7 @@ import java.io.File; +import java.util.concurrent.TimeUnit; import javax.inject.Named; import javax.inject.Singleton; @@ -30,9 +31,11 @@ public class NetworkingModule { @Singleton public OkHttpClient provideOkHttpClient(Context context) { File dir = new File(context.getCacheDir(), "okHttpCache"); - return new OkHttpClient.Builder() - .cache(new Cache(dir, OK_HTTP_CACHE_SIZE)) - .build(); + return new OkHttpClient.Builder().connectTimeout(60, TimeUnit.SECONDS) + .writeTimeout(60, TimeUnit.SECONDS) + .readTimeout(60, TimeUnit.SECONDS) + .cache(new Cache(dir, OK_HTTP_CACHE_SIZE)) + .build(); } @Provides diff --git a/app/src/main/java/fr/free/nrw/commons/explore/categories/SearchCategoryFragment.java b/app/src/main/java/fr/free/nrw/commons/explore/categories/SearchCategoryFragment.java index 520c55a572..983127c69d 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/categories/SearchCategoryFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/explore/categories/SearchCategoryFragment.java @@ -196,7 +196,7 @@ private void handleError(Throwable throwable) { Timber.e(throwable, "Error occurred while loading queried categories"); try { initErrorView(); - ViewUtil.showSnackbar(categoriesRecyclerView, R.string.error_loading_categories); + ViewUtil.showShortSnackbar(categoriesRecyclerView, R.string.error_loading_categories); }catch (Exception e){ e.printStackTrace(); } @@ -217,6 +217,6 @@ private void initErrorView() { */ private void handleNoInternet() { progressBar.setVisibility(GONE); - ViewUtil.showSnackbar(categoriesRecyclerView, R.string.no_internet); + ViewUtil.showShortSnackbar(categoriesRecyclerView, R.string.no_internet); } } diff --git a/app/src/main/java/fr/free/nrw/commons/explore/images/SearchImageFragment.java b/app/src/main/java/fr/free/nrw/commons/explore/images/SearchImageFragment.java index 8b28f50d51..f3beadfcf0 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/images/SearchImageFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/explore/images/SearchImageFragment.java @@ -206,7 +206,7 @@ private void handleSuccess(List mediaList) { private void handleError(Throwable throwable) { Timber.e(throwable, "Error occurred while loading queried images"); try { - ViewUtil.showSnackbar(imagesRecyclerView, R.string.error_loading_images); + ViewUtil.showShortSnackbar(imagesRecyclerView, R.string.error_loading_images); }catch (Exception e){ e.printStackTrace(); } @@ -226,7 +226,7 @@ private void initErrorView() { */ private void handleNoInternet() { progressBar.setVisibility(GONE); - ViewUtil.showSnackbar(imagesRecyclerView, R.string.no_internet); + ViewUtil.showShortSnackbar(imagesRecyclerView, R.string.no_internet); } /** 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 76549b2077..4eb69af7c3 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 @@ -271,7 +271,7 @@ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { menu.clear(); // see http://stackoverflow.com/a/8495697/17865 inflater.inflate(R.menu.fragment_image_detail, menu); if (pager != null) { - MediaDetailProvider provider = (MediaDetailProvider) getParentFragment(); + MediaDetailProvider provider = getMediaDetailProvider(); if(provider == null) { return; } 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 8c4c39639b..5ad6b52fcd 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 @@ -350,6 +350,7 @@ public MediaResult fetchMediaByFilename(String filename) throws IOException { @Override @NonNull public Observable searchCategories(String filterValue, int searchCatsLimit) { + List categories = new ArrayList<>(); return Single.fromCallable(() -> { List categoryNodes = null; try { @@ -370,11 +371,12 @@ public Observable searchCategories(String filterValue, int searchCatsLim return new ArrayList(); } - List categories = new ArrayList<>(); for (CustomApiResult categoryNode : categoryNodes) { String cat = categoryNode.getDocument().getTextContent(); String catString = cat.replace("Category:", ""); - categories.add(catString); + if (!categories.contains(catString)) { + categories.add(catString); + } } return categories; diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyFragment.java b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyFragment.java index 58943b0b5c..5a1c48edf5 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyFragment.java @@ -16,7 +16,6 @@ import android.support.v7.app.AlertDialog; import android.util.Log; import android.view.LayoutInflater; - import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; @@ -38,6 +37,7 @@ import fr.free.nrw.commons.location.LatLng; import fr.free.nrw.commons.location.LocationServiceManager; import fr.free.nrw.commons.location.LocationUpdateListener; +import fr.free.nrw.commons.utils.FragmentUtils; import fr.free.nrw.commons.utils.NetworkUtils; import fr.free.nrw.commons.utils.UriSerializer; import fr.free.nrw.commons.utils.ViewUtil; @@ -116,7 +116,6 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c resumeFragment();*/ bundle = new Bundle(); initBottomSheetBehaviour(); - wikidataEditListener.setAuthenticationStateListener(this); this.view = view; return view; } @@ -387,7 +386,7 @@ private void populatePlaces(NearbyController.NearbyPlacesInfo nearbyPlacesInfo) String gsonBoundaryCoordinates = gson.toJson(boundaryCoordinates); if (placeList.size() == 0) { - ViewUtil.showSnackbar(view.findViewById(R.id.container), R.string.no_nearby); + ViewUtil.showShortSnackbar(view.findViewById(R.id.container), R.string.no_nearby); } bundle.putString("PlaceList", gsonPlaceList); @@ -673,14 +672,17 @@ private void showErrorMessage(String message) { } private void addNetworkBroadcastReceiver() { + if (!FragmentUtils.isFragmentUIActive(this)) { + return; + } + IntentFilter intentFilter = new IntentFilter(NETWORK_INTENT_ACTION); - snackbar = Snackbar.make(transparentView , R.string.no_internet, Snackbar.LENGTH_INDEFINITE); - - broadcastReceiver = new BroadcastReceiver() { + snackbar = Snackbar.make(transparentView, R.string.no_internet, Snackbar.LENGTH_INDEFINITE); + broadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - if (snackbar != null) { + if (snackbar != null && getActivity() != null) { if (NetworkUtils.isInternetConnectionEstablished(getActivity())) { refreshView(LOCATION_SIGNIFICANTLY_CHANGED); snackbar.dismiss(); @@ -691,6 +693,10 @@ public void onReceive(Context context, Intent intent) { } }; + if (getActivity() == null) { + return; + } + getActivity().registerReceiver(broadcastReceiver, intentFilter); } @@ -723,6 +729,7 @@ private void performNearbyOperations() { @Override public void onAttach(Context context) { super.onAttach(context); + wikidataEditListener.setAuthenticationStateListener(this); } @Override @@ -731,6 +738,7 @@ public void onDestroy() { if (placesDisposable != null) { placesDisposable.dispose(); } + wikidataEditListener.setAuthenticationStateListener(null); if (placesDisposableCustom != null) { placesDisposableCustom.dispose(); } @@ -741,6 +749,7 @@ public void onDetach() { super.onDetach(); snackbar = null; broadcastReceiver = null; + wikidataEditListener.setAuthenticationStateListener(null); } @Override diff --git a/app/src/main/java/fr/free/nrw/commons/notification/NotificationActivity.java b/app/src/main/java/fr/free/nrw/commons/notification/NotificationActivity.java index ebeb7f7181..5036d6fa87 100644 --- a/app/src/main/java/fr/free/nrw/commons/notification/NotificationActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/notification/NotificationActivity.java @@ -106,7 +106,7 @@ private void addNotifications() { progressBar.setVisibility(View.GONE); }, throwable -> { Timber.e(throwable, "Error occurred while loading notifications"); - ViewUtil.showSnackbar(relativeLayout, R.string.error_notifications); + ViewUtil.showShortSnackbar(relativeLayout, R.string.error_notifications); progressBar.setVisibility(View.GONE); }); } else { @@ -123,7 +123,7 @@ private void handleUrl(String url) { private void setAdapter(List notificationList) { if (notificationList == null || notificationList.isEmpty()) { - ViewUtil.showSnackbar(relativeLayout, R.string.no_notifications); + ViewUtil.showShortSnackbar(relativeLayout, R.string.no_notifications); return; } notificationAdapterFactory = new NotificationAdapterFactory(notification -> { diff --git a/app/src/main/java/fr/free/nrw/commons/utils/FragmentUtils.java b/app/src/main/java/fr/free/nrw/commons/utils/FragmentUtils.java index d0e432c330..63c9d974da 100644 --- a/app/src/main/java/fr/free/nrw/commons/utils/FragmentUtils.java +++ b/app/src/main/java/fr/free/nrw/commons/utils/FragmentUtils.java @@ -28,4 +28,13 @@ public static boolean addAndCommitFragmentWithImmediateExecution( } return false; } + + /** + * Utility function to check whether the fragment UI is still active or not + * @param fragment + * @return + */ + public static boolean isFragmentUIActive(Fragment fragment) { + return fragment.getActivity() != null && fragment.isAdded() && !fragment.isDetached() && !fragment.isRemoving(); + } } diff --git a/app/src/main/java/fr/free/nrw/commons/utils/NetworkUtils.java b/app/src/main/java/fr/free/nrw/commons/utils/NetworkUtils.java index b9da22e6ee..030dbdef8d 100644 --- a/app/src/main/java/fr/free/nrw/commons/utils/NetworkUtils.java +++ b/app/src/main/java/fr/free/nrw/commons/utils/NetworkUtils.java @@ -11,6 +11,9 @@ public static boolean isInternetConnectionEstablished(Context context) { ConnectivityManager cm = (ConnectivityManager)context.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE); + if (cm == null) { + return false; + } NetworkInfo activeNetwork = cm.getActiveNetworkInfo(); return activeNetwork != null && activeNetwork.isConnectedOrConnecting(); diff --git a/app/src/main/java/fr/free/nrw/commons/utils/ViewUtil.java b/app/src/main/java/fr/free/nrw/commons/utils/ViewUtil.java index aef3dddb0c..e88194d153 100644 --- a/app/src/main/java/fr/free/nrw/commons/utils/ViewUtil.java +++ b/app/src/main/java/fr/free/nrw/commons/utils/ViewUtil.java @@ -17,7 +17,12 @@ public class ViewUtil { public static final String SHOWCASE_VIEW_ID_2 = "SHOWCASE_VIEW_ID_2"; public static final String SHOWCASE_VIEW_ID_3 = "SHOWCASE_VIEW_ID_3"; - public static void showSnackbar(View view, int messageResourceId) { + /** + * Utility function to show short snack bar + * @param view + * @param messageResourceId + */ + public static void showShortSnackbar(View view, int messageResourceId) { if (view.getContext() == null) { return; } @@ -76,15 +81,23 @@ public static void hideKeyboard(View view){ } } - public static void displayPopupWindow(View anchorView, Context context, View popupWindowLayout, String text) { - - PopupWindow popup = new PopupWindow(context); - popup.setContentView(popupWindowLayout); - // Closes the popup window when touch outside of it - when looses focus - popup.setOutsideTouchable(true); - popup.setFocusable(true); - // Show anchored to button - popup.showAsDropDown(anchorView); + /** + * A snack bar which has an action button which on click dismisses the snackbar and invokes the + * listener passed + */ + public static void showDismissibleSnackBar(View view, int messageResourceId, + int actionButtonResourceId, View.OnClickListener onClickListener) { + if (view.getContext() == null) { + return; + } + ExecutorUtils.uiExecutor().execute(() -> { + Snackbar snackbar = Snackbar.make(view, view.getContext().getString(messageResourceId), + Snackbar.LENGTH_INDEFINITE); + snackbar.setAction(view.getContext().getString(actionButtonResourceId), v -> { + snackbar.dismiss(); + onClickListener.onClick(v); + }); + snackbar.show(); + }); } - } diff --git a/app/src/main/res/layout/nearby_info_popup_layout.xml b/app/src/main/res/layout/nearby_info_popup_layout.xml deleted file mode 100644 index 04c1a2d547..0000000000 --- a/app/src/main/res/layout/nearby_info_popup_layout.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 06025e255a..a54ee35fd5 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -437,6 +437,7 @@ Upload your first media by touching the camera or gallery icon above. Never ask this again Display location permission Ask for location permission when needed for nearby notification card view feature. + Something went wrong, We could not fetch your achievements Ends on: Display campaigns Tap here to see the ongoing campaigns