mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-26 12:23:58 +01:00
Convert MediaDetailPagerFragment to kotlin
This commit is contained in:
parent
1d1210e863
commit
48658a693c
3 changed files with 625 additions and 592 deletions
|
|
@ -8,7 +8,7 @@ import fr.free.nrw.commons.media.MediaDetailFragment.Companion.forMedia
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
||||||
// FragmentStatePagerAdapter allows user to swipe across collection of images (no. of images undetermined)
|
// FragmentStatePagerAdapter allows user to swipe across collection of images (no. of images undetermined)
|
||||||
internal class MediaDetailAdapter(
|
class MediaDetailAdapter(
|
||||||
val mediaDetailPagerFragment: MediaDetailPagerFragment,
|
val mediaDetailPagerFragment: MediaDetailPagerFragment,
|
||||||
fm: FragmentManager
|
fm: FragmentManager
|
||||||
) : FragmentStatePagerAdapter(fm) {
|
) : FragmentStatePagerAdapter(fm) {
|
||||||
|
|
@ -24,7 +24,7 @@ internal class MediaDetailAdapter(
|
||||||
Timber.d("Skipping getItem. Returning as activity is destroyed!")
|
Timber.d("Skipping getItem. Returning as activity is destroyed!")
|
||||||
return Fragment()
|
return Fragment()
|
||||||
}
|
}
|
||||||
mediaDetailPagerFragment.binding.mediaDetailsPager.postDelayed(
|
mediaDetailPagerFragment.binding!!.mediaDetailsPager.postDelayed(
|
||||||
{ mediaDetailPagerFragment.requireActivity().invalidateOptionsMenu() }, 5
|
{ mediaDetailPagerFragment.requireActivity().invalidateOptionsMenu() }, 5
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -48,7 +48,7 @@ internal class MediaDetailAdapter(
|
||||||
Timber.d("Skipping getCount. Returning as activity is destroyed!")
|
Timber.d("Skipping getCount. Returning as activity is destroyed!")
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return mediaDetailPagerFragment.provider.getTotalMediaCount()
|
return mediaDetailPagerFragment.mediaDetailProvider!!.getTotalMediaCount()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1,589 +0,0 @@
|
||||||
package fr.free.nrw.commons.media;
|
|
||||||
|
|
||||||
import static fr.free.nrw.commons.utils.UrlUtilsKt.handleWebUrl;
|
|
||||||
|
|
||||||
import android.os.Handler;
|
|
||||||
import android.os.Looper;
|
|
||||||
import android.widget.ProgressBar;
|
|
||||||
import android.content.ActivityNotFoundException;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.graphics.Bitmap;
|
|
||||||
import android.graphics.BitmapFactory;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.Menu;
|
|
||||||
import android.view.MenuInflater;
|
|
||||||
import android.view.MenuItem;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.Toast;
|
|
||||||
import androidx.appcompat.app.ActionBar;
|
|
||||||
import androidx.appcompat.app.AlertDialog;
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
import androidx.core.content.ContextCompat;
|
|
||||||
import androidx.fragment.app.FragmentManager;
|
|
||||||
import androidx.viewpager.widget.ViewPager;
|
|
||||||
import com.google.android.material.snackbar.Snackbar;
|
|
||||||
import fr.free.nrw.commons.CommonsApplication;
|
|
||||||
import fr.free.nrw.commons.Media;
|
|
||||||
import fr.free.nrw.commons.R;
|
|
||||||
import fr.free.nrw.commons.utils.ClipboardUtils;
|
|
||||||
import fr.free.nrw.commons.auth.SessionManager;
|
|
||||||
import fr.free.nrw.commons.bookmarks.models.Bookmark;
|
|
||||||
import fr.free.nrw.commons.bookmarks.pictures.BookmarkPicturesContentProvider;
|
|
||||||
import fr.free.nrw.commons.bookmarks.pictures.BookmarkPicturesDao;
|
|
||||||
import fr.free.nrw.commons.contributions.Contribution;
|
|
||||||
import fr.free.nrw.commons.contributions.MainActivity;
|
|
||||||
import fr.free.nrw.commons.databinding.FragmentMediaDetailPagerBinding;
|
|
||||||
import fr.free.nrw.commons.di.CommonsDaggerSupportFragment;
|
|
||||||
import fr.free.nrw.commons.mwapi.OkHttpJsonApiClient;
|
|
||||||
import fr.free.nrw.commons.profile.ProfileActivity;
|
|
||||||
import fr.free.nrw.commons.utils.DownloadUtils;
|
|
||||||
import fr.free.nrw.commons.utils.ImageUtils;
|
|
||||||
import fr.free.nrw.commons.utils.NetworkUtils;
|
|
||||||
import fr.free.nrw.commons.utils.ViewUtil;
|
|
||||||
import io.reactivex.Observable;
|
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
|
||||||
import io.reactivex.disposables.CompositeDisposable;
|
|
||||||
import io.reactivex.schedulers.Schedulers;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.concurrent.Callable;
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import timber.log.Timber;
|
|
||||||
|
|
||||||
public class MediaDetailPagerFragment extends CommonsDaggerSupportFragment implements ViewPager.OnPageChangeListener, MediaDetailFragment.Callback {
|
|
||||||
|
|
||||||
@Inject BookmarkPicturesDao bookmarkDao;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
protected OkHttpJsonApiClient okHttpJsonApiClient;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
protected SessionManager sessionManager;
|
|
||||||
|
|
||||||
private static CompositeDisposable compositeDisposable = new CompositeDisposable();
|
|
||||||
|
|
||||||
FragmentMediaDetailPagerBinding binding;
|
|
||||||
|
|
||||||
boolean editable;
|
|
||||||
boolean isFeaturedImage;
|
|
||||||
boolean isWikipediaButtonDisplayed;
|
|
||||||
MediaDetailAdapter adapter;
|
|
||||||
Bookmark bookmark;
|
|
||||||
MediaDetailProvider provider;
|
|
||||||
boolean isFromFeaturedRootFragment;
|
|
||||||
int position;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ProgressBar used to indicate the loading status of media items.
|
|
||||||
*/
|
|
||||||
ProgressBar imageProgressBar;
|
|
||||||
|
|
||||||
ArrayList<Integer> removedItems=new ArrayList<Integer>();
|
|
||||||
|
|
||||||
public void clearRemoved(){
|
|
||||||
removedItems.clear();
|
|
||||||
}
|
|
||||||
public ArrayList<Integer> getRemovedItems() {
|
|
||||||
return removedItems;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Use this factory method to create a new instance of this fragment using the provided
|
|
||||||
* parameters.
|
|
||||||
*
|
|
||||||
* This method will create a new instance of MediaDetailPagerFragment and the arguments will be
|
|
||||||
* saved to a bundle which will be later available in the {@link #onCreate(Bundle)}
|
|
||||||
* @param editable
|
|
||||||
* @param isFeaturedImage
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static MediaDetailPagerFragment newInstance(boolean editable, boolean isFeaturedImage) {
|
|
||||||
MediaDetailPagerFragment mediaDetailPagerFragment = new MediaDetailPagerFragment();
|
|
||||||
Bundle args = new Bundle();
|
|
||||||
args.putBoolean("is_editable", editable);
|
|
||||||
args.putBoolean("is_featured_image", isFeaturedImage);
|
|
||||||
mediaDetailPagerFragment.setArguments(args);
|
|
||||||
return mediaDetailPagerFragment;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MediaDetailPagerFragment() {
|
|
||||||
// Required empty public constructor
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public View onCreateView(LayoutInflater inflater,
|
|
||||||
ViewGroup container,
|
|
||||||
Bundle savedInstanceState) {
|
|
||||||
binding = FragmentMediaDetailPagerBinding.inflate(inflater, container, false);
|
|
||||||
binding.mediaDetailsPager.addOnPageChangeListener(this);
|
|
||||||
// Initialize the ProgressBar by finding it in the layout
|
|
||||||
imageProgressBar = binding.getRoot().findViewById(R.id.itemProgressBar);
|
|
||||||
adapter = new MediaDetailAdapter(this, getChildFragmentManager());
|
|
||||||
|
|
||||||
// ActionBar is now supported in both activities - if this crashes something is quite wrong
|
|
||||||
final ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar();
|
|
||||||
if (actionBar != null) {
|
|
||||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new AssertionError("Action bar should not be null!");
|
|
||||||
}
|
|
||||||
|
|
||||||
// If fragment is associated with ProfileActivity, then hide the tabLayout
|
|
||||||
if (getActivity() instanceof ProfileActivity) {
|
|
||||||
((ProfileActivity)getActivity()).setTabLayoutVisibility(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Else if fragment is associated with MainActivity then hide that tab layout
|
|
||||||
else if (getActivity() instanceof MainActivity) {
|
|
||||||
((MainActivity)getActivity()).hideTabs();
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.mediaDetailsPager.setAdapter(adapter);
|
|
||||||
|
|
||||||
if (savedInstanceState != null) {
|
|
||||||
final int pageNumber = savedInstanceState.getInt("current-page");
|
|
||||||
binding.mediaDetailsPager.setCurrentItem(pageNumber, false);
|
|
||||||
getActivity().invalidateOptionsMenu();
|
|
||||||
}
|
|
||||||
adapter.notifyDataSetChanged();
|
|
||||||
|
|
||||||
return binding.getRoot();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onSaveInstanceState(Bundle outState) {
|
|
||||||
super.onSaveInstanceState(outState);
|
|
||||||
outState.putInt("current-page", binding.mediaDetailsPager.getCurrentItem());
|
|
||||||
outState.putBoolean("editable", editable);
|
|
||||||
outState.putBoolean("isFeaturedImage", isFeaturedImage);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
if (savedInstanceState != null) {
|
|
||||||
editable = savedInstanceState.getBoolean("editable", false);
|
|
||||||
isFeaturedImage = savedInstanceState.getBoolean("isFeaturedImage", false);
|
|
||||||
|
|
||||||
}
|
|
||||||
setHasOptionsMenu(true);
|
|
||||||
initProvider();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* initialise the provider, based on from where the fragment was started, as in from an activity
|
|
||||||
* or a fragment
|
|
||||||
*/
|
|
||||||
private void initProvider() {
|
|
||||||
if (getParentFragment() instanceof MediaDetailProvider) {
|
|
||||||
provider = (MediaDetailProvider) getParentFragment();
|
|
||||||
} else if (getActivity() instanceof MediaDetailProvider) {
|
|
||||||
provider = (MediaDetailProvider) getActivity();
|
|
||||||
} else {
|
|
||||||
throw new ClassCastException("Parent must implement MediaDetailProvider");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public MediaDetailProvider getMediaDetailProvider() {
|
|
||||||
return provider;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
|
||||||
if (getActivity() == null) {
|
|
||||||
Timber.d("Returning as activity is destroyed!");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Media m = provider.getMediaAtPosition(binding.mediaDetailsPager.getCurrentItem());
|
|
||||||
MediaDetailFragment mediaDetailFragment = this.adapter.getCurrentMediaDetailFragment();
|
|
||||||
switch (item.getItemId()) {
|
|
||||||
case R.id.menu_bookmark_current_image:
|
|
||||||
boolean bookmarkExists = bookmarkDao.updateBookmark(bookmark);
|
|
||||||
Snackbar snackbar = bookmarkExists ? Snackbar.make(getView(), R.string.add_bookmark, Snackbar.LENGTH_LONG) : Snackbar.make(getView(), R.string.remove_bookmark, Snackbar.LENGTH_LONG);
|
|
||||||
snackbar.show();
|
|
||||||
updateBookmarkState(item);
|
|
||||||
return true;
|
|
||||||
case R.id.menu_copy_link:
|
|
||||||
String uri = m.getPageTitle().getCanonicalUri();
|
|
||||||
ClipboardUtils.copy("shareLink", uri, requireContext());
|
|
||||||
Timber.d("Copied share link to clipboard: %s", uri);
|
|
||||||
Toast.makeText(requireContext(), getString(R.string.menu_link_copied),
|
|
||||||
Toast.LENGTH_SHORT).show();
|
|
||||||
return true;
|
|
||||||
case R.id.menu_share_current_image:
|
|
||||||
Intent shareIntent = new Intent(Intent.ACTION_SEND);
|
|
||||||
shareIntent.setType("text/plain");
|
|
||||||
shareIntent.putExtra(Intent.EXTRA_TEXT, m.getDisplayTitle() + " \n" + m.getPageTitle().getCanonicalUri());
|
|
||||||
startActivity(Intent.createChooser(shareIntent, "Share image via..."));
|
|
||||||
|
|
||||||
//Add media detail to backstack when the share button is clicked
|
|
||||||
//So that when the share is cancelled or completed the media detail page is on top
|
|
||||||
// of back stack fixing:https://github.com/commons-app/apps-android-commons/issues/2296
|
|
||||||
FragmentManager supportFragmentManager = getActivity().getSupportFragmentManager();
|
|
||||||
if (supportFragmentManager.getBackStackEntryCount() < 2) {
|
|
||||||
supportFragmentManager
|
|
||||||
.beginTransaction()
|
|
||||||
.addToBackStack(MediaDetailPagerFragment.class.getName())
|
|
||||||
.commit();
|
|
||||||
supportFragmentManager.executePendingTransactions();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
case R.id.menu_browser_current_image:
|
|
||||||
// View in browser
|
|
||||||
handleWebUrl(requireContext(), Uri.parse(m.getPageTitle().getMobileUri()));
|
|
||||||
return true;
|
|
||||||
case R.id.menu_download_current_image:
|
|
||||||
// Download
|
|
||||||
if (!NetworkUtils.isInternetConnectionEstablished(getActivity())) {
|
|
||||||
ViewUtil.showShortSnackbar(getView(), R.string.no_internet);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
DownloadUtils.downloadMedia(getActivity(), m);
|
|
||||||
return true;
|
|
||||||
case R.id.menu_set_as_wallpaper:
|
|
||||||
// Set wallpaper
|
|
||||||
setWallpaper(m);
|
|
||||||
return true;
|
|
||||||
case R.id.menu_set_as_avatar:
|
|
||||||
// Set avatar
|
|
||||||
setAvatar(m);
|
|
||||||
return true;
|
|
||||||
case R.id.menu_view_user_page:
|
|
||||||
if (m != null && m.getUser() != null) {
|
|
||||||
ProfileActivity.startYourself(getActivity(), m.getUser(),
|
|
||||||
!Objects.equals(sessionManager.getUserName(), m.getUser()));
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
case R.id.menu_view_report:
|
|
||||||
showReportDialog(m);
|
|
||||||
case R.id.menu_view_set_white_background:
|
|
||||||
if (mediaDetailFragment != null) {
|
|
||||||
mediaDetailFragment.onImageBackgroundChanged(ContextCompat.getColor(getContext(), R.color.white));
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
case R.id.menu_view_set_black_background:
|
|
||||||
if (mediaDetailFragment != null) {
|
|
||||||
mediaDetailFragment.onImageBackgroundChanged(ContextCompat.getColor(getContext(), R.color.black));
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return super.onOptionsItemSelected(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void showReportDialog(final Media media) {
|
|
||||||
if (media == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
final AlertDialog.Builder builder = new AlertDialog.Builder(requireActivity());
|
|
||||||
final String[] values = requireContext().getResources()
|
|
||||||
.getStringArray(R.array.report_violation_options);
|
|
||||||
builder.setTitle(R.string.report_violation);
|
|
||||||
builder.setItems(R.array.report_violation_options, (dialog, which) -> {
|
|
||||||
sendReportEmail(media, values[which]);
|
|
||||||
});
|
|
||||||
builder.setNegativeButton(R.string.cancel, (dialog, which) -> {});
|
|
||||||
builder.setCancelable(false);
|
|
||||||
builder.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sendReportEmail(final Media media, final String type) {
|
|
||||||
final String technicalInfo = getTechInfo(media, type);
|
|
||||||
|
|
||||||
final Intent feedbackIntent = new Intent(Intent.ACTION_SENDTO);
|
|
||||||
feedbackIntent.setType("message/rfc822");
|
|
||||||
feedbackIntent.setData(Uri.parse("mailto:"));
|
|
||||||
feedbackIntent.putExtra(Intent.EXTRA_EMAIL,
|
|
||||||
new String[]{CommonsApplication.REPORT_EMAIL});
|
|
||||||
feedbackIntent.putExtra(Intent.EXTRA_SUBJECT,
|
|
||||||
CommonsApplication.REPORT_EMAIL_SUBJECT);
|
|
||||||
feedbackIntent.putExtra(Intent.EXTRA_TEXT, technicalInfo);
|
|
||||||
try {
|
|
||||||
startActivity(feedbackIntent);
|
|
||||||
} catch (final ActivityNotFoundException e) {
|
|
||||||
Toast.makeText(getActivity(), R.string.no_email_client, Toast.LENGTH_SHORT).show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getTechInfo(final Media media, final String type) {
|
|
||||||
final StringBuilder builder = new StringBuilder();
|
|
||||||
|
|
||||||
builder.append("Report type: ")
|
|
||||||
.append(type)
|
|
||||||
.append("\n\n");
|
|
||||||
|
|
||||||
builder.append("Image that you want to report: ")
|
|
||||||
.append(media.getImageUrl())
|
|
||||||
.append("\n\n");
|
|
||||||
|
|
||||||
builder.append("User that you want to report: ")
|
|
||||||
.append(media.getUser())
|
|
||||||
.append("\n\n");
|
|
||||||
|
|
||||||
if (sessionManager.getUserName() != null) {
|
|
||||||
builder.append("Your username: ")
|
|
||||||
.append(sessionManager.getUserName())
|
|
||||||
.append("\n\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.append("Violation reason: ")
|
|
||||||
.append("\n");
|
|
||||||
|
|
||||||
builder.append("----------------------------------------------")
|
|
||||||
.append("\n")
|
|
||||||
.append("(please write reason here)")
|
|
||||||
.append("\n")
|
|
||||||
.append("----------------------------------------------")
|
|
||||||
.append("\n\n")
|
|
||||||
.append("Thank you for your report! Our team will investigate as soon as possible.")
|
|
||||||
.append("\n")
|
|
||||||
.append("Please note that images also have a `Nominate for deletion` button.");
|
|
||||||
|
|
||||||
return builder.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the media as the device's wallpaper if the imageUrl is not null
|
|
||||||
* Fails silently if setting the wallpaper fails
|
|
||||||
* @param media
|
|
||||||
*/
|
|
||||||
private void setWallpaper(Media media) {
|
|
||||||
if (media.getImageUrl() == null || media.getImageUrl().isEmpty()) {
|
|
||||||
Timber.d("Media URL not present");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ImageUtils.setWallpaperFromImageUrl(getActivity(), Uri.parse(media.getImageUrl()));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the media as user's leaderboard avatar
|
|
||||||
* @param media
|
|
||||||
*/
|
|
||||||
private void setAvatar(Media media) {
|
|
||||||
if (media.getImageUrl() == null || media.getImageUrl().isEmpty()) {
|
|
||||||
Timber.d("Media URL not present");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ImageUtils.setAvatarFromImageUrl(getActivity(), media.getImageUrl(),
|
|
||||||
Objects.requireNonNull(sessionManager.getCurrentAccount()).name,
|
|
||||||
okHttpJsonApiClient, compositeDisposable);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
|
||||||
if (!editable) { // Disable menu options for editable views
|
|
||||||
menu.clear(); // see http://stackoverflow.com/a/8495697/17865
|
|
||||||
inflater.inflate(R.menu.fragment_image_detail, menu);
|
|
||||||
if (binding.mediaDetailsPager != null) {
|
|
||||||
MediaDetailProvider provider = getMediaDetailProvider();
|
|
||||||
if(provider == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
final int position;
|
|
||||||
if (isFromFeaturedRootFragment) {
|
|
||||||
position = this.position;
|
|
||||||
} else {
|
|
||||||
position = binding.mediaDetailsPager.getCurrentItem();
|
|
||||||
}
|
|
||||||
|
|
||||||
Media m = provider.getMediaAtPosition(position);
|
|
||||||
if (m != null) {
|
|
||||||
// Enable default set of actions, then re-enable different set of actions only if it is a failed contrib
|
|
||||||
menu.findItem(R.id.menu_browser_current_image).setEnabled(true).setVisible(true);
|
|
||||||
menu.findItem(R.id.menu_copy_link).setEnabled(true).setVisible(true);
|
|
||||||
menu.findItem(R.id.menu_share_current_image).setEnabled(true).setVisible(true);
|
|
||||||
menu.findItem(R.id.menu_download_current_image).setEnabled(true).setVisible(true);
|
|
||||||
menu.findItem(R.id.menu_bookmark_current_image).setEnabled(true).setVisible(true);
|
|
||||||
menu.findItem(R.id.menu_set_as_wallpaper).setEnabled(true).setVisible(true);
|
|
||||||
if (m.getUser() != null) {
|
|
||||||
menu.findItem(R.id.menu_view_user_page).setEnabled(true).setVisible(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
URL mediaUrl = new URL(m.getImageUrl());
|
|
||||||
this.handleBackgroundColorMenuItems(
|
|
||||||
() -> BitmapFactory.decodeStream(mediaUrl.openConnection().getInputStream()),
|
|
||||||
menu
|
|
||||||
);
|
|
||||||
} catch (Exception e) {
|
|
||||||
Timber.e("Cant detect media transparency");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize bookmark object
|
|
||||||
bookmark = new Bookmark(
|
|
||||||
m.getFilename(),
|
|
||||||
m.getAuthorOrUser(),
|
|
||||||
BookmarkPicturesContentProvider.uriForName(m.getFilename())
|
|
||||||
);
|
|
||||||
updateBookmarkState(menu.findItem(R.id.menu_bookmark_current_image));
|
|
||||||
final Integer contributionState = provider.getContributionStateAt(position);
|
|
||||||
if (contributionState != null) {
|
|
||||||
switch (contributionState) {
|
|
||||||
case Contribution.STATE_FAILED:
|
|
||||||
case Contribution.STATE_IN_PROGRESS:
|
|
||||||
case Contribution.STATE_QUEUED:
|
|
||||||
menu.findItem(R.id.menu_browser_current_image).setEnabled(false)
|
|
||||||
.setVisible(false);
|
|
||||||
menu.findItem(R.id.menu_copy_link).setEnabled(false)
|
|
||||||
.setVisible(false);
|
|
||||||
menu.findItem(R.id.menu_share_current_image).setEnabled(false)
|
|
||||||
.setVisible(false);
|
|
||||||
menu.findItem(R.id.menu_download_current_image).setEnabled(false)
|
|
||||||
.setVisible(false);
|
|
||||||
menu.findItem(R.id.menu_bookmark_current_image).setEnabled(false)
|
|
||||||
.setVisible(false);
|
|
||||||
menu.findItem(R.id.menu_set_as_wallpaper).setEnabled(false)
|
|
||||||
.setVisible(false);
|
|
||||||
break;
|
|
||||||
case Contribution.STATE_COMPLETED:
|
|
||||||
// Default set of menu items works fine. Treat same as regular media object
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
menu.findItem(R.id.menu_browser_current_image).setEnabled(false)
|
|
||||||
.setVisible(false);
|
|
||||||
menu.findItem(R.id.menu_copy_link).setEnabled(false)
|
|
||||||
.setVisible(false);
|
|
||||||
menu.findItem(R.id.menu_share_current_image).setEnabled(false)
|
|
||||||
.setVisible(false);
|
|
||||||
menu.findItem(R.id.menu_download_current_image).setEnabled(false)
|
|
||||||
.setVisible(false);
|
|
||||||
menu.findItem(R.id.menu_bookmark_current_image).setEnabled(false)
|
|
||||||
.setVisible(false);
|
|
||||||
menu.findItem(R.id.menu_set_as_wallpaper).setEnabled(false)
|
|
||||||
.setVisible(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!sessionManager.isUserLoggedIn()) {
|
|
||||||
menu.findItem(R.id.menu_set_as_avatar).setVisible(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Decide wether or not we should display the background color menu items
|
|
||||||
* We display them if the image is transparent
|
|
||||||
* @param getBitmap
|
|
||||||
* @param menu
|
|
||||||
*/
|
|
||||||
private void handleBackgroundColorMenuItems(Callable<Bitmap> getBitmap, Menu menu) {
|
|
||||||
Observable.fromCallable(
|
|
||||||
getBitmap
|
|
||||||
).subscribeOn(Schedulers.newThread())
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
.subscribe(image -> {
|
|
||||||
if (image.hasAlpha()) {
|
|
||||||
menu.findItem(R.id.menu_view_set_white_background).setVisible(true).setEnabled(true);
|
|
||||||
menu.findItem(R.id.menu_view_set_black_background).setVisible(true).setEnabled(true);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateBookmarkState(MenuItem item) {
|
|
||||||
boolean isBookmarked = bookmarkDao.findBookmark(bookmark);
|
|
||||||
if(isBookmarked) {
|
|
||||||
if(removedItems.contains(binding.mediaDetailsPager.getCurrentItem())) {
|
|
||||||
removedItems.remove(new Integer(binding.mediaDetailsPager.getCurrentItem()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if(!removedItems.contains(binding.mediaDetailsPager.getCurrentItem())) {
|
|
||||||
removedItems.add(binding.mediaDetailsPager.getCurrentItem());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int icon = isBookmarked ? R.drawable.menu_ic_round_star_filled_24px : R.drawable.menu_ic_round_star_border_24px;
|
|
||||||
item.setIcon(icon);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void showImage(int i, boolean isWikipediaButtonDisplayed) {
|
|
||||||
this.isWikipediaButtonDisplayed = isWikipediaButtonDisplayed;
|
|
||||||
setViewPagerCurrentItem(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void showImage(int i) {
|
|
||||||
setViewPagerCurrentItem(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function waits for the item to load then sets the item to current item
|
|
||||||
* @param position current item that to be shown
|
|
||||||
*/
|
|
||||||
private void setViewPagerCurrentItem(int position) {
|
|
||||||
|
|
||||||
final Handler handler = new Handler(Looper.getMainLooper());
|
|
||||||
final Runnable runnable = new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
// Show the ProgressBar while waiting for the item to load
|
|
||||||
imageProgressBar.setVisibility(View.VISIBLE);
|
|
||||||
// Check if the adapter has enough items loaded
|
|
||||||
if(adapter.getCount() > position){
|
|
||||||
// Set the current item in the ViewPager
|
|
||||||
binding.mediaDetailsPager.setCurrentItem(position, false);
|
|
||||||
// Hide the ProgressBar once the item is loaded
|
|
||||||
imageProgressBar.setVisibility(View.GONE);
|
|
||||||
} else {
|
|
||||||
// If the item is not ready yet, post the Runnable again
|
|
||||||
handler.post(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// Start the Runnable
|
|
||||||
handler.post(runnable);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The method notify the viewpager that number of items have changed.
|
|
||||||
*/
|
|
||||||
public void notifyDataSetChanged(){
|
|
||||||
if (null != adapter) {
|
|
||||||
adapter.notifyDataSetChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPageScrolled(int i, float v, int i2) {
|
|
||||||
if(getActivity() == null) {
|
|
||||||
Timber.d("Returning as activity is destroyed!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
getActivity().invalidateOptionsMenu();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPageSelected(int i) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPageScrollStateChanged(int i) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onDataSetChanged() {
|
|
||||||
if (null != adapter) {
|
|
||||||
adapter.notifyDataSetChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called after the media is nominated for deletion
|
|
||||||
*
|
|
||||||
* @param index item position that has been nominated
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void nominatingForDeletion(int index) {
|
|
||||||
provider.refreshNominatedMedia(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,622 @@
|
||||||
|
package fr.free.nrw.commons.media
|
||||||
|
|
||||||
|
import android.content.ActivityNotFoundException
|
||||||
|
import android.content.DialogInterface
|
||||||
|
import android.content.Intent
|
||||||
|
import android.graphics.Bitmap
|
||||||
|
import android.graphics.BitmapFactory
|
||||||
|
import android.net.Uri
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.Looper
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.Menu
|
||||||
|
import android.view.MenuInflater
|
||||||
|
import android.view.MenuItem
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.ProgressBar
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.appcompat.app.AlertDialog
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.viewpager.widget.ViewPager.OnPageChangeListener
|
||||||
|
import com.google.android.material.snackbar.Snackbar
|
||||||
|
import fr.free.nrw.commons.CommonsApplication
|
||||||
|
import fr.free.nrw.commons.Media
|
||||||
|
import fr.free.nrw.commons.R
|
||||||
|
import fr.free.nrw.commons.auth.SessionManager
|
||||||
|
import fr.free.nrw.commons.bookmarks.models.Bookmark
|
||||||
|
import fr.free.nrw.commons.bookmarks.pictures.BookmarkPicturesContentProvider
|
||||||
|
import fr.free.nrw.commons.bookmarks.pictures.BookmarkPicturesDao
|
||||||
|
import fr.free.nrw.commons.contributions.Contribution
|
||||||
|
import fr.free.nrw.commons.contributions.MainActivity
|
||||||
|
import fr.free.nrw.commons.databinding.FragmentMediaDetailPagerBinding
|
||||||
|
import fr.free.nrw.commons.di.CommonsDaggerSupportFragment
|
||||||
|
import fr.free.nrw.commons.mwapi.OkHttpJsonApiClient
|
||||||
|
import fr.free.nrw.commons.profile.ProfileActivity
|
||||||
|
import fr.free.nrw.commons.profile.ProfileActivity.Companion.startYourself
|
||||||
|
import fr.free.nrw.commons.utils.ClipboardUtils.copy
|
||||||
|
import fr.free.nrw.commons.utils.DownloadUtils.downloadMedia
|
||||||
|
import fr.free.nrw.commons.utils.ImageUtils.setAvatarFromImageUrl
|
||||||
|
import fr.free.nrw.commons.utils.ImageUtils.setWallpaperFromImageUrl
|
||||||
|
import fr.free.nrw.commons.utils.NetworkUtils.isInternetConnectionEstablished
|
||||||
|
import fr.free.nrw.commons.utils.ViewUtil.showShortSnackbar
|
||||||
|
import fr.free.nrw.commons.utils.handleWebUrl
|
||||||
|
import io.reactivex.Observable
|
||||||
|
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||||
|
import io.reactivex.disposables.CompositeDisposable
|
||||||
|
import io.reactivex.functions.Consumer
|
||||||
|
import io.reactivex.schedulers.Schedulers
|
||||||
|
import timber.log.Timber
|
||||||
|
import java.net.URL
|
||||||
|
import java.util.concurrent.Callable
|
||||||
|
import javax.inject.Inject
|
||||||
|
import androidx.core.net.toUri
|
||||||
|
|
||||||
|
class MediaDetailPagerFragment : CommonsDaggerSupportFragment(), OnPageChangeListener,
|
||||||
|
MediaDetailFragment.Callback {
|
||||||
|
@JvmField
|
||||||
|
@Inject
|
||||||
|
var bookmarkDao: BookmarkPicturesDao? = null
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
@Inject
|
||||||
|
var okHttpJsonApiClient: OkHttpJsonApiClient? = null
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
@Inject
|
||||||
|
var sessionManager: SessionManager? = null
|
||||||
|
|
||||||
|
var binding: FragmentMediaDetailPagerBinding? = null
|
||||||
|
var editable: Boolean = false
|
||||||
|
var isFeaturedImage: Boolean = false
|
||||||
|
var isWikipediaButtonDisplayed: Boolean = false
|
||||||
|
var adapter: MediaDetailAdapter? = null
|
||||||
|
var bookmark: Bookmark? = null
|
||||||
|
var mediaDetailProvider: MediaDetailProvider? = null
|
||||||
|
var isFromFeaturedRootFragment: Boolean = false
|
||||||
|
var position: Int = 0
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ProgressBar used to indicate the loading status of media items.
|
||||||
|
*/
|
||||||
|
var imageProgressBar: ProgressBar? = null
|
||||||
|
|
||||||
|
var removedItems: ArrayList<Int> = ArrayList()
|
||||||
|
|
||||||
|
fun clearRemoved() = removedItems.clear()
|
||||||
|
|
||||||
|
override fun onCreateView(
|
||||||
|
inflater: LayoutInflater,
|
||||||
|
container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?
|
||||||
|
): View? {
|
||||||
|
binding = FragmentMediaDetailPagerBinding.inflate(inflater, container, false)
|
||||||
|
binding!!.mediaDetailsPager.addOnPageChangeListener(this)
|
||||||
|
// Initialize the ProgressBar by finding it in the layout
|
||||||
|
imageProgressBar = binding!!.root.findViewById(R.id.itemProgressBar)
|
||||||
|
adapter = MediaDetailAdapter(this, childFragmentManager)
|
||||||
|
|
||||||
|
// ActionBar is now supported in both activities - if this crashes something is quite wrong
|
||||||
|
val actionBar = (activity as AppCompatActivity).supportActionBar
|
||||||
|
if (actionBar != null) {
|
||||||
|
actionBar.setDisplayHomeAsUpEnabled(true)
|
||||||
|
} else {
|
||||||
|
throw AssertionError("Action bar should not be null!")
|
||||||
|
}
|
||||||
|
|
||||||
|
// If fragment is associated with ProfileActivity, then hide the tabLayout
|
||||||
|
if (activity is ProfileActivity) {
|
||||||
|
(activity as ProfileActivity).setTabLayoutVisibility(false)
|
||||||
|
} else if (activity is MainActivity) {
|
||||||
|
(activity as MainActivity).hideTabs()
|
||||||
|
}
|
||||||
|
|
||||||
|
binding!!.mediaDetailsPager.adapter = adapter
|
||||||
|
|
||||||
|
if (savedInstanceState != null) {
|
||||||
|
val pageNumber = savedInstanceState.getInt("current-page")
|
||||||
|
binding!!.mediaDetailsPager.setCurrentItem(pageNumber, false)
|
||||||
|
requireActivity().invalidateOptionsMenu()
|
||||||
|
}
|
||||||
|
adapter!!.notifyDataSetChanged()
|
||||||
|
|
||||||
|
return binding!!.root
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSaveInstanceState(outState: Bundle) {
|
||||||
|
super.onSaveInstanceState(outState)
|
||||||
|
outState.putInt("current-page", binding!!.mediaDetailsPager.currentItem)
|
||||||
|
outState.putBoolean("editable", editable)
|
||||||
|
outState.putBoolean("isFeaturedImage", isFeaturedImage)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
if (savedInstanceState != null) {
|
||||||
|
editable = savedInstanceState.getBoolean("editable", false)
|
||||||
|
isFeaturedImage = savedInstanceState.getBoolean("isFeaturedImage", false)
|
||||||
|
}
|
||||||
|
setHasOptionsMenu(true)
|
||||||
|
initProvider()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* initialise the provider, based on from where the fragment was started, as in from an activity
|
||||||
|
* or a fragment
|
||||||
|
*/
|
||||||
|
private fun initProvider() {
|
||||||
|
if (parentFragment is MediaDetailProvider) {
|
||||||
|
mediaDetailProvider = parentFragment as MediaDetailProvider
|
||||||
|
} else if (activity is MediaDetailProvider) {
|
||||||
|
mediaDetailProvider = activity as MediaDetailProvider?
|
||||||
|
} else {
|
||||||
|
throw ClassCastException("Parent must implement MediaDetailProvider")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
|
if (activity == null) {
|
||||||
|
Timber.d("Returning as activity is destroyed!")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
val m = mediaDetailProvider!!.getMediaAtPosition(binding!!.mediaDetailsPager.currentItem)
|
||||||
|
val mediaDetailFragment = adapter!!.currentMediaDetailFragment
|
||||||
|
when (item.itemId) {
|
||||||
|
R.id.menu_bookmark_current_image -> {
|
||||||
|
val bookmarkExists = bookmarkDao!!.updateBookmark(bookmark)
|
||||||
|
val snackbar = if (bookmarkExists) Snackbar.make(
|
||||||
|
requireView(),
|
||||||
|
R.string.add_bookmark,
|
||||||
|
Snackbar.LENGTH_LONG
|
||||||
|
) else Snackbar.make(
|
||||||
|
requireView(), R.string.remove_bookmark, Snackbar.LENGTH_LONG
|
||||||
|
)
|
||||||
|
snackbar.show()
|
||||||
|
updateBookmarkState(item)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
R.id.menu_copy_link -> {
|
||||||
|
val uri = m!!.pageTitle.canonicalUri
|
||||||
|
copy("shareLink", uri, requireContext())
|
||||||
|
Timber.d("Copied share link to clipboard: %s", uri)
|
||||||
|
Toast.makeText(
|
||||||
|
requireContext(), getString(R.string.menu_link_copied),
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
R.id.menu_share_current_image -> {
|
||||||
|
val shareIntent = Intent(Intent.ACTION_SEND)
|
||||||
|
shareIntent.setType("text/plain")
|
||||||
|
shareIntent.putExtra(
|
||||||
|
Intent.EXTRA_TEXT, """${m!!.displayTitle}
|
||||||
|
${m.pageTitle.canonicalUri}"""
|
||||||
|
)
|
||||||
|
startActivity(Intent.createChooser(shareIntent, "Share image via..."))
|
||||||
|
|
||||||
|
//Add media detail to backstack when the share button is clicked
|
||||||
|
//So that when the share is cancelled or completed the media detail page is on top
|
||||||
|
// of back stack fixing:https://github.com/commons-app/apps-android-commons/issues/2296
|
||||||
|
val supportFragmentManager = requireActivity().supportFragmentManager
|
||||||
|
if (supportFragmentManager.backStackEntryCount < 2) {
|
||||||
|
supportFragmentManager
|
||||||
|
.beginTransaction()
|
||||||
|
.addToBackStack(MediaDetailPagerFragment::class.java.name)
|
||||||
|
.commit()
|
||||||
|
supportFragmentManager.executePendingTransactions()
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
R.id.menu_browser_current_image -> {
|
||||||
|
// View in browser
|
||||||
|
handleWebUrl(requireContext(), m!!.pageTitle.mobileUri.toUri())
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
R.id.menu_download_current_image -> {
|
||||||
|
// Download
|
||||||
|
if (!isInternetConnectionEstablished(activity)) {
|
||||||
|
showShortSnackbar(requireView(), R.string.no_internet)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
downloadMedia(activity, m!!)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
R.id.menu_set_as_wallpaper -> {
|
||||||
|
// Set wallpaper
|
||||||
|
setWallpaper(m!!)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
R.id.menu_set_as_avatar -> {
|
||||||
|
// Set avatar
|
||||||
|
setAvatar(m!!)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
R.id.menu_view_user_page -> {
|
||||||
|
if (m?.user != null) {
|
||||||
|
startYourself(
|
||||||
|
requireActivity(), m.user!!,
|
||||||
|
sessionManager!!.userName != m.user
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
R.id.menu_view_report -> {
|
||||||
|
showReportDialog(m)
|
||||||
|
mediaDetailFragment?.onImageBackgroundChanged(
|
||||||
|
ContextCompat.getColor(
|
||||||
|
requireContext(),
|
||||||
|
R.color.white
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
R.id.menu_view_set_white_background -> {
|
||||||
|
mediaDetailFragment?.onImageBackgroundChanged(
|
||||||
|
ContextCompat.getColor(
|
||||||
|
requireContext(),
|
||||||
|
R.color.white
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
R.id.menu_view_set_black_background -> {
|
||||||
|
mediaDetailFragment?.onImageBackgroundChanged(
|
||||||
|
ContextCompat.getColor(
|
||||||
|
requireContext(),
|
||||||
|
R.color.black
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> return super.onOptionsItemSelected(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showReportDialog(media: Media?) {
|
||||||
|
if (media == null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val builder = AlertDialog.Builder(requireActivity())
|
||||||
|
val values = requireContext().resources
|
||||||
|
.getStringArray(R.array.report_violation_options)
|
||||||
|
builder.setTitle(R.string.report_violation)
|
||||||
|
builder.setItems(
|
||||||
|
R.array.report_violation_options
|
||||||
|
) { dialog: DialogInterface?, which: Int ->
|
||||||
|
sendReportEmail(media, values[which])
|
||||||
|
}
|
||||||
|
builder.setNegativeButton(
|
||||||
|
R.string.cancel
|
||||||
|
) { dialog: DialogInterface?, which: Int -> }
|
||||||
|
builder.setCancelable(false)
|
||||||
|
builder.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun sendReportEmail(media: Media, type: String) {
|
||||||
|
val technicalInfo = getTechInfo(media, type)
|
||||||
|
|
||||||
|
val feedbackIntent = Intent(Intent.ACTION_SENDTO)
|
||||||
|
feedbackIntent.setType("message/rfc822")
|
||||||
|
feedbackIntent.setData(Uri.parse("mailto:"))
|
||||||
|
feedbackIntent.putExtra(
|
||||||
|
Intent.EXTRA_EMAIL,
|
||||||
|
arrayOf(CommonsApplication.REPORT_EMAIL)
|
||||||
|
)
|
||||||
|
feedbackIntent.putExtra(
|
||||||
|
Intent.EXTRA_SUBJECT,
|
||||||
|
CommonsApplication.REPORT_EMAIL_SUBJECT
|
||||||
|
)
|
||||||
|
feedbackIntent.putExtra(Intent.EXTRA_TEXT, technicalInfo)
|
||||||
|
try {
|
||||||
|
startActivity(feedbackIntent)
|
||||||
|
} catch (e: ActivityNotFoundException) {
|
||||||
|
Toast.makeText(activity, R.string.no_email_client, Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getTechInfo(media: Media, type: String): String {
|
||||||
|
val builder = StringBuilder()
|
||||||
|
|
||||||
|
builder.append("Report type: ")
|
||||||
|
.append(type)
|
||||||
|
.append("\n\n")
|
||||||
|
|
||||||
|
builder.append("Image that you want to report: ")
|
||||||
|
.append(media.imageUrl)
|
||||||
|
.append("\n\n")
|
||||||
|
|
||||||
|
builder.append("User that you want to report: ")
|
||||||
|
.append(media.user)
|
||||||
|
.append("\n\n")
|
||||||
|
|
||||||
|
if (sessionManager!!.userName != null) {
|
||||||
|
builder.append("Your username: ")
|
||||||
|
.append(sessionManager!!.userName)
|
||||||
|
.append("\n\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.append("Violation reason: ")
|
||||||
|
.append("\n")
|
||||||
|
|
||||||
|
builder.append("----------------------------------------------")
|
||||||
|
.append("\n")
|
||||||
|
.append("(please write reason here)")
|
||||||
|
.append("\n")
|
||||||
|
.append("----------------------------------------------")
|
||||||
|
.append("\n\n")
|
||||||
|
.append("Thank you for your report! Our team will investigate as soon as possible.")
|
||||||
|
.append("\n")
|
||||||
|
.append("Please note that images also have a `Nominate for deletion` button.")
|
||||||
|
|
||||||
|
return builder.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the media as the device's wallpaper if the imageUrl is not null
|
||||||
|
* Fails silently if setting the wallpaper fails
|
||||||
|
* @param media
|
||||||
|
*/
|
||||||
|
private fun setWallpaper(media: Media) {
|
||||||
|
if (media.imageUrl == null || media.imageUrl!!.isEmpty()) {
|
||||||
|
Timber.d("Media URL not present")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
setWallpaperFromImageUrl(requireActivity(), media.imageUrl!!.toUri())
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the media as user's leaderboard avatar
|
||||||
|
* @param media
|
||||||
|
*/
|
||||||
|
private fun setAvatar(media: Media) {
|
||||||
|
if (media.imageUrl == null || media.imageUrl!!.isEmpty()) {
|
||||||
|
Timber.d("Media URL not present")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
setAvatarFromImageUrl(
|
||||||
|
requireActivity(), media.imageUrl!!,
|
||||||
|
sessionManager!!.currentAccount!!.name,
|
||||||
|
okHttpJsonApiClient!!, Companion.compositeDisposable
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||||
|
if (!editable) { // Disable menu options for editable views
|
||||||
|
menu.clear() // see http://stackoverflow.com/a/8495697/17865
|
||||||
|
inflater.inflate(R.menu.fragment_image_detail, menu)
|
||||||
|
if (binding!!.mediaDetailsPager != null) {
|
||||||
|
val provider = mediaDetailProvider ?: return
|
||||||
|
val position = if (isFromFeaturedRootFragment) {
|
||||||
|
position
|
||||||
|
} else {
|
||||||
|
binding!!.mediaDetailsPager.currentItem
|
||||||
|
}
|
||||||
|
|
||||||
|
val m = provider.getMediaAtPosition(position)
|
||||||
|
if (m != null) {
|
||||||
|
// Enable default set of actions, then re-enable different set of actions only if it is a failed contrib
|
||||||
|
menu.findItem(R.id.menu_browser_current_image).setEnabled(true).setVisible(true)
|
||||||
|
menu.findItem(R.id.menu_copy_link).setEnabled(true).setVisible(true)
|
||||||
|
menu.findItem(R.id.menu_share_current_image).setEnabled(true).setVisible(true)
|
||||||
|
menu.findItem(R.id.menu_download_current_image).setEnabled(true)
|
||||||
|
.setVisible(true)
|
||||||
|
menu.findItem(R.id.menu_bookmark_current_image).setEnabled(true)
|
||||||
|
.setVisible(true)
|
||||||
|
menu.findItem(R.id.menu_set_as_wallpaper).setEnabled(true).setVisible(true)
|
||||||
|
if (m.user != null) {
|
||||||
|
menu.findItem(R.id.menu_view_user_page).setEnabled(true).setVisible(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
val mediaUrl = URL(m.imageUrl)
|
||||||
|
handleBackgroundColorMenuItems({
|
||||||
|
BitmapFactory.decodeStream(
|
||||||
|
mediaUrl.openConnection().getInputStream()
|
||||||
|
)
|
||||||
|
}, menu)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Timber.e("Cant detect media transparency")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize bookmark object
|
||||||
|
bookmark = Bookmark(
|
||||||
|
m.filename,
|
||||||
|
m.getAuthorOrUser(),
|
||||||
|
BookmarkPicturesContentProvider.uriForName(m.filename)
|
||||||
|
)
|
||||||
|
updateBookmarkState(menu.findItem(R.id.menu_bookmark_current_image))
|
||||||
|
val contributionState = provider.getContributionStateAt(position)
|
||||||
|
if (contributionState != null) {
|
||||||
|
when (contributionState) {
|
||||||
|
Contribution.STATE_FAILED, Contribution.STATE_IN_PROGRESS, Contribution.STATE_QUEUED -> {
|
||||||
|
menu.findItem(R.id.menu_browser_current_image).setEnabled(false)
|
||||||
|
.setVisible(false)
|
||||||
|
menu.findItem(R.id.menu_copy_link).setEnabled(false)
|
||||||
|
.setVisible(false)
|
||||||
|
menu.findItem(R.id.menu_share_current_image).setEnabled(false)
|
||||||
|
.setVisible(false)
|
||||||
|
menu.findItem(R.id.menu_download_current_image).setEnabled(false)
|
||||||
|
.setVisible(false)
|
||||||
|
menu.findItem(R.id.menu_bookmark_current_image).setEnabled(false)
|
||||||
|
.setVisible(false)
|
||||||
|
menu.findItem(R.id.menu_set_as_wallpaper).setEnabled(false)
|
||||||
|
.setVisible(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
Contribution.STATE_COMPLETED -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
menu.findItem(R.id.menu_browser_current_image).setEnabled(false)
|
||||||
|
.setVisible(false)
|
||||||
|
menu.findItem(R.id.menu_copy_link).setEnabled(false)
|
||||||
|
.setVisible(false)
|
||||||
|
menu.findItem(R.id.menu_share_current_image).setEnabled(false)
|
||||||
|
.setVisible(false)
|
||||||
|
menu.findItem(R.id.menu_download_current_image).setEnabled(false)
|
||||||
|
.setVisible(false)
|
||||||
|
menu.findItem(R.id.menu_bookmark_current_image).setEnabled(false)
|
||||||
|
.setVisible(false)
|
||||||
|
menu.findItem(R.id.menu_set_as_wallpaper).setEnabled(false)
|
||||||
|
.setVisible(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sessionManager!!.isUserLoggedIn) {
|
||||||
|
menu.findItem(R.id.menu_set_as_avatar).setVisible(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decide wether or not we should display the background color menu items
|
||||||
|
* We display them if the image is transparent
|
||||||
|
* @param getBitmap
|
||||||
|
* @param menu
|
||||||
|
*/
|
||||||
|
private fun handleBackgroundColorMenuItems(getBitmap: Callable<Bitmap>, menu: Menu) {
|
||||||
|
Observable.fromCallable(
|
||||||
|
getBitmap
|
||||||
|
).subscribeOn(Schedulers.newThread())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(Consumer { image: Bitmap ->
|
||||||
|
if (image.hasAlpha()) {
|
||||||
|
menu.findItem(R.id.menu_view_set_white_background).setVisible(true)
|
||||||
|
.setEnabled(true)
|
||||||
|
menu.findItem(R.id.menu_view_set_black_background).setVisible(true)
|
||||||
|
.setEnabled(true)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateBookmarkState(item: MenuItem) {
|
||||||
|
val isBookmarked = bookmarkDao!!.findBookmark(bookmark)
|
||||||
|
if (isBookmarked) {
|
||||||
|
if (removedItems.contains(binding!!.mediaDetailsPager.currentItem)) {
|
||||||
|
removedItems.remove(binding!!.mediaDetailsPager.currentItem)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!removedItems.contains(binding!!.mediaDetailsPager.currentItem)) {
|
||||||
|
removedItems.add(binding!!.mediaDetailsPager.currentItem)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
item.setIcon(if (isBookmarked) {
|
||||||
|
R.drawable.menu_ic_round_star_filled_24px
|
||||||
|
} else {
|
||||||
|
R.drawable.menu_ic_round_star_border_24px
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fun showImage(i: Int, isWikipediaButtonDisplayed: Boolean) {
|
||||||
|
this.isWikipediaButtonDisplayed = isWikipediaButtonDisplayed
|
||||||
|
setViewPagerCurrentItem(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun showImage(i: Int) {
|
||||||
|
setViewPagerCurrentItem(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function waits for the item to load then sets the item to current item
|
||||||
|
* @param position current item that to be shown
|
||||||
|
*/
|
||||||
|
private fun setViewPagerCurrentItem(position: Int) {
|
||||||
|
val handler = Handler(Looper.getMainLooper())
|
||||||
|
val runnable: Runnable = object : Runnable {
|
||||||
|
override fun run() {
|
||||||
|
// Show the ProgressBar while waiting for the item to load
|
||||||
|
imageProgressBar!!.visibility = View.VISIBLE
|
||||||
|
// Check if the adapter has enough items loaded
|
||||||
|
if (adapter!!.count > position) {
|
||||||
|
// Set the current item in the ViewPager
|
||||||
|
binding!!.mediaDetailsPager.setCurrentItem(position, false)
|
||||||
|
// Hide the ProgressBar once the item is loaded
|
||||||
|
imageProgressBar!!.visibility = View.GONE
|
||||||
|
} else {
|
||||||
|
// If the item is not ready yet, post the Runnable again
|
||||||
|
handler.post(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Start the Runnable
|
||||||
|
handler.post(runnable)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The method notify the viewpager that number of items have changed.
|
||||||
|
*/
|
||||||
|
fun notifyDataSetChanged() {
|
||||||
|
if (null != adapter) {
|
||||||
|
adapter!!.notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPageScrolled(i: Int, v: Float, i2: Int) {
|
||||||
|
if (activity == null) {
|
||||||
|
Timber.d("Returning as activity is destroyed!")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
requireActivity().invalidateOptionsMenu()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPageSelected(i: Int) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPageScrollStateChanged(i: Int) {
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onDataSetChanged() {
|
||||||
|
if (null != adapter) {
|
||||||
|
adapter!!.notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called after the media is nominated for deletion
|
||||||
|
*
|
||||||
|
* @param index item position that has been nominated
|
||||||
|
*/
|
||||||
|
override fun nominatingForDeletion(index: Int) {
|
||||||
|
mediaDetailProvider!!.refreshNominatedMedia(index)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val compositeDisposable = CompositeDisposable()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use this factory method to create a new instance of this fragment using the provided
|
||||||
|
* parameters.
|
||||||
|
*
|
||||||
|
* This method will create a new instance of MediaDetailPagerFragment and the arguments will be
|
||||||
|
* saved to a bundle which will be later available in the [.onCreate]
|
||||||
|
* @param editable
|
||||||
|
* @param isFeaturedImage
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun newInstance(editable: Boolean, isFeaturedImage: Boolean): MediaDetailPagerFragment {
|
||||||
|
val mediaDetailPagerFragment = MediaDetailPagerFragment()
|
||||||
|
val args = Bundle()
|
||||||
|
args.putBoolean("is_editable", editable)
|
||||||
|
args.putBoolean("is_featured_image", isFeaturedImage)
|
||||||
|
mediaDetailPagerFragment.arguments = args
|
||||||
|
return mediaDetailPagerFragment
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue