-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Show campaigns on home screen #2108
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
ashishkumar468
wants to merge
7
commits into
commons-app:2.9-release
from
ashishkumar468:feature/campaigns
Closed
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
e94fa5f
Show campaigns on home screen
ashishkumar468 3cfdc45
added click listener to a campaign
ashishkumar468 6d44a03
* Added JavaDocs
ashishkumar468 eb3a3df
* ui fixes
ashishkumar468 fe49334
removed unused constant
ashishkumar468 3da6417
ui fixes, description for a campaign is temporarily hidden
ashishkumar468 6eb0701
updated campaigns base url, switched to the prod url
ashishkumar468 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package fr.free.nrw.commons; | ||
|
||
/** | ||
* Base presenter, enforcing contracts to atach and detach view | ||
*/ | ||
public interface BasePresenter { | ||
/** | ||
* Until a view is attached, it is open to listen events from the presenter | ||
*/ | ||
void onAttachView(MvpView view); | ||
|
||
/** | ||
* Detaching a view makes sure that the view no more receives events from the presenter | ||
*/ | ||
void onDetachView(); | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package fr.free.nrw.commons; | ||
|
||
/** | ||
* Base interface for all the views | ||
*/ | ||
public interface MvpView { | ||
void showMessage(String message); | ||
} |
55 changes: 55 additions & 0 deletions
55
app/src/main/java/fr/free/nrw/commons/campaigns/Campaign.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
app/src/main/java/fr/free/nrw/commons/campaigns/CampaignConfig.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} |
24 changes: 24 additions & 0 deletions
24
app/src/main/java/fr/free/nrw/commons/campaigns/CampaignResponseDTO.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} | ||
} |
110 changes: 110 additions & 0 deletions
110
app/src/main/java/fr/free/nrw/commons/campaigns/CampaignView.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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(); | ||
} | ||
} | ||
} | ||
} | ||
} |
99 changes: 99 additions & 0 deletions
99
app/src/main/java/fr/free/nrw/commons/campaigns/CampaignsPresenter.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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()); | ||
} | ||
}); | ||
} | ||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
app/src/main/java/fr/free/nrw/commons/campaigns/ICampaignsView.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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); | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add Javadocs for all the new classes and methods. :) I guess there isn't really a need to have them for every single getter and setter method in this particular class (since they are fairly self-explanatory), but there should still at least be a Javadoc for the class itself. And the methods in the other classes would need them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes I was gonna, have added a lot of classes :P, will do it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done