mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-28 21:33:53 +01:00
Show campaigns (#2113)
* Show campaigns * Added a ui util class SwipableCardView which passes the onSwipe event to its children * NearbyCardView & CampaignView extend SwipableCardView * Fetch campaigns in ContributionsFragment * Added an option to enable disable campaign in Settings/Preferences * synced strings with master * removed duplicate initialsation of CampaignPresenter
This commit is contained in:
parent
707c52c768
commit
1b01c6517f
22 changed files with 608 additions and 47 deletions
|
|
@ -0,0 +1,55 @@
|
|||
package fr.free.nrw.commons.campaigns;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* A data class to hold a campaign
|
||||
*/
|
||||
public class Campaign {
|
||||
|
||||
@SerializedName("title") private String title;
|
||||
@SerializedName("description") private String description;
|
||||
@SerializedName("startDate") private String startDate;
|
||||
@SerializedName("endDate") private String endDate;
|
||||
@SerializedName("link") private String link;
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getStartDate() {
|
||||
return startDate;
|
||||
}
|
||||
|
||||
public void setStartDate(String startDate) {
|
||||
this.startDate = startDate;
|
||||
}
|
||||
|
||||
public String getEndDate() {
|
||||
return endDate;
|
||||
}
|
||||
|
||||
public void setEndDate(String endDate) {
|
||||
this.endDate = endDate;
|
||||
}
|
||||
|
||||
public String getLink() {
|
||||
return link;
|
||||
}
|
||||
|
||||
public void setLink(String link) {
|
||||
this.link = link;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package fr.free.nrw.commons.campaigns;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* A data class to hold the campaign configs
|
||||
*/
|
||||
class CampaignConfig {
|
||||
|
||||
@SerializedName("showOnlyLiveCampaigns") private boolean showOnlyLiveCampaigns;
|
||||
@SerializedName("sortBy") private String sortBy;
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
package fr.free.nrw.commons.campaigns;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Data class to hold the response from the campaigns api
|
||||
*/
|
||||
public class CampaignResponseDTO {
|
||||
|
||||
@SerializedName("config")
|
||||
private CampaignConfig campaignConfig;
|
||||
|
||||
@SerializedName("campaigns")
|
||||
private List<Campaign> campaigns;
|
||||
|
||||
public CampaignConfig getCampaignConfig() {
|
||||
return campaignConfig;
|
||||
}
|
||||
|
||||
public List<Campaign> getCampaigns() {
|
||||
return campaigns;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
package fr.free.nrw.commons.campaigns;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import fr.free.nrw.commons.R;
|
||||
import fr.free.nrw.commons.contributions.MainActivity;
|
||||
import fr.free.nrw.commons.utils.SwipableCardView;
|
||||
import fr.free.nrw.commons.utils.ViewUtil;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* A view which represents a single campaign
|
||||
*/
|
||||
public class CampaignView extends SwipableCardView {
|
||||
Campaign campaign = null;
|
||||
private ViewHolder viewHolder;
|
||||
|
||||
public CampaignView(@NonNull Context context) {
|
||||
super(context);
|
||||
init();
|
||||
}
|
||||
|
||||
public CampaignView(@NonNull Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init();
|
||||
}
|
||||
|
||||
public CampaignView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
init();
|
||||
}
|
||||
|
||||
public void setCampaign(Campaign campaign) {
|
||||
this.campaign = campaign;
|
||||
if (campaign != null) {
|
||||
this.setVisibility(View.VISIBLE);
|
||||
viewHolder.init();
|
||||
} else {
|
||||
this.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override public boolean onSwipe(View view) {
|
||||
view.setVisibility(View.GONE);
|
||||
((MainActivity) getContext()).prefs.edit()
|
||||
.putBoolean("displayCampaignsCardView", false)
|
||||
.apply();
|
||||
ViewUtil.showLongToast(getContext(),
|
||||
getResources().getString(R.string.nearby_campaign_dismiss_message));
|
||||
return true;
|
||||
}
|
||||
|
||||
private void init() {
|
||||
View rootView = inflate(getContext(), R.layout.layout_campagin, this);
|
||||
viewHolder = new ViewHolder(rootView);
|
||||
setOnClickListener(view -> {
|
||||
if (campaign != null) {
|
||||
showCampaignInBrowser(campaign.getLink());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* open the url associated with the campaign in the system's default browser
|
||||
*/
|
||||
private void showCampaignInBrowser(String link) {
|
||||
Intent view = new Intent();
|
||||
view.setAction(Intent.ACTION_VIEW);
|
||||
view.setData(Uri.parse(link));
|
||||
getContext().startActivity(view);
|
||||
}
|
||||
|
||||
public class ViewHolder {
|
||||
|
||||
@BindView(R.id.tv_title) TextView tvTitle;
|
||||
@BindView(R.id.tv_description) TextView tvDescription;
|
||||
@BindView(R.id.tv_dates) TextView tvDates;
|
||||
|
||||
public ViewHolder(View itemView) {
|
||||
ButterKnife.bind(this, itemView);
|
||||
}
|
||||
|
||||
public void init() {
|
||||
if (campaign != null) {
|
||||
tvTitle.setText(campaign.getTitle());
|
||||
tvDescription.setText(campaign.getDescription());
|
||||
SimpleDateFormat inputDateFormat = new SimpleDateFormat("yyyy-MM-dd");
|
||||
SimpleDateFormat outputDateFormat = new SimpleDateFormat("dd MMM");
|
||||
try {
|
||||
Date startDate = inputDateFormat.parse(campaign.getStartDate());
|
||||
Date endDate = inputDateFormat.parse(campaign.getEndDate());
|
||||
tvDates.setText(String.format("%1s - %2s", outputDateFormat.format(startDate),
|
||||
outputDateFormat.format(endDate)));
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
package fr.free.nrw.commons.campaigns;
|
||||
|
||||
import android.util.Log;
|
||||
import fr.free.nrw.commons.BasePresenter;
|
||||
import fr.free.nrw.commons.MvpView;
|
||||
import fr.free.nrw.commons.mwapi.MediaWikiApi;
|
||||
import io.reactivex.Single;
|
||||
import io.reactivex.SingleObserver;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.disposables.Disposable;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The presenter for the campaigns view, fetches the campaigns from the api and informs the view on
|
||||
* success and error
|
||||
*/
|
||||
public class CampaignsPresenter implements BasePresenter {
|
||||
private final String TAG = "#CampaignsPresenter#";
|
||||
private ICampaignsView view;
|
||||
private MediaWikiApi mediaWikiApi;
|
||||
private Disposable disposable;
|
||||
private Campaign campaign;
|
||||
|
||||
@Override public void onAttachView(MvpView view) {
|
||||
this.view = (ICampaignsView) view;
|
||||
this.mediaWikiApi = ((ICampaignsView) view).getMediaWikiApi();
|
||||
}
|
||||
|
||||
@Override public void onDetachView() {
|
||||
this.view = null;
|
||||
disposable.dispose();
|
||||
}
|
||||
|
||||
/**
|
||||
* make the api call to fetch the campaigns
|
||||
*/
|
||||
public void getCampaigns() {
|
||||
if (view != null && mediaWikiApi != null) {
|
||||
//If we already have a campaign, lets not make another call
|
||||
if (this.campaign != null) {
|
||||
view.showCampaigns(campaign);
|
||||
return;
|
||||
}
|
||||
Single<CampaignResponseDTO> campaigns = mediaWikiApi.getCampaigns();
|
||||
campaigns.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribeWith(new SingleObserver<CampaignResponseDTO>() {
|
||||
|
||||
@Override public void onSubscribe(Disposable d) {
|
||||
disposable = d;
|
||||
}
|
||||
|
||||
@Override public void onSuccess(CampaignResponseDTO campaignResponseDTO) {
|
||||
List<Campaign> campaigns = campaignResponseDTO.getCampaigns();
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
|
||||
if (campaigns == null || campaigns.isEmpty()) {
|
||||
Log.e(TAG, "The campaigns list is empty");
|
||||
view.showCampaigns(null);
|
||||
}
|
||||
Collections.sort(campaigns, (campaign, t1) -> {
|
||||
Date date1, date2;
|
||||
try {
|
||||
date1 = dateFormat.parse(campaign.getStartDate());
|
||||
date2 = dateFormat.parse(t1.getStartDate());
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
return -1;
|
||||
}
|
||||
return date1.compareTo(date2);
|
||||
});
|
||||
Date campaignEndDate = null;
|
||||
try {
|
||||
campaignEndDate = dateFormat.parse(campaigns.get(0).getEndDate());
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (campaignEndDate == null) {
|
||||
view.showCampaigns(null);
|
||||
} else if (campaignEndDate.compareTo(new Date()) > 0) {
|
||||
campaign = campaigns.get(0);
|
||||
view.showCampaigns(campaign);
|
||||
} else {
|
||||
Log.e(TAG, "The campaigns has already finished");
|
||||
view.showCampaigns(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void onError(Throwable e) {
|
||||
Log.e(TAG, "could not fetch campaigns: " + e.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
package fr.free.nrw.commons.campaigns;
|
||||
|
||||
import fr.free.nrw.commons.MvpView;
|
||||
import fr.free.nrw.commons.mwapi.MediaWikiApi;
|
||||
|
||||
/**
|
||||
* Interface which defines the view contracts of the campaign view
|
||||
*/
|
||||
public interface ICampaignsView extends MvpView {
|
||||
MediaWikiApi getMediaWikiApi();
|
||||
|
||||
void showCampaigns(Campaign campaign);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue