diff --git a/app/src/main/java/com/etesync/syncadapter/NotificationHelper.java b/app/src/main/java/com/etesync/syncadapter/NotificationHelper.java
index 3c708a5c..327df9b8 100644
--- a/app/src/main/java/com/etesync/syncadapter/NotificationHelper.java
+++ b/app/src/main/java/com/etesync/syncadapter/NotificationHelper.java
@@ -30,6 +30,8 @@ public class NotificationHelper {
Intent detailsIntent;
int messageString;
+ private Throwable throwable = null;
+
public NotificationHelper(Context context, String notificationTag, int notificationId) {
this.notificationManager = NotificationManagerCompat.from(context);
this.context = context;
@@ -38,6 +40,7 @@ public class NotificationHelper {
}
public void setThrowable(Throwable e) {
+ throwable = e;
if (e instanceof Exceptions.UnauthorizedException) {
App.log.log(Level.SEVERE, "Not authorized anymore", e);
messageString = R.string.sync_error_unauthorized;
@@ -68,18 +71,39 @@ public class NotificationHelper {
public void notify(String title, String state) {
String message = context.getString(messageString, state);
+ notify(title, message, null, detailsIntent);
+ }
+ public void notify(String title, String content, String bigText, Intent intent) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
- builder.setSmallIcon(R.drawable.ic_error_light)
- .setLargeIcon(App.getLauncherBitmap(context))
+ int icon;
+ String category;
+ String tag;
+ //Check if error was configured
+ if (throwable == null) {
+ icon = R.drawable.ic_sync_dark;
+ category = NotificationCompat.CATEGORY_STATUS;
+ } else {
+ icon = R.drawable.ic_error_light;
+ category = NotificationCompat.CATEGORY_ERROR;
+ }
+
+ builder.setLargeIcon(App.getLauncherBitmap(context))
.setContentTitle(title)
- .setContentIntent(PendingIntent.getActivity(context, 0, detailsIntent, PendingIntent.FLAG_CANCEL_CURRENT))
- .setCategory(NotificationCompat.CATEGORY_ERROR)
- .setContentText(message);
+ .setContentText(content)
+ .setAutoCancel(true)
+ .setCategory(category)
+ .setSmallIcon(icon)
+ .setContentIntent(PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT))
+ ;
+
+ if (bigText != null) builder.setStyle(new NotificationCompat.BigTextStyle()
+ .bigText(bigText));
notificationManager.notify(notificationTag, notificationId, builder.build());
}
+
public void cancel() {
notificationManager.cancel(notificationTag, notificationId);
}
diff --git a/app/src/main/java/com/etesync/syncadapter/syncadapter/CalendarSyncManager.java b/app/src/main/java/com/etesync/syncadapter/syncadapter/CalendarSyncManager.java
index 9b3c4183..a793c022 100644
--- a/app/src/main/java/com/etesync/syncadapter/syncadapter/CalendarSyncManager.java
+++ b/app/src/main/java/com/etesync/syncadapter/syncadapter/CalendarSyncManager.java
@@ -59,6 +59,12 @@ public class CalendarSyncManager extends SyncManager {
return context.getString(R.string.sync_error_calendar, account.name);
}
+ @Override
+ protected String getSyncSuccessfullyTitle() {
+ return context.getString(R.string.sync_successfully_calendar, info.displayName,
+ account.name);
+ }
+
@Override
protected boolean prepare() throws ContactsStorageException, CalendarStorageException {
if (!super.prepare())
diff --git a/app/src/main/java/com/etesync/syncadapter/syncadapter/ContactsSyncManager.java b/app/src/main/java/com/etesync/syncadapter/syncadapter/ContactsSyncManager.java
index e49c36cf..392a9961 100644
--- a/app/src/main/java/com/etesync/syncadapter/syncadapter/ContactsSyncManager.java
+++ b/app/src/main/java/com/etesync/syncadapter/syncadapter/ContactsSyncManager.java
@@ -82,6 +82,11 @@ public class ContactsSyncManager extends SyncManager {
return context.getString(R.string.sync_error_contacts, account.name);
}
+ @Override
+ protected String getSyncSuccessfullyTitle() {
+ return context.getString(R.string.sync_successfully_contacts, account.name);
+ }
+
@Override
protected boolean prepare() throws ContactsStorageException, CalendarStorageException {
if (!super.prepare())
diff --git a/app/src/main/java/com/etesync/syncadapter/syncadapter/SyncManager.java b/app/src/main/java/com/etesync/syncadapter/syncadapter/SyncManager.java
index e9042699..9803fa96 100644
--- a/app/src/main/java/com/etesync/syncadapter/syncadapter/SyncManager.java
+++ b/app/src/main/java/com/etesync/syncadapter/syncadapter/SyncManager.java
@@ -12,6 +12,7 @@ import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
import android.content.SyncResult;
+import android.content.res.Resources;
import android.os.Bundle;
import com.etesync.syncadapter.AccountSettings;
@@ -32,6 +33,7 @@ import com.etesync.syncadapter.model.SyncEntry;
import com.etesync.syncadapter.resource.LocalCollection;
import com.etesync.syncadapter.resource.LocalResource;
import com.etesync.syncadapter.ui.DebugInfoActivity;
+import com.etesync.syncadapter.ui.ViewCollectionActivity;
import org.apache.commons.collections4.ListUtils;
@@ -51,6 +53,7 @@ import io.requery.sql.EntityDataStore;
import okhttp3.OkHttpClient;
import static com.etesync.syncadapter.Constants.KEY_ACCOUNT;
+import static com.etesync.syncadapter.model.SyncEntry.Actions.ADD;
abstract public class SyncManager {
private static final int MAX_FETCH = 50;
@@ -132,6 +135,8 @@ abstract public class SyncManager {
protected abstract String getSyncErrorTitle();
+ protected abstract String getSyncSuccessfullyTitle();
+
@TargetApi(21)
public void performSync() {
int syncPhase = R.string.sync_phase_prepare;
@@ -194,6 +199,8 @@ abstract public class SyncManager {
App.log.info("Sync phase: " + context.getString(syncPhase));
postProcess();
+ notifyUserOnSync();
+
App.log.info("Finished sync with CTag=" + remoteCTag);
} catch (IOException e) {
App.log.log(Level.WARNING, "I/O exception during sync, trying again later", e);
@@ -230,6 +237,47 @@ abstract public class SyncManager {
}
}
+ private void notifyUserOnSync() {
+ if (remoteEntries.isEmpty()) {
+ return;
+ }
+ NotificationHelper notificationHelper = new NotificationHelper(context,
+ String.valueOf(System.currentTimeMillis()), notificationId());
+
+ int deleted = 0;
+ int added = 0;
+ int changed = 0;
+ for (JournalEntryManager.Entry entry : remoteEntries) {
+ SyncEntry cEntry = SyncEntry.fromJournalEntry(crypto, entry);
+ SyncEntry.Actions action = cEntry.getAction();
+ switch (action) {
+ case ADD:
+ added++;
+ break;
+ case DELETE:
+ deleted++;
+ break;
+ case CHANGE:
+ changed++;
+ break;
+ }
+ }
+
+ Resources resources = context.getResources();
+ Intent intent = ViewCollectionActivity.newIntent(context, account, info);
+ notificationHelper.notify(getSyncSuccessfullyTitle(),
+ String.format(context.getString(R.string.sync_successfully_modified),
+ resources.getQuantityString(R.plurals.sync_successfully,
+ remoteEntries.size(), remoteEntries.size())),
+ String.format(context.getString(R.string.sync_successfully_modified_full),
+ resources.getQuantityString(R.plurals.sync_successfully,
+ added, added),
+ resources.getQuantityString(R.plurals.sync_successfully,
+ changed, changed),
+ resources.getQuantityString(R.plurals.sync_successfully,
+ deleted, deleted)),
+ intent);
+ }
/**
* Prepares synchronization (for instance, allocates necessary resources).
@@ -386,7 +434,7 @@ abstract public class SyncManager {
for (LocalResource local : localDirty) {
SyncEntry.Actions action;
if (local.isLocalOnly()) {
- action = SyncEntry.Actions.ADD;
+ action = ADD;
} else {
action = SyncEntry.Actions.CHANGE;
}
diff --git a/app/src/main/res/values/plurals.xml b/app/src/main/res/values/plurals.xml
new file mode 100644
index 00000000..8549eacc
--- /dev/null
+++ b/app/src/main/res/values/plurals.xml
@@ -0,0 +1,7 @@
+
+
+
+ - %d entry
+ - %d entries
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index b18eb510..0d3fd53c 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -303,6 +303,10 @@
post processing
Authentication failed
User is inactive
+ Calendar \"%s\" modified (%s)
+ Contacts modified (%s)
+ %s modified.
+ %s added.\n%s updated.\n%s deleted.
EteSync: Connection security