mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-29 13:53:54 +01:00
Code to retrive unknown notification and UI (#2340)
* request change, changed notification icon * Completed task 1 of the work * commit changes * commit changes * updated notification class * before notification id * gradle reverted * Minor changes to mark notifications as read * commit changes * delete on swipe * notification count * sipe to delete * changes * worked on changes requested * commit changes * Fix notification count * reviewed changes * round icon, swipe with icon * Fix pending NPE issues with notifications * final commit * graddle changes * removed changes for testing
This commit is contained in:
parent
9451b00a15
commit
1b62ac4d2d
22 changed files with 381 additions and 195 deletions
|
|
@ -31,7 +31,6 @@ import android.widget.CheckBox;
|
|||
import android.widget.Toast;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
|
@ -56,7 +55,6 @@ import fr.free.nrw.commons.nearby.NearbyController;
|
|||
import fr.free.nrw.commons.nearby.NearbyNotificationCardView;
|
||||
import fr.free.nrw.commons.nearby.Place;
|
||||
import fr.free.nrw.commons.notification.NotificationController;
|
||||
import fr.free.nrw.commons.notification.UnreadNotificationsCheckAsync;
|
||||
import fr.free.nrw.commons.settings.Prefs;
|
||||
import fr.free.nrw.commons.upload.UploadService;
|
||||
import fr.free.nrw.commons.utils.ConfigUtils;
|
||||
|
|
@ -87,8 +85,7 @@ public class ContributionsFragment
|
|||
@Inject @Named("default_preferences") BasicKvStore defaultKvStore;
|
||||
@Inject ContributionDao contributionDao;
|
||||
@Inject MediaWikiApi mediaWikiApi;
|
||||
@Inject NotificationController notificationController;
|
||||
@Inject NearbyController nearbyController;
|
||||
@Inject NearbyController nearbyController;
|
||||
|
||||
private ArrayList<DataSetObserver> observersWaitingForLoad = new ArrayList<>();
|
||||
private UploadService uploadService;
|
||||
|
|
@ -213,7 +210,6 @@ public class ContributionsFragment
|
|||
if (((MainActivity)getActivity()).isAuthCookieAcquired && !isFragmentAttachedBefore) {
|
||||
onAuthCookieAcquired(((MainActivity)getActivity()).uploadServiceIntent);
|
||||
isFragmentAttachedBefore = true;
|
||||
new UnreadNotificationsCheckAsync((MainActivity) getActivity(), notificationController).execute();
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -478,14 +474,6 @@ public class ContributionsFragment
|
|||
displayUploadCount(betaUploadCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates notification indicator on toolbar to indicate there are unread notifications
|
||||
* @param isThereUnreadNotifications true if user checked notifications before last notification date
|
||||
*/
|
||||
public void updateNotificationsNotification(boolean isThereUnreadNotifications) {
|
||||
((MainActivity)getActivity()).updateNotificationIcon(isThereUnreadNotifications);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package fr.free.nrw.commons.contributions;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
|
|
@ -8,7 +9,6 @@ import android.support.design.widget.TabLayout;
|
|||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.FragmentPagerAdapter;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
|
|
@ -16,6 +16,7 @@ import android.view.MenuInflater;
|
|||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.esafirm.imagepicker.features.ImagePicker;
|
||||
import com.esafirm.imagepicker.model.Image;
|
||||
|
|
@ -35,10 +36,15 @@ import fr.free.nrw.commons.kvstore.BasicKvStore;
|
|||
import fr.free.nrw.commons.location.LocationServiceManager;
|
||||
import fr.free.nrw.commons.nearby.NearbyFragment;
|
||||
import fr.free.nrw.commons.nearby.NearbyNotificationCardView;
|
||||
import fr.free.nrw.commons.notification.Notification;
|
||||
import fr.free.nrw.commons.notification.NotificationActivity;
|
||||
import fr.free.nrw.commons.notification.NotificationController;
|
||||
import fr.free.nrw.commons.upload.UploadService;
|
||||
import fr.free.nrw.commons.utils.ImageUtils;
|
||||
import fr.free.nrw.commons.utils.IntentUtils;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import timber.log.Timber;
|
||||
|
||||
import static android.content.ContentResolver.requestSync;
|
||||
|
|
@ -58,6 +64,8 @@ public class MainActivity extends AuthenticatedActivity implements FragmentManag
|
|||
@Inject
|
||||
@Named("default_preferences")
|
||||
public BasicKvStore defaultKvStore;
|
||||
@Inject
|
||||
NotificationController notificationController;
|
||||
|
||||
|
||||
public Intent uploadServiceIntent;
|
||||
|
|
@ -69,10 +77,12 @@ public class MainActivity extends AuthenticatedActivity implements FragmentManag
|
|||
|
||||
public boolean isContributionsFragmentVisible = true; // False means nearby fragment is visible
|
||||
private Menu menu;
|
||||
private boolean isThereUnreadNotifications = false;
|
||||
|
||||
private boolean onOrientationChanged = false;
|
||||
|
||||
private MenuItem notificationsMenuItem;
|
||||
private TextView notificationCount;
|
||||
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_contributions);
|
||||
|
|
@ -82,6 +92,7 @@ public class MainActivity extends AuthenticatedActivity implements FragmentManag
|
|||
initDrawer();
|
||||
setTitle(getString(R.string.navigation_item_home)); // Should I create a new string variable with another name instead?
|
||||
|
||||
|
||||
if (savedInstanceState != null ) {
|
||||
onOrientationChanged = true; // Will be used in nearby fragment to determine significant update of map
|
||||
|
||||
|
|
@ -126,13 +137,11 @@ public class MainActivity extends AuthenticatedActivity implements FragmentManag
|
|||
tabLayout.getTabAt(1).setCustomView(nearbyTabLinearLayout);
|
||||
|
||||
nearbyInfo.setOnClickListener(view ->
|
||||
new AlertDialog.Builder(MainActivity.this)
|
||||
.setTitle(R.string.title_activity_nearby)
|
||||
.setMessage(R.string.showcase_view_whole_nearby_activity)
|
||||
.setCancelable(true)
|
||||
.setPositiveButton(android.R.string.ok, (dialog, id) -> dialog.cancel())
|
||||
.create()
|
||||
.show()
|
||||
new AlertDialog.Builder(MainActivity.this).setTitle(R.string.title_activity_nearby).setMessage(R.string.showcase_view_whole_nearby_activity)
|
||||
.setCancelable(true)
|
||||
.setPositiveButton(android.R.string.ok, (dialog, id) -> dialog.cancel())
|
||||
.create()
|
||||
.show()
|
||||
);
|
||||
|
||||
if (uploadServiceIntent != null) {
|
||||
|
|
@ -278,20 +287,35 @@ public class MainActivity extends AuthenticatedActivity implements FragmentManag
|
|||
MenuInflater inflater = getMenuInflater();
|
||||
inflater.inflate(R.menu.contribution_activity_notification_menu, menu);
|
||||
|
||||
if (!isThereUnreadNotifications) {
|
||||
// TODO: used vectors are not compatible with API 19 and below, change them
|
||||
menu.findItem(R.id.notifications).setIcon(ContextCompat.getDrawable(this, R.drawable.ic_notification_white_clip_art));
|
||||
} else {
|
||||
menu.findItem(R.id.notifications).setIcon(ContextCompat.getDrawable(this, R.drawable.ic_notification_white_clip_art_dot));
|
||||
}
|
||||
|
||||
notificationsMenuItem = menu.findItem(R.id.notifications);
|
||||
final View notification = notificationsMenuItem.getActionView();
|
||||
notificationCount = notification.findViewById(R.id.notification_count_badge);
|
||||
notification.setOnClickListener(view -> NotificationActivity.startYourself(MainActivity.this));
|
||||
this.menu = menu;
|
||||
|
||||
updateMenuItem();
|
||||
|
||||
setNotificationCount();
|
||||
return true;
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
private void setNotificationCount() {
|
||||
Observable.fromCallable(() -> notificationController.getNotifications())
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(this::initNotificationViews,
|
||||
throwable -> Timber.e(throwable, "Error occurred while loading notifications"));
|
||||
}
|
||||
|
||||
private void initNotificationViews(List<Notification> notificationList) {
|
||||
Timber.d("Number of notifications is %d", notificationList.size());
|
||||
if (notificationList.isEmpty()) {
|
||||
notificationCount.setVisibility(View.GONE);
|
||||
} else {
|
||||
notificationCount.setVisibility(View.VISIBLE);
|
||||
notificationCount.setText(String.valueOf(notificationList.size()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Responsible with displaying required menu items according to displayed fragment.
|
||||
* Notifications icon when contributions list is visible, list sheet icon when nearby is visible
|
||||
|
|
@ -319,7 +343,7 @@ public class MainActivity extends AuthenticatedActivity implements FragmentManag
|
|||
// Starts notification activity on click to notification icon
|
||||
NotificationActivity.startYourself(this);
|
||||
return true;
|
||||
case R.id.list_sheet:
|
||||
case R.id.list_sheet:NotificationActivity.startYourself(this);
|
||||
if (contributionsActivityPagerAdapter.getItem(1) != null) {
|
||||
((NearbyFragment)contributionsActivityPagerAdapter.getItem(1)).listOptionMenuIteClicked();
|
||||
}
|
||||
|
|
@ -335,21 +359,6 @@ public class MainActivity extends AuthenticatedActivity implements FragmentManag
|
|||
pm.hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update notification icon if there is an unread notification
|
||||
* @param isThereUnreadNotifications true if user didn't visit notifications activity since
|
||||
* latest notification came to account
|
||||
*/
|
||||
public void updateNotificationIcon(boolean isThereUnreadNotifications) {
|
||||
if (!isThereUnreadNotifications) {
|
||||
this.isThereUnreadNotifications = false;
|
||||
menu.findItem(R.id.notifications).setIcon(ContextCompat.getDrawable(this, R.drawable.ic_notification_white_clip_art));
|
||||
} else {
|
||||
this.isThereUnreadNotifications = true;
|
||||
menu.findItem(R.id.notifications).setIcon(ContextCompat.getDrawable(this, R.drawable.ic_notification_white_clip_art_dot));
|
||||
}
|
||||
}
|
||||
|
||||
public class ContributionsActivityPagerAdapter extends FragmentPagerAdapter {
|
||||
FragmentManager fragmentManager;
|
||||
private boolean isContributionsListFragment = true; // to know what to put in first tab, Contributions of Media Details
|
||||
|
|
@ -471,7 +480,7 @@ public class MainActivity extends AuthenticatedActivity implements FragmentManag
|
|||
if (!isContributionsFragmentVisible) {
|
||||
viewPager.setCurrentItem(CONTRIBUTIONS_TAB_POSITION);
|
||||
|
||||
// TODO: If contrib fragment is visible and location permission is not given, display permission request button
|
||||
// TODO: If contrib fragment is visible and location permission is not given, display permission request button
|
||||
} else {
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -164,17 +164,6 @@ public class CommonsApplicationModule {
|
|||
return new JsonKvStore(context, "direct_nearby_upload_prefs", gson);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is used to determine when user is viewed notifications activity last
|
||||
* @param context
|
||||
* @return date of lastReadNotificationDate
|
||||
*/
|
||||
@Provides
|
||||
@Named("last_read_notification_date")
|
||||
public BasicKvStore providesLastReadNotificationDateKvStore(Context context) {
|
||||
return new BasicKvStore(context, "last_read_notification_date");
|
||||
}
|
||||
|
||||
@Provides
|
||||
public UploadController providesUploadController(SessionManager sessionManager,
|
||||
@Named("default_preferences") BasicKvStore kvStore,
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ import fr.free.nrw.commons.notification.Notification;
|
|||
import fr.free.nrw.commons.notification.NotificationUtils;
|
||||
import fr.free.nrw.commons.utils.ConfigUtils;
|
||||
import fr.free.nrw.commons.utils.DateUtils;
|
||||
import fr.free.nrw.commons.utils.StringUtils;
|
||||
import fr.free.nrw.commons.utils.ViewUtil;
|
||||
import in.yuvi.http.fluent.Http;
|
||||
import io.reactivex.Observable;
|
||||
|
|
@ -82,7 +83,7 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi {
|
|||
private Gson gson;
|
||||
private final OkHttpClient okHttpClient;
|
||||
private final String WIKIMEDIA_CAMPAIGNS_BASE_URL =
|
||||
"https://raw.githubusercontent.com/commons-app/campaigns/master/campaigns.json";
|
||||
"https://raw.githubusercontent.com/commons-app/campaigns/master/campaigns.json";
|
||||
|
||||
private final String ERROR_CODE_BAD_TOKEN = "badtoken";
|
||||
|
||||
|
|
@ -587,6 +588,7 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi {
|
|||
.param("meta", "notifications")
|
||||
.param("notformat", "model")
|
||||
.param("notwikis", "wikidatawiki|commonswiki|enwiki")
|
||||
.param("notfilter","!read")
|
||||
.get()
|
||||
.getNode("/api/query/notifications/list");
|
||||
} catch (IOException e) {
|
||||
|
|
@ -599,11 +601,26 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi {
|
|||
|| notificationNode.getDocument().getChildNodes().getLength() == 0) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
NodeList childNodes = notificationNode.getDocument().getChildNodes();
|
||||
return NotificationUtils.getNotificationsFromList(context, childNodes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean markNotificationAsRead(Notification notification) throws IOException {
|
||||
Timber.d("Trying to mark notification as read: %s", notification.toString());
|
||||
String result = api.action("echomarkread")
|
||||
.param("token", getEditToken())
|
||||
.param("list", notification.notificationId)
|
||||
.post()
|
||||
.getString("/api/query/echomarkread/@result");
|
||||
|
||||
if (StringUtils.isNullOrWhiteSpace(result)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return result.equals("success");
|
||||
}
|
||||
|
||||
/**
|
||||
* The method takes categoryName as input and returns a List of Subcategories
|
||||
* It uses the generator query API to get the subcategories in a category, 500 at a time.
|
||||
|
|
|
|||
|
|
@ -84,6 +84,9 @@ public interface MediaWikiApi {
|
|||
@NonNull
|
||||
List<Notification> getNotifications() throws IOException;
|
||||
|
||||
@NonNull
|
||||
boolean markNotificationAsRead(Notification notification) throws IOException;
|
||||
|
||||
@NonNull
|
||||
Observable<String> searchTitles(String title, int searchCatsLimit);
|
||||
|
||||
|
|
|
|||
|
|
@ -12,8 +12,9 @@ public class Notification {
|
|||
public String link;
|
||||
public String iconUrl;
|
||||
public String dateWithYear;
|
||||
public String notificationId;
|
||||
|
||||
public Notification(NotificationType notificationType, String notificationText, String date, String description, String link, String iconUrl, String dateWithYear) {
|
||||
public Notification(NotificationType notificationType, String notificationText, String date, String description, String link, String iconUrl, String dateWithYear, String notificationId) {
|
||||
this.notificationType = notificationType;
|
||||
this.notificationText = notificationText;
|
||||
this.date = date;
|
||||
|
|
@ -21,5 +22,20 @@ public class Notification {
|
|||
this.link = link;
|
||||
this.iconUrl = iconUrl;
|
||||
this.dateWithYear = dateWithYear;
|
||||
this.notificationId=notificationId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Notification" +
|
||||
"notificationType='" + notificationType + '\'' +
|
||||
", notificationText='" + notificationText + '\'' +
|
||||
", date='" + date + '\'' +
|
||||
", description='" + description + '\'' +
|
||||
", link='" + link + '\'' +
|
||||
", iconUrl='" + iconUrl + '\'' +
|
||||
", dateWithYear=" + dateWithYear +
|
||||
", notificationId='" + notificationId + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
package fr.free.nrw.commons.notification;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.FragmentManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.support.constraint.ConstraintLayout;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v7.widget.DividerItemDecoration;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
|
|
@ -13,23 +13,19 @@ import android.support.v7.widget.RecyclerView;
|
|||
import android.view.View;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.pedrogomez.renderers.RVRendererAdapter;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import fr.free.nrw.commons.R;
|
||||
import fr.free.nrw.commons.Utils;
|
||||
import fr.free.nrw.commons.contributions.MainActivity;
|
||||
import fr.free.nrw.commons.kvstore.BasicKvStore;
|
||||
import fr.free.nrw.commons.mwapi.MediaWikiApi;
|
||||
import fr.free.nrw.commons.theme.NavigationBaseActivity;
|
||||
import fr.free.nrw.commons.utils.NetworkUtils;
|
||||
import fr.free.nrw.commons.utils.ViewUtil;
|
||||
|
|
@ -44,17 +40,23 @@ import timber.log.Timber;
|
|||
|
||||
public class NotificationActivity extends NavigationBaseActivity {
|
||||
NotificationAdapterFactory notificationAdapterFactory;
|
||||
|
||||
@BindView(R.id.listView) RecyclerView recyclerView;
|
||||
@BindView(R.id.progressBar) ProgressBar progressBar;
|
||||
@BindView(R.id.container) RelativeLayout relativeLayout;
|
||||
|
||||
@Inject NotificationController controller;
|
||||
@Inject MediaWikiApi mediaWikiApi;
|
||||
@Inject @Named("last_read_notification_date") BasicKvStore kvStore;
|
||||
@BindView(R.id.listView)
|
||||
RecyclerView recyclerView;
|
||||
@BindView(R.id.progressBar)
|
||||
ProgressBar progressBar;
|
||||
@BindView(R.id.container)
|
||||
RelativeLayout relativeLayout;
|
||||
@BindView(R.id.no_notification_background)
|
||||
ConstraintLayout no_notification;
|
||||
/* @BindView(R.id.swipe_bg)
|
||||
TextView swipe_bg;*/
|
||||
@Inject
|
||||
NotificationController controller;
|
||||
|
||||
private static final String TAG_NOTIFICATION_WORKER_FRAGMENT = "NotificationWorkerFragment";
|
||||
private NotificationWorkerFragment mNotificationWorkerFragment;
|
||||
private RVRendererAdapter<Notification> adapter;
|
||||
private List<Notification> notificationList;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
|
|
@ -62,11 +64,46 @@ public class NotificationActivity extends NavigationBaseActivity {
|
|||
setContentView(R.layout.activity_notification);
|
||||
ButterKnife.bind(this);
|
||||
mNotificationWorkerFragment = (NotificationWorkerFragment) getFragmentManager()
|
||||
.findFragmentByTag(TAG_NOTIFICATION_WORKER_FRAGMENT);
|
||||
.findFragmentByTag(TAG_NOTIFICATION_WORKER_FRAGMENT);
|
||||
initListView();
|
||||
initDrawer();
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
public void removeNotification(Notification notification) {
|
||||
Observable.fromCallable(() -> controller.markAsRead(notification))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(result -> {
|
||||
if (result){
|
||||
notificationList.remove(notification);
|
||||
setAdapter(notificationList);
|
||||
adapter.notifyDataSetChanged();
|
||||
Snackbar snackbar = Snackbar
|
||||
.make(relativeLayout,"Notification marked as read", Snackbar.LENGTH_LONG);
|
||||
|
||||
snackbar.show();
|
||||
if (notificationList.size()==0){
|
||||
relativeLayout.setVisibility(View.GONE);
|
||||
no_notification.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
else {
|
||||
adapter.notifyDataSetChanged();
|
||||
setAdapter(notificationList);
|
||||
Toast.makeText(NotificationActivity.this, "There was some error!", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}, throwable -> {
|
||||
|
||||
Timber.e(throwable, "Error occurred while loading notifications");
|
||||
throwable.printStackTrace();
|
||||
ViewUtil.showShortSnackbar(relativeLayout, R.string.error_notifications);
|
||||
progressBar.setVisibility(View.GONE);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void initListView() {
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(this));
|
||||
DividerItemDecoration itemDecor = new DividerItemDecoration(recyclerView.getContext(), DividerItemDecoration.VERTICAL);
|
||||
|
|
@ -77,9 +114,9 @@ public class NotificationActivity extends NavigationBaseActivity {
|
|||
private void refresh() {
|
||||
if (!NetworkUtils.isInternetConnectionEstablished(this)) {
|
||||
progressBar.setVisibility(View.GONE);
|
||||
Snackbar.make(relativeLayout , R.string.no_internet, Snackbar.LENGTH_INDEFINITE)
|
||||
Snackbar.make(relativeLayout, R.string.no_internet, Snackbar.LENGTH_INDEFINITE)
|
||||
.setAction(R.string.retry, view -> refresh()).show();
|
||||
}else {
|
||||
} else {
|
||||
progressBar.setVisibility(View.VISIBLE);
|
||||
addNotifications();
|
||||
}
|
||||
|
|
@ -88,13 +125,7 @@ public class NotificationActivity extends NavigationBaseActivity {
|
|||
@SuppressLint("CheckResult")
|
||||
private void addNotifications() {
|
||||
Timber.d("Add notifications");
|
||||
|
||||
// Store when add notification is called last
|
||||
long currentDate = new Date(System.currentTimeMillis()).getTime();
|
||||
kvStore.putLong("last_read_notification_date", currentDate);
|
||||
Timber.d("Set last notification read date to current date:"+ currentDate);
|
||||
|
||||
if(mNotificationWorkerFragment == null){
|
||||
if (mNotificationWorkerFragment == null) {
|
||||
Observable.fromCallable(() -> {
|
||||
progressBar.setVisibility(View.VISIBLE);
|
||||
return controller.getNotifications();
|
||||
|
|
@ -104,7 +135,13 @@ public class NotificationActivity extends NavigationBaseActivity {
|
|||
.subscribe(notificationList -> {
|
||||
Collections.reverse(notificationList);
|
||||
Timber.d("Number of notifications is %d", notificationList.size());
|
||||
setAdapter(notificationList);
|
||||
this.notificationList = notificationList;
|
||||
if (notificationList.size()==0){
|
||||
relativeLayout.setVisibility(View.GONE);
|
||||
no_notification.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
setAdapter(notificationList);
|
||||
}
|
||||
progressBar.setVisibility(View.GONE);
|
||||
}, throwable -> {
|
||||
Timber.e(throwable, "Error occurred while loading notifications");
|
||||
|
|
@ -112,7 +149,8 @@ public class NotificationActivity extends NavigationBaseActivity {
|
|||
progressBar.setVisibility(View.GONE);
|
||||
});
|
||||
} else {
|
||||
setAdapter(mNotificationWorkerFragment.getNotificationList());
|
||||
notificationList = mNotificationWorkerFragment.getNotificationList();
|
||||
setAdapter(notificationList);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -126,13 +164,28 @@ public class NotificationActivity extends NavigationBaseActivity {
|
|||
private void setAdapter(List<Notification> notificationList) {
|
||||
if (notificationList == null || notificationList.isEmpty()) {
|
||||
ViewUtil.showShortSnackbar(relativeLayout, R.string.no_notifications);
|
||||
/*progressBar.setVisibility(View.GONE);
|
||||
recyclerView.setVisibility(View.GONE);*/
|
||||
relativeLayout.setVisibility(View.GONE);
|
||||
no_notification.setVisibility(View.VISIBLE);
|
||||
return;
|
||||
}
|
||||
notificationAdapterFactory = new NotificationAdapterFactory(notification -> {
|
||||
Timber.d("Notification clicked %s", notification.link);
|
||||
handleUrl(notification.link);
|
||||
notificationAdapterFactory = new NotificationAdapterFactory(new NotificationRenderer.NotificationClicked() {
|
||||
@Override
|
||||
public void notificationClicked(Notification notification) {
|
||||
Timber.d("Notification clicked %s", notification.link);
|
||||
handleUrl(notification.link);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markNotificationAsRead(Notification notification) {
|
||||
Timber.d("Notification to mark as read %s", notification.notificationId);
|
||||
removeNotification(notification);
|
||||
}
|
||||
});
|
||||
RVRendererAdapter<Notification> adapter = notificationAdapterFactory.create(notificationList);
|
||||
adapter = notificationAdapterFactory.create(notificationList);
|
||||
relativeLayout.setVisibility(View.VISIBLE);
|
||||
no_notification.setVisibility(View.GONE);
|
||||
recyclerView.setAdapter(adapter);
|
||||
}
|
||||
|
||||
|
|
@ -141,5 +194,4 @@ public class NotificationActivity extends NavigationBaseActivity {
|
|||
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,4 +36,7 @@ public class NotificationController {
|
|||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
public boolean markAsRead(Notification notification) throws IOException{
|
||||
return mediaWikiApi.markNotificationAsRead(notification);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,36 +1,55 @@
|
|||
package fr.free.nrw.commons.notification;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.text.Html;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.nineoldandroids.view.ViewHelper;
|
||||
import com.pedrogomez.renderers.Renderer;
|
||||
|
||||
import com.daimajia.swipe.SwipeLayout;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
import fr.free.nrw.commons.R;
|
||||
import timber.log.Timber;
|
||||
|
||||
/**
|
||||
* Created by root on 19.12.2017.
|
||||
*/
|
||||
|
||||
public class NotificationRenderer extends Renderer<Notification> {
|
||||
@BindView(R.id.title) TextView title;
|
||||
@BindView(R.id.time) TextView time;
|
||||
@BindView(R.id.icon) ImageView icon;
|
||||
@BindView(R.id.title)
|
||||
TextView title;
|
||||
@BindView(R.id.time)
|
||||
TextView time;
|
||||
@BindView(R.id.icon)
|
||||
ImageView icon;
|
||||
@BindView(R.id.swipeLayout)
|
||||
SwipeLayout swipeLayout;
|
||||
@BindView(R.id.bottom)
|
||||
LinearLayout bottomLayout;
|
||||
|
||||
private NotificationClicked listener;
|
||||
|
||||
|
||||
NotificationRenderer(NotificationClicked listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
@OnClick(R.id.bottom)
|
||||
void onBottomLayoutClicked(){
|
||||
Notification notification = getContent();
|
||||
Timber.d("NotificationID: %s", notification.notificationId);
|
||||
listener.markNotificationAsRead(notification);
|
||||
}
|
||||
@Override
|
||||
protected void setUpView(View view) { }
|
||||
protected void setUpView(View rootView) {
|
||||
|
||||
}
|
||||
@Override
|
||||
protected void hookListeners(View rootView) {
|
||||
rootView.setOnClickListener(v -> listener.notificationClicked(getContent()));
|
||||
|
|
@ -40,9 +59,39 @@ public class NotificationRenderer extends Renderer<Notification> {
|
|||
protected View inflate(LayoutInflater layoutInflater, ViewGroup viewGroup) {
|
||||
View inflatedView = layoutInflater.inflate(R.layout.item_notification, viewGroup, false);
|
||||
ButterKnife.bind(this, inflatedView);
|
||||
|
||||
swipeLayout.addDrag(SwipeLayout.DragEdge.Top, bottomLayout);
|
||||
swipeLayout.addRevealListener(R.id.bottom_wrapper_child1, (child, edge, fraction, distance) -> {
|
||||
View star = child.findViewById(R.id.star);
|
||||
float d = child.getHeight() / 2 - star.getHeight() / 2;
|
||||
ViewHelper.setTranslationY(star, d * fraction);
|
||||
ViewHelper.setScaleX(star, fraction + 0.6f);
|
||||
ViewHelper.setScaleY(star, fraction + 0.6f);
|
||||
int c = (Integer) evaluate(fraction, Color.parseColor("#dddddd"), Color.parseColor("#90960a0a"));
|
||||
child.setBackgroundColor(c);
|
||||
});
|
||||
return inflatedView;
|
||||
}
|
||||
|
||||
public Object evaluate(float fraction, Object startValue, Object endValue) {
|
||||
int startInt = (Integer) startValue;
|
||||
int startA = (startInt >> 24) & 0xff;
|
||||
int startR = (startInt >> 16) & 0xff;
|
||||
int startG = (startInt >> 8) & 0xff;
|
||||
int startB = startInt & 0xff;
|
||||
|
||||
int endInt = (Integer) endValue;
|
||||
int endA = (endInt >> 24) & 0xff;
|
||||
int endR = (endInt >> 16) & 0xff;
|
||||
int endG = (endInt >> 8) & 0xff;
|
||||
int endB = endInt & 0xff;
|
||||
|
||||
return (int) ((startA + (int) (fraction * (endA - startA))) << 24) |
|
||||
(int) ((startR + (int) (fraction * (endR - startR))) << 16) |
|
||||
(int) ((startG + (int) (fraction * (endG - startG))) << 8) |
|
||||
(int) ((startB + (int) (fraction * (endB - startB))));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render() {
|
||||
Notification notification = getContent();
|
||||
|
|
@ -53,20 +102,22 @@ public class NotificationRenderer extends Renderer<Notification> {
|
|||
/**
|
||||
* Cleans up the notification text and sets it as the title
|
||||
* Clean up is required to fix escaped HTML string and extra white spaces at the beginning of the notification
|
||||
*
|
||||
* @param notificationText
|
||||
*/
|
||||
private void setTitle(String notificationText) {
|
||||
notificationText = notificationText.trim().replaceAll("(^\\s*)|(\\s*$)", "");
|
||||
notificationText = Html.fromHtml(notificationText).toString();
|
||||
if(notificationText.length()>280){
|
||||
notificationText = notificationText.substring(0,279);
|
||||
if (notificationText.length() > 280) {
|
||||
notificationText = notificationText.substring(0, 279);
|
||||
notificationText = notificationText.concat("...");
|
||||
}
|
||||
notificationText = notificationText.concat(" ");
|
||||
title.setText(notificationText);
|
||||
}
|
||||
|
||||
public interface NotificationClicked{
|
||||
public interface NotificationClicked {
|
||||
void notificationClicked(Notification notification);
|
||||
void markNotificationAsRead(Notification notification);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,6 +74,11 @@ public class NotificationUtils {
|
|||
return NotificationType.handledValueOf(type);
|
||||
}
|
||||
|
||||
public static String getNotificationId(Node document) {
|
||||
Element element = (Element) document;
|
||||
return element.getAttribute("id");
|
||||
}
|
||||
|
||||
public static List<Notification> getNotificationsFromBundle(Context context, Node document) {
|
||||
Element bundledNotifications = getBundledNotifications(document);
|
||||
NodeList childNodes = bundledNotifications.getChildNodes();
|
||||
|
|
@ -154,7 +159,8 @@ public class NotificationUtils {
|
|||
notificationText = getWelcomeMessage(context, document);
|
||||
break;
|
||||
}
|
||||
return new Notification(type, notificationText, getTimestamp(document), description, link, iconUrl, getTimestampWithYear(document));
|
||||
return new Notification(type, notificationText, getTimestamp(document), description, link, iconUrl, getTimestampWithYear(document),
|
||||
getNotificationId(document));
|
||||
}
|
||||
|
||||
private static String getNotificationText(Node document) {
|
||||
|
|
|
|||
|
|
@ -1,81 +0,0 @@
|
|||
package fr.free.nrw.commons.notification;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import fr.free.nrw.commons.contributions.MainActivity;
|
||||
import fr.free.nrw.commons.contributions.ContributionsFragment;
|
||||
import timber.log.Timber;
|
||||
|
||||
/**
|
||||
* This asynctask will check unread notifications after a date (date user check notifications last)
|
||||
*/
|
||||
|
||||
public class UnreadNotificationsCheckAsync extends AsyncTask<Void, Void, Notification> {
|
||||
|
||||
WeakReference<MainActivity> context;
|
||||
NotificationController notificationController;
|
||||
|
||||
|
||||
public UnreadNotificationsCheckAsync(MainActivity context, NotificationController notificationController) {
|
||||
this.context = new WeakReference<>(context);
|
||||
this.notificationController = notificationController;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Notification doInBackground(Void... voids) {
|
||||
Notification lastNotification = null;
|
||||
|
||||
try {
|
||||
lastNotification = findLastNotification(notificationController.getNotifications());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return lastNotification;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Notification lastNotification) {
|
||||
super.onPostExecute(lastNotification);
|
||||
|
||||
if (lastNotification == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Date lastNotificationCheckDate = new Date(context.get()
|
||||
.getSharedPreferences("defaultKvStore",0)
|
||||
.getLong("last_read_notification_date", 0));
|
||||
Timber.d("You may have unread notifications since"+lastNotificationCheckDate);
|
||||
|
||||
boolean isThereUnreadNotifications;
|
||||
|
||||
Date lastReadNotificationDate = new java.util.Date(Long.parseLong(lastNotification.dateWithYear)*1000);
|
||||
|
||||
if (lastNotificationCheckDate.before(lastReadNotificationDate)) {
|
||||
isThereUnreadNotifications = true;
|
||||
} else {
|
||||
isThereUnreadNotifications = false;
|
||||
}
|
||||
|
||||
// Check if activity is still running
|
||||
if (context.get().getWindow().getDecorView().isShown() && !context.get().isFinishing()) {
|
||||
// Check if fragment is not null and visible
|
||||
if (context.get().isContributionsFragmentVisible && context.get().contributionsActivityPagerAdapter.getItem(0) != null) {
|
||||
((ContributionsFragment)(context.get().contributionsActivityPagerAdapter.getItem(0))).updateNotificationsNotification(isThereUnreadNotifications);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Notification findLastNotification(List<Notification> allNotifications) {
|
||||
if (allNotifications.size() > 0) {
|
||||
return allNotifications.get(allNotifications.size()-1);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue