diff --git a/app/src/main/java/fr/free/nrw/commons/Media.java b/app/src/main/java/fr/free/nrw/commons/Media.java index 726d787f3..5f6a498ea 100644 --- a/app/src/main/java/fr/free/nrw/commons/Media.java +++ b/app/src/main/java/fr/free/nrw/commons/Media.java @@ -43,6 +43,7 @@ public class Media implements Parcelable { protected String license; protected String creator; protected ArrayList categories; // as loaded at runtime? + protected boolean requestedDeletion; private Map descriptions; // multilingual descriptions as loaded private HashMap tags = new HashMap<>(); private @Nullable LatLng coordinates; @@ -416,4 +417,12 @@ public class Media implements Parcelable { parcel.writeStringList(categories); parcel.writeMap(descriptions); } + + public void setRequestedDeletion(){ + requestedDeletion = true; + } + + public boolean getRequestedDeletion(){ + return requestedDeletion; + } } diff --git a/app/src/main/java/fr/free/nrw/commons/MediaDataExtractor.java b/app/src/main/java/fr/free/nrw/commons/MediaDataExtractor.java index 25e778b74..2d79a6c4f 100644 --- a/app/src/main/java/fr/free/nrw/commons/MediaDataExtractor.java +++ b/app/src/main/java/fr/free/nrw/commons/MediaDataExtractor.java @@ -35,6 +35,7 @@ import timber.log.Timber; public class MediaDataExtractor { private final MediaWikiApi mediaWikiApi; private boolean fetched; + private boolean deletionStatus; private ArrayList categories; private Map descriptions; private String license; @@ -59,6 +60,14 @@ public class MediaDataExtractor { throw new IllegalStateException("Tried to call MediaDataExtractor.fetch() again."); } + try{ + Timber.d("Nominated for deletion: " + mediaWikiApi.pageExists("Commons:Deletion_requests/"+filename)); + deletionStatus = mediaWikiApi.pageExists("Commons:Deletion_requests/"+filename); + } + catch (Exception e){ + Timber.d(e.getMessage()); + } + MediaResult result = mediaWikiApi.fetchMediaByFilename(filename); // In-page category links are extracted from source, as XML doesn't cover [[links]] @@ -296,6 +305,9 @@ public class MediaDataExtractor { if (license != null) { media.setLicense(license); } + if (deletionStatus){ + media.setRequestedDeletion(); + } // add author, date, etc fields } diff --git a/app/src/main/java/fr/free/nrw/commons/delete/DeleteTask.java b/app/src/main/java/fr/free/nrw/commons/delete/DeleteTask.java index 07ae8cb81..0cce496f0 100644 --- a/app/src/main/java/fr/free/nrw/commons/delete/DeleteTask.java +++ b/app/src/main/java/fr/free/nrw/commons/delete/DeleteTask.java @@ -1,10 +1,13 @@ package fr.free.nrw.commons.delete; -import android.app.AlertDialog; +import android.app.NotificationManager; import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; import android.os.AsyncTask; +import android.support.v4.app.NotificationCompat; +import android.support.v4.app.NotificationCompat.Builder; +import android.view.Gravity; +import android.widget.Toast; + import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Locale; @@ -18,17 +21,18 @@ import fr.free.nrw.commons.di.ApplicationlessInjection; import fr.free.nrw.commons.mwapi.MediaWikiApi; import timber.log.Timber; -import static android.support.v4.content.ContextCompat.startActivity; +import static android.support.v4.app.NotificationCompat.DEFAULT_ALL; +import static android.support.v4.app.NotificationCompat.PRIORITY_HIGH; -public class DeleteTask extends AsyncTask { - - private static final int SUCCESS = 0; - private static final int FAILED = -1; - private static final int ALREADY_DELETED = -2; +public class DeleteTask extends AsyncTask { @Inject MediaWikiApi mwApi; @Inject SessionManager sessionManager; + public static final int NOTIFICATION_DELETE = 1; + + private NotificationManager notificationManager; + private Builder notificationBuilder; private Context context; private Media media; private String reason; @@ -45,10 +49,19 @@ public class DeleteTask extends AsyncTask { .getInstance(context.getApplicationContext()) .getCommonsApplicationComponent() .inject(this); + + notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + notificationBuilder = new NotificationCompat.Builder(context); + Toast toast = new Toast(context); + toast.setGravity(Gravity.CENTER,0,0); + toast = Toast.makeText(context,"Trying to nominate "+media.getDisplayTitle()+ " for deletion",Toast.LENGTH_SHORT); + toast.show(); } @Override - protected Integer doInBackground(Void ...voids) { + protected Boolean doInBackground(Void ...voids) { + publishProgress(0); + String editToken; String authCookie; String summary = "Nominating " + media.getFilename() +" for deletion."; @@ -56,27 +69,6 @@ public class DeleteTask extends AsyncTask { authCookie = sessionManager.getAuthCookie(); mwApi.setAuthCookie(authCookie); - try{ - if (mwApi.pageExists("Commons:Deletion_requests/"+media.getFilename())){ - return ALREADY_DELETED; - } - } - catch (Exception e) { - Timber.d(e.getMessage()); - return FAILED; - } - - try { - editToken = mwApi.getEditToken(); - } - catch (Exception e){ - Timber.d(e.getMessage()); - return FAILED; - } - if (editToken.equals("+\\")) { - return FAILED; - } - Calendar calendar = Calendar.getInstance(); String fileDeleteString = "{{delete|reason=" + reason + "|subpage=" +media.getFilename() + @@ -84,91 +76,106 @@ public class DeleteTask extends AsyncTask { "|month=" + calendar.getDisplayName(Calendar.MONTH,Calendar.LONG, Locale.getDefault()) + "|year=" + calendar.get(Calendar.YEAR) + "}}"; - try{ - mwApi.prependEdit(editToken,fileDeleteString+"\n", - media.getFilename(),summary); - } - catch (Exception e) { - Timber.d(e.getMessage()); - return FAILED; - } String subpageString = "=== [[:" + media.getFilename() + "]] ===\n" + reason + " ~~~~"; - try{ - mwApi.edit(editToken,subpageString+"\n", - "Commons:Deletion_requests/"+media.getFilename(),summary); - } - catch (Exception e) { - Timber.d(e.getMessage()); - return FAILED; - } String logPageString = "\n{{Commons:Deletion requests/" + media.getFilename() + "}}\n"; SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd"); String date = sdf.format(calendar.getTime()); - try{ - mwApi.appendEdit(editToken,logPageString+"\n", - "Commons:Deletion_requests/"+date,summary); - } - catch (Exception e) { - Timber.d(e.getMessage()); - return FAILED; - } String userPageString = "\n{{subst:idw|" + media.getFilename() + "}} ~~~~"; - try{ + + try { + editToken = mwApi.getEditToken(); + if (editToken.equals("+\\")) { + return false; + } + publishProgress(1); + + mwApi.prependEdit(editToken,fileDeleteString+"\n", + media.getFilename(),summary); + publishProgress(2); + + mwApi.edit(editToken,subpageString+"\n", + "Commons:Deletion_requests/"+media.getFilename(),summary); + publishProgress(3); + + mwApi.appendEdit(editToken,logPageString+"\n", + "Commons:Deletion_requests/"+date,summary); + publishProgress(4); + mwApi.appendEdit(editToken,userPageString+"\n", "User_Talk:"+sessionManager.getCurrentAccount().name,summary); + publishProgress(5); } catch (Exception e) { Timber.d(e.getMessage()); - return FAILED; + return false; } - return SUCCESS; + return true; } @Override - protected void onPostExecute(Integer result) { + protected void onProgressUpdate (Integer... values){ + super.onProgressUpdate(values); + String message = ""; - String title = ""; - switch (result){ - case SUCCESS: - title = "Success"; - message = "Successfully nominated " + media.getDisplayTitle() + " deletion.\n" + - "Check the webpage for more details"; + switch (values[0]){ + case 0: + message = "Getting token"; break; - case FAILED: - title = "Failed"; - message = "Could not request deletion. Something went wrong."; + case 1: + message = "Adding delete message to file"; break; - case ALREADY_DELETED: - title = "Already Nominated"; - message = media.getDisplayTitle() + " has already been nominated for deletion.\n" + - "Check the webpage for more details"; + case 2: + message = "Creating Delete requests sub-page"; + break; + case 3: + message = "Adding file to Delete requests log"; + break; + case 4: + message = "Notifying User on Talk page"; + break; + case 5: + message = "Done"; break; } - AlertDialog alert; - AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setTitle(title); - builder.setMessage(message); - builder.setCancelable(true); - builder.setPositiveButton( - R.string.ok, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) {} - }); - builder.setNeutralButton(R.string.view_browser, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - Intent browserIntent = new Intent(Intent.ACTION_VIEW, media.getFilePageTitle().getMobileUri()); - startActivity(context,browserIntent,null); - } - }); - alert = builder.create(); - alert.show(); + + notificationBuilder.setContentTitle("Nominating "+media.getDisplayTitle()+" for deletion") + .setStyle(new NotificationCompat.BigTextStyle() + .bigText(message)) + .setSmallIcon(R.drawable.ic_launcher) + .setProgress(5, values[0], false) + .setOngoing(true); + notificationManager.notify(NOTIFICATION_DELETE, notificationBuilder.build()); + } + + @Override + protected void onPostExecute(Boolean result) { + String message = ""; + String title = "Nominating for Deletion"; + + if (result){ + title += ": Success"; + message = "Successfully nominated " + media.getDisplayTitle() + " deletion."; + } + else { + title += ": Failed"; + message = "Could not request deletion."; + } + + notificationBuilder.setDefaults(DEFAULT_ALL) + .setContentTitle(title) + .setStyle(new NotificationCompat.BigTextStyle() + .bigText(message)) + .setSmallIcon(R.drawable.ic_launcher) + .setProgress(0,0,false) + .setOngoing(false) + .setPriority(PRIORITY_HIGH); + notificationManager.notify(NOTIFICATION_DELETE, notificationBuilder.build()); } } \ No newline at end of file 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 2407602bb..b06869e8d 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 @@ -15,7 +15,6 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.ViewTreeObserver; -import android.view.WindowManager; import android.widget.Button; import android.widget.EditText; import android.widget.LinearLayout; @@ -42,6 +41,7 @@ import fr.free.nrw.commons.R; import fr.free.nrw.commons.delete.DeleteTask; import fr.free.nrw.commons.di.CommonsDaggerSupportFragment; import fr.free.nrw.commons.location.LatLng; +import fr.free.nrw.commons.mwapi.MediaWikiApi; import fr.free.nrw.commons.ui.widget.CompatTextView; import timber.log.Timber; @@ -69,6 +69,9 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment { @Inject Provider mediaDataExtractorProvider; + @Inject + MediaWikiApi mwApi; + private MediaWikiImageView image; private MediaDetailSpacer spacer; @@ -79,6 +82,8 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment { private TextView license; private TextView coordinates; private TextView uploadedDate; + private TextView seeMore; + private LinearLayout nominatedforDeletion; private LinearLayout categoryContainer; private Button delete; private ScrollView scrollView; @@ -133,6 +138,8 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment { license = (TextView) view.findViewById(R.id.mediaDetailLicense); coordinates = (TextView) view.findViewById(R.id.mediaDetailCoordinates); uploadedDate = (TextView) view.findViewById(R.id.mediaDetailuploadeddate); + seeMore = (TextView) view.findViewById(R.id.seeMore); + nominatedforDeletion = (LinearLayout) view.findViewById(R.id.nominatedDeletionBanner); delete = (Button) view.findViewById(R.id.nominateDeletion); categoryContainer = (LinearLayout) view.findViewById(R.id.mediaDetailCategoryContainer); @@ -231,7 +238,6 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment { if (success) { extractor.fill(media); - setTextFields(media); setOnClickListeners(media); } else { @@ -284,21 +290,23 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment { } rebuildCatList(); - delete.setVisibility(View.VISIBLE); + checkDeletion(media); } private void setOnClickListeners(final Media media) { if (licenseLink(media) != null) { license.setOnClickListener(v -> openWebBrowser(licenseLink(media))); - } else { + } else { Toast toast = Toast.makeText(getContext(), getString(R.string.null_url), Toast.LENGTH_SHORT); toast.show(); - } + } if (media.getCoordinates() != null) { coordinates.setOnClickListener(v -> openMap(media.getCoordinates())); } - if (delete.getVisibility()==View.VISIBLE){ + if (delete.getVisibility() == View.VISIBLE) { delete.setOnClickListener(v -> { + delete.setEnabled(false); + delete.setTextColor(getResources().getColor(R.color.deleteButtonLight)); AlertDialog.Builder alert = new AlertDialog.Builder(getActivity()); alert.setMessage("Why should this file be deleted?"); final EditText input = new EditText(getActivity()); @@ -343,6 +351,11 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment { d.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false); }); } + if (nominatedforDeletion.getVisibility() == View.VISIBLE){ + seeMore.setOnClickListener(v -> { + openWebBrowser(media.getFilePageTitle().getMobileUri().toString()); + }); + } } private void rebuildCatList() { @@ -366,7 +379,7 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment { viewIntent.setAction(Intent.ACTION_VIEW); viewIntent.setData(new PageTitle(selectedCategoryTitle).getCanonicalUri()); //check if web browser available - if(viewIntent.resolveActivity(getActivity().getPackageManager()) != null){ + if (viewIntent.resolveActivity(getActivity().getPackageManager()) != null) { startActivity(viewIntent); } else { Toast toast = Toast.makeText(getContext(), getString(R.string.no_web_browser), LENGTH_SHORT); @@ -434,6 +447,16 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment { return media.getCoordinates().getPrettyCoordinateString(); } + private void checkDeletion(Media media){ + if (media.getRequestedDeletion()){ + delete.setVisibility(View.GONE); + nominatedforDeletion.setVisibility(View.VISIBLE); + } + else{ + delete.setVisibility(View.VISIBLE); + nominatedforDeletion.setVisibility(View.GONE); + } + } private @Nullable String licenseLink(Media media) { 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 ed954ed42..88d5880f5 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 @@ -1,6 +1,9 @@ package fr.free.nrw.commons.nearby; +import android.content.BroadcastReceiver; +import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.content.pm.PackageManager; import android.net.Uri; import android.os.Build; @@ -10,6 +13,7 @@ import android.support.design.widget.BottomSheetBehavior; import android.support.v4.app.FragmentTransaction; import android.support.v7.app.AlertDialog; +import android.util.Log; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; @@ -33,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.theme.NavigationBaseActivity; +import fr.free.nrw.commons.utils.NetworkUtils; import fr.free.nrw.commons.utils.UriSerializer; import fr.free.nrw.commons.utils.ViewUtil; @@ -69,11 +74,14 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp private boolean lockNearbyView; //Determines if the nearby places needs to be refreshed private BottomSheetBehavior bottomSheetBehavior; // Behavior for list bottom sheet private BottomSheetBehavior bottomSheetBehaviorForDetails; // Behavior for details bottom sheet - private NearbyMapFragment nearbyMapFragment; + public NearbyMapFragment nearbyMapFragment; private NearbyListFragment nearbyListFragment; private static final String TAG_RETAINED_MAP_FRAGMENT = NearbyMapFragment.class.getSimpleName(); private static final String TAG_RETAINED_LIST_FRAGMENT = NearbyListFragment.class.getSimpleName(); + private final String NETWORK_INTENT_ACTION = "android.net.conn.CONNECTIVITY_CHANGE"; + private BroadcastReceiver broadcastReceiver; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -271,6 +279,7 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp super.onResume(); lockNearbyView = false; checkGps(); + addNetworkBroadcastReceiver(); } @Override @@ -283,9 +292,28 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp // to the retained fragment object to perform its own cleanup. removeMapFragment(); removeListFragment(); + unregisterReceiver(broadcastReceiver); } } + private void addNetworkBroadcastReceiver() { + IntentFilter intentFilter = new IntentFilter(NETWORK_INTENT_ACTION); + + broadcastReceiver = new BroadcastReceiver() { + + @Override + public void onReceive(Context context, Intent intent) { + if (NetworkUtils.isInternetConnectionEstablished(NearbyActivity.this)) { + refreshView(LocationServiceManager + .LocationChangeType.LOCATION_SIGNIFICANTLY_CHANGED); + } else { + ViewUtil.showLongToast(NearbyActivity.this, getString(R.string.no_internet)); + } + } + }; + + this.registerReceiver(broadcastReceiver, intentFilter); + } /** @@ -297,6 +325,12 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp if (lockNearbyView) { return; } + + if (!NetworkUtils.isInternetConnectionEstablished(this)) { + hideProgressBar(); + return; + } + locationManager.registerLocationManager(); LatLng lastLocation = locationManager.getLastLocation(); 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 7d0cda450..d541a8e45 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 @@ -394,11 +394,9 @@ public class NearbyMapFragment extends DaggerFragment { } }); - // Remove texts if it doesnt fit - if (wikipediaButtonText.getLineCount() > 1 - || wikidataButtonText.getLineCount() > 1 - || commonsButtonText.getLineCount() > 1 - || directionsButtonText.getLineCount() > 1) { + // Remove button text if they exceed 1 line or if internal layout has not been built + // Only need to check for directions button because it is the longest + if (directionsButtonText.getLineCount() > 1 || directionsButtonText.getLineCount() == 0) { wikipediaButtonText.setVisibility(View.GONE); wikidataButtonText.setVisibility(View.GONE); commonsButtonText.setVisibility(View.GONE); @@ -583,7 +581,7 @@ public class NearbyMapFragment extends DaggerFragment { /* - * Add amnchors back before making them visible again. + * Add anchors back before making them visible again. * */ private void addAnchorToBigFABs(FloatingActionButton floatingActionButton, int anchorID) { CoordinatorLayout.LayoutParams params = new CoordinatorLayout.LayoutParams @@ -594,7 +592,7 @@ public class NearbyMapFragment extends DaggerFragment { } /* - * Add amnchors back before making them visible again. Big and small fabs have different anchor + * Add anchors back before making them visible again. Big and small fabs have different anchor * gravities, therefore the are two methods. * */ private void addAnchorToSmallFABs(FloatingActionButton floatingActionButton, int anchorID) { @@ -651,9 +649,6 @@ public class NearbyMapFragment extends DaggerFragment { DirectUpload directUpload = new DirectUpload(this, controller); storeSharedPrefs(); directUpload.initiateGalleryUpload(); - - //TODO: App crashes after image upload completes - //TODO: Handle onRequestPermissionsResult } }); } 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 new file mode 100644 index 000000000..e934e53e5 --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/utils/NetworkUtils.java @@ -0,0 +1,18 @@ +package fr.free.nrw.commons.utils; + + +import android.content.Context; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; + +public class NetworkUtils { + + public static boolean isInternetConnectionEstablished(Context context) { + ConnectivityManager cm = + (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE); + + 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 82227c59a..91e2114a9 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 @@ -1,7 +1,9 @@ package fr.free.nrw.commons.utils; +import android.content.Context; import android.support.design.widget.Snackbar; import android.view.View; +import android.widget.Toast; public class ViewUtil { @@ -9,4 +11,9 @@ public class ViewUtil { Snackbar.make(view, messageResourceId, Snackbar.LENGTH_SHORT).show(); } + public static void showLongToast(Context context, String text) { + Toast.makeText(context, text, + Toast.LENGTH_LONG).show(); + } + } diff --git a/app/src/main/res/drawable/bg_delete_button.xml b/app/src/main/res/drawable/bg_delete_button.xml new file mode 100644 index 000000000..199940e1b --- /dev/null +++ b/app/src/main/res/drawable/bg_delete_button.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_nearby.xml b/app/src/main/res/layout/activity_nearby.xml index 31eceff07..26d6473f3 100644 --- a/app/src/main/res/layout/activity_nearby.xml +++ b/app/src/main/res/layout/activity_nearby.xml @@ -5,7 +5,7 @@ android:layout_width="match_parent" android:layout_height="match_parent"> - - @@ -37,33 +38,14 @@ android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent" /> - - + @@ -88,7 +70,7 @@ - + + + + + +