mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-26 12:23:58 +01:00
[GSoC] Added option to set a new avatar (#3892)
* Fixes #3861 Use the APIs to fetch leaderboard’s based on uploads via mobile app (all time) and display it in the Leaderboard screen. * Added option to set a new avatar
This commit is contained in:
parent
5f77f610f5
commit
bc0b5c05c7
9 changed files with 182 additions and 23 deletions
|
|
@ -22,15 +22,19 @@ import butterknife.ButterKnife;
|
|||
import com.google.android.material.snackbar.Snackbar;
|
||||
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.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.di.CommonsDaggerSupportFragment;
|
||||
import fr.free.nrw.commons.mwapi.OkHttpJsonApiClient;
|
||||
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.disposables.CompositeDisposable;
|
||||
import java.util.Objects;
|
||||
import javax.inject.Inject;
|
||||
import timber.log.Timber;
|
||||
|
||||
|
|
@ -38,6 +42,14 @@ public class MediaDetailPagerFragment extends CommonsDaggerSupportFragment imple
|
|||
|
||||
@Inject BookmarkPicturesDao bookmarkDao;
|
||||
|
||||
@Inject
|
||||
OkHttpJsonApiClient okHttpJsonApiClient;
|
||||
|
||||
@Inject
|
||||
SessionManager sessionManager;
|
||||
|
||||
private static CompositeDisposable compositeDisposable = new CompositeDisposable();
|
||||
|
||||
@BindView(R.id.mediaDetailsPager) ViewPager pager;
|
||||
private Boolean editable;
|
||||
private boolean isFeaturedImage;
|
||||
|
|
@ -159,6 +171,10 @@ public class MediaDetailPagerFragment extends CommonsDaggerSupportFragment imple
|
|||
// Set wallpaper
|
||||
setWallpaper(m);
|
||||
return true;
|
||||
case R.id.menu_set_as_avatar:
|
||||
// Set avatar
|
||||
setAvatar(m);
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
|
@ -177,6 +193,20 @@ public class MediaDetailPagerFragment extends CommonsDaggerSupportFragment imple
|
|||
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
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import fr.free.nrw.commons.nearby.model.NearbyResultItem;
|
|||
import fr.free.nrw.commons.profile.achievements.FeaturedImages;
|
||||
import fr.free.nrw.commons.profile.achievements.FeedbackResponse;
|
||||
import fr.free.nrw.commons.profile.leaderboard.LeaderboardResponse;
|
||||
import fr.free.nrw.commons.profile.leaderboard.UpdateAvatarResponse;
|
||||
import fr.free.nrw.commons.upload.FileUtils;
|
||||
import fr.free.nrw.commons.upload.structure.depictions.DepictedItem;
|
||||
import fr.free.nrw.commons.utils.ConfigUtils;
|
||||
|
|
@ -103,6 +104,38 @@ public class OkHttpJsonApiClient {
|
|||
});
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public Single<UpdateAvatarResponse> setAvatar(String username, String avatar) {
|
||||
final String urlTemplate = wikiMediaTestToolforgeUrl
|
||||
+ "/update_avatar.py";
|
||||
return Single.fromCallable(() -> {
|
||||
String url = String.format(Locale.ENGLISH,
|
||||
urlTemplate,
|
||||
username,
|
||||
avatar);
|
||||
HttpUrl.Builder urlBuilder = HttpUrl.parse(url).newBuilder();
|
||||
urlBuilder.addQueryParameter("user", username);
|
||||
urlBuilder.addQueryParameter("avatar", avatar);
|
||||
Timber.i("Url %s", urlBuilder.toString());
|
||||
Request request = new Request.Builder()
|
||||
.url(urlBuilder.toString())
|
||||
.build();
|
||||
Response response = okHttpClient.newCall(request).execute();
|
||||
if (response != null && response.body() != null && response.isSuccessful()) {
|
||||
String json = response.body().string();
|
||||
if (json == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return gson.fromJson(json, UpdateAvatarResponse.class);
|
||||
} catch (Exception e) {
|
||||
return new UpdateAvatarResponse();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public Single<Integer> getUploadCount(String userName) {
|
||||
HttpUrl.Builder urlBuilder = wikiMediaToolforgeUrl.newBuilder();
|
||||
|
|
|
|||
|
|
@ -6,8 +6,6 @@ public class LeaderboardConstants {
|
|||
|
||||
public static final int START_OFFSET = 0;
|
||||
|
||||
public static final String AVATAR_SOURCE_URL = "https://upload.wikimedia.org/wikipedia/commons/thumb/0/0a/%s/1024px-%s.png";
|
||||
|
||||
public final static String LOADING = "Loading";
|
||||
|
||||
public final static String LOADED = "Loaded";
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
package fr.free.nrw.commons.profile.leaderboard;
|
||||
|
||||
import static fr.free.nrw.commons.profile.leaderboard.LeaderboardConstants.AVATAR_SOURCE_URL;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.view.LayoutInflater;
|
||||
|
|
@ -72,9 +70,7 @@ public class LeaderboardListAdapter extends PagedListAdapter<LeaderboardList, Le
|
|||
|
||||
rank.setText(getItem(position).getRank().toString());
|
||||
|
||||
avatar.setImageURI(
|
||||
Uri.parse(String.format(AVATAR_SOURCE_URL, getItem(position).getAvatar(),
|
||||
getItem(position).getAvatar())));
|
||||
avatar.setImageURI(Uri.parse(getItem(position).getAvatar()));
|
||||
username.setText(getItem(position).getUsername());
|
||||
count.setText(getItem(position).getCategoryCount().toString());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,44 @@
|
|||
package fr.free.nrw.commons.profile.leaderboard;
|
||||
|
||||
import com.google.gson.annotations.Expose;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
public class UpdateAvatarResponse {
|
||||
|
||||
@SerializedName("status")
|
||||
@Expose
|
||||
private String status;
|
||||
|
||||
@SerializedName("message")
|
||||
@Expose
|
||||
private String message;
|
||||
|
||||
@SerializedName("user")
|
||||
@Expose
|
||||
private String user;
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(String status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public String getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public void setUser(String user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,7 +1,5 @@
|
|||
package fr.free.nrw.commons.profile.leaderboard;
|
||||
|
||||
import static fr.free.nrw.commons.profile.leaderboard.LeaderboardConstants.AVATAR_SOURCE_URL;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.view.LayoutInflater;
|
||||
|
|
@ -62,8 +60,7 @@ public class UserDetailAdapter extends RecyclerView.Adapter<UserDetailAdapter.Da
|
|||
leaderboardResponse.getRank()));
|
||||
|
||||
avatar.setImageURI(
|
||||
Uri.parse(String.format(AVATAR_SOURCE_URL, leaderboardResponse.getAvatar(),
|
||||
leaderboardResponse.getAvatar())));
|
||||
Uri.parse(leaderboardResponse.getAvatar()));
|
||||
username.setText(leaderboardResponse.getUsername());
|
||||
count.setText(String.format("%s %d",
|
||||
holder.getContext().getResources().getString(R.string.count_prefix),
|
||||
|
|
|
|||
|
|
@ -7,11 +7,9 @@ import android.graphics.Bitmap;
|
|||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Color;
|
||||
import android.net.Uri;
|
||||
|
||||
import androidx.annotation.IntDef;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.exifinterface.media.ExifInterface;
|
||||
|
||||
import com.facebook.common.executors.CallerThreadExecutor;
|
||||
import com.facebook.common.references.CloseableReference;
|
||||
import com.facebook.datasource.DataSource;
|
||||
|
|
@ -21,13 +19,15 @@ import com.facebook.imagepipeline.datasource.BaseBitmapDataSubscriber;
|
|||
import com.facebook.imagepipeline.image.CloseableImage;
|
||||
import com.facebook.imagepipeline.request.ImageRequest;
|
||||
import com.facebook.imagepipeline.request.ImageRequestBuilder;
|
||||
|
||||
import fr.free.nrw.commons.R;
|
||||
import fr.free.nrw.commons.location.LatLng;
|
||||
import fr.free.nrw.commons.mwapi.OkHttpJsonApiClient;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.disposables.CompositeDisposable;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import java.io.IOException;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
import fr.free.nrw.commons.R;
|
||||
import fr.free.nrw.commons.location.LatLng;
|
||||
import timber.log.Timber;
|
||||
|
||||
/**
|
||||
|
|
@ -69,7 +69,9 @@ public class ImageUtils {
|
|||
public static final int FILE_NAME_EXISTS = -4;
|
||||
static final int NO_CATEGORY_SELECTED = -5;
|
||||
|
||||
private static ProgressDialog progressDialog;
|
||||
private static ProgressDialog progressDialogWallpaper;
|
||||
|
||||
private static ProgressDialog progressDialogAvatar;
|
||||
|
||||
@IntDef(
|
||||
flag = true,
|
||||
|
|
@ -223,28 +225,78 @@ public class ImageUtils {
|
|||
}, CallerThreadExecutor.getInstance());
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the set avatar api to set the image url as user's avatar
|
||||
* @param context
|
||||
* @param url
|
||||
* @param username
|
||||
* @param okHttpJsonApiClient
|
||||
* @param compositeDisposable
|
||||
*/
|
||||
public static void setAvatarFromImageUrl(Context context, String url, String username,
|
||||
OkHttpJsonApiClient okHttpJsonApiClient, CompositeDisposable compositeDisposable) {
|
||||
showSettingAvatarProgressBar(context);
|
||||
|
||||
try {
|
||||
compositeDisposable.add(okHttpJsonApiClient
|
||||
.setAvatar(username, url)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(
|
||||
response -> {
|
||||
if (response != null && response.getStatus().equals("200")) {
|
||||
ViewUtil.showLongToast(context, context.getString(R.string.avatar_set_successfully));
|
||||
if (progressDialogAvatar != null && progressDialogAvatar.isShowing()) {
|
||||
progressDialogAvatar.dismiss();
|
||||
}
|
||||
}
|
||||
},
|
||||
t -> {
|
||||
Timber.e(t, "Setting Avatar Failed");
|
||||
ViewUtil.showLongToast(context, context.getString(R.string.avatar_set_unsuccessfully));
|
||||
if (progressDialogAvatar != null) {
|
||||
progressDialogAvatar.cancel();
|
||||
}
|
||||
}
|
||||
));
|
||||
}
|
||||
catch (Exception e){
|
||||
Timber.d(e+"success");
|
||||
ViewUtil.showLongToast(context, context.getString(R.string.avatar_set_unsuccessfully));
|
||||
if (progressDialogAvatar != null) {
|
||||
progressDialogAvatar.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void setWallpaper(Context context, Bitmap bitmap) {
|
||||
WallpaperManager wallpaperManager = WallpaperManager.getInstance(context);
|
||||
try {
|
||||
wallpaperManager.setBitmap(bitmap);
|
||||
ViewUtil.showLongToast(context, context.getString(R.string.wallpaper_set_successfully));
|
||||
if (progressDialog != null && progressDialog.isShowing()) {
|
||||
progressDialog.dismiss();
|
||||
if (progressDialogWallpaper != null && progressDialogWallpaper.isShowing()) {
|
||||
progressDialogWallpaper.dismiss();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Timber.e(e, "Error setting wallpaper");
|
||||
ViewUtil.showLongToast(context, context.getString(R.string.wallpaper_set_unsuccessfully));
|
||||
if (progressDialog != null) {
|
||||
progressDialog.cancel();
|
||||
if (progressDialogWallpaper != null) {
|
||||
progressDialogWallpaper.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void showSettingWallpaperProgressBar(Context context) {
|
||||
progressDialog = ProgressDialog.show(context, context.getString(R.string.setting_wallpaper_dialog_title),
|
||||
progressDialogWallpaper = ProgressDialog.show(context, context.getString(R.string.setting_wallpaper_dialog_title),
|
||||
context.getString(R.string.setting_wallpaper_dialog_message), true);
|
||||
}
|
||||
|
||||
private static void showSettingAvatarProgressBar(Context context) {
|
||||
progressDialogAvatar = ProgressDialog.show(context, context.getString(R.string.setting_avatar_dialog_title),
|
||||
context.getString(R.string.setting_avatar_dialog_message), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Result variable is a result of an or operation of all possible problems. Ie. if result
|
||||
* is 0001 means IMAGE_DARK
|
||||
|
|
|
|||
|
|
@ -25,5 +25,9 @@
|
|||
android:id="@+id/menu_set_as_wallpaper"
|
||||
android:title="@string/menu_set_wallpaper"
|
||||
app:showAsAction="never" />
|
||||
<item
|
||||
android:id="@+id/menu_set_as_avatar"
|
||||
android:title="@string/menu_set_avatar"
|
||||
app:showAsAction="never" />
|
||||
|
||||
</menu>
|
||||
|
|
@ -656,4 +656,9 @@ Upload your first media by tapping on the add button.</string>
|
|||
<string name="leaderboard_column_rank">Rank</string>
|
||||
<string name="leaderboard_column_user">User</string>
|
||||
<string name="leaderboard_column_count">Count</string>
|
||||
<string name="setting_avatar_dialog_title">Set as Leaderboard Avatar</string>
|
||||
<string name="setting_avatar_dialog_message">Setting as Avatar, please wait</string>
|
||||
<string name="avatar_set_successfully">Avatar Set Successfully</string>
|
||||
<string name="avatar_set_unsuccessfully">Error setting new avatar, please try again</string>
|
||||
<string name="menu_set_avatar">Set as avatar</string>
|
||||
</resources>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue