1
0
mirror of https://github.com/etesync/android synced 2025-02-02 19:01:06 +00:00

Add invite attendees notification for new and modified calendar events

This commit is contained in:
tal 2018-08-18 11:37:11 +03:00 committed by Tom Hacohen
parent 20feee0df7
commit cb54e51280
4 changed files with 149 additions and 15 deletions

View File

@ -82,17 +82,22 @@ public class NotificationHelper {
} }
public void notify(String title, String content, String bigText, Intent intent) { public void notify(String title, String content, String bigText, Intent intent) {
notify(title, content, bigText, intent, -1);
}
public void notify(String title, String content, String bigText, Intent intent, int icon) {
createNotificationChannel(); createNotificationChannel();
NotificationCompat.Builder builder = new NotificationCompat.Builder(context); NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
int icon; String category =
String category; throwable == null ?
//Check if error was configured NotificationCompat.CATEGORY_STATUS : NotificationCompat.CATEGORY_ERROR;
if (throwable == null) { if (icon == -1) {
icon = R.drawable.ic_sync_dark; //Check if error was configured
category = NotificationCompat.CATEGORY_STATUS; if (throwable == null) {
} else { icon = R.drawable.ic_sync_dark;
icon = R.drawable.ic_error_light; } else {
category = NotificationCompat.CATEGORY_ERROR; icon = R.drawable.ic_error_light;
}
} }
builder.setLargeIcon(App.getLauncherBitmap(context)) builder.setLargeIcon(App.getLauncherBitmap(context))

View File

@ -10,12 +10,16 @@ package com.etesync.syncadapter.syncadapter;
import android.accounts.Account; import android.accounts.Account;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.content.SyncResult; import android.content.SyncResult;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import com.etesync.syncadapter.AccountSettings; import com.etesync.syncadapter.AccountSettings;
import com.etesync.syncadapter.App; import com.etesync.syncadapter.App;
import com.etesync.syncadapter.Constants; import com.etesync.syncadapter.Constants;
import com.etesync.syncadapter.NotificationHelper;
import com.etesync.syncadapter.R; import com.etesync.syncadapter.R;
import com.etesync.syncadapter.journalmanager.Exceptions; import com.etesync.syncadapter.journalmanager.Exceptions;
import com.etesync.syncadapter.journalmanager.JournalEntryManager; import com.etesync.syncadapter.journalmanager.JournalEntryManager;
@ -25,11 +29,23 @@ import com.etesync.syncadapter.resource.LocalCalendar;
import com.etesync.syncadapter.resource.LocalEvent; import com.etesync.syncadapter.resource.LocalEvent;
import com.etesync.syncadapter.resource.LocalResource; import com.etesync.syncadapter.resource.LocalResource;
import net.fortuna.ical4j.model.property.Attendee;
import org.acra.attachment.AcraContentProvider;
import org.acra.util.IOUtils;
import org.apache.commons.codec.Charsets; import org.apache.commons.codec.Charsets;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import at.bitfire.ical4android.CalendarStorageException; import at.bitfire.ical4android.CalendarStorageException;
import at.bitfire.ical4android.Event; import at.bitfire.ical4android.Event;
@ -61,8 +77,8 @@ public class CalendarSyncManager extends SyncManager {
@Override @Override
protected String getSyncSuccessfullyTitle() { protected String getSyncSuccessfullyTitle() {
return context.getString(R.string.sync_successfully_calendar, info.displayName, return context.getString(R.string.sync_successfully_calendar, info.displayName,
account.name); account.name);
} }
@Override @Override
@ -95,8 +111,9 @@ public class CalendarSyncManager extends SyncManager {
if (events.length == 0) { if (events.length == 0) {
App.log.warning("Received VCard without data, ignoring"); App.log.warning("Received VCard without data, ignoring");
return; return;
} else if (events.length > 1) } else if (events.length > 1) {
App.log.warning("Received multiple VCALs, using first one"); App.log.warning("Received multiple VCALs, using first one");
}
Event event = events[0]; Event event = events[0];
LocalEvent local = (LocalEvent) localCollection.getByUid(event.uid); LocalEvent local = (LocalEvent) localCollection.getByUid(event.uid);
@ -113,6 +130,57 @@ public class CalendarSyncManager extends SyncManager {
} }
} }
protected void createLocalEntries() throws CalendarStorageException, ContactsStorageException, IOException {
super.createLocalEntries();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
createInviteAttendeesNotification();
}
}
private void createInviteAttendeesNotification() throws CalendarStorageException, ContactsStorageException, IOException {
for (LocalResource local : localDirty) {
Event event = ((LocalEvent) local).getEvent();
if (event.attendees.isEmpty()) {
return;
}
createInviteAttendeesNotification(event, local.getContent());
}
}
private void createInviteAttendeesNotification(Event event, String icsContent) {
NotificationHelper notificationHelper = new NotificationHelper(context, event.uid, event.uid.hashCode());
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_EMAIL, getEmailAddresses(event.attendees ,false));
final DateFormat dateFormatDate =
new SimpleDateFormat("EEEE, MMM dd", Locale.US);
intent.putExtra(Intent.EXTRA_SUBJECT,
context.getString(R.string.sync_calendar_attendees_email_subject,
event.summary,
dateFormatDate.format(event.dtStart.getDate())));
intent.putExtra(Intent.EXTRA_TEXT,
context.getString(R.string.sync_calendar_attendees_email_content,
event.summary,
formatEventDates(event),
formatAttendees(event.attendees)));
Uri uri = createAttachmentFromString(context, event.uid, icsContent);
if (uri == null) {
App.log.severe("Unable to create attachment from calendar event");
return;
}
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.putExtra(Intent.EXTRA_STREAM, uri);
notificationHelper.notify(
context.getString(
R.string.sync_calendar_attendees_notification_title, event.summary),
context.getString(R.string.sync_calendar_attendees_notification_content),
null,
intent,
R.drawable.ic_email_black);
}
private LocalResource processEvent(final Event newData, LocalEvent localEvent) throws IOException, ContactsStorageException, CalendarStorageException { private LocalResource processEvent(final Event newData, LocalEvent localEvent) throws IOException, ContactsStorageException, CalendarStorageException {
// delete local event, if it exists // delete local event, if it exists
if (localEvent != null) { if (localEvent != null) {
@ -129,4 +197,63 @@ public class CalendarSyncManager extends SyncManager {
return localEvent; return localEvent;
} }
private String[] getEmailAddresses(List<Attendee> attendees,
boolean shouldIncludeAccount) {
List<String> attendeesEmails = new ArrayList<>(attendees.size());
for (Attendee attendee : attendees) {
String attendeeEmail = attendee.getValue().replace("mailto:", "");
if (!shouldIncludeAccount && attendeeEmail.equals(account.name)) {
continue;
}
attendeesEmails.add(attendeeEmail);
}
return attendeesEmails.toArray(new String[0]);
}
private String formatAttendees(List<Attendee> attendeesList) {
StringBuilder stringBuilder = new StringBuilder();
String[] attendees = getEmailAddresses(attendeesList, true);
for (String attendee : attendees) {
stringBuilder.append("\n ").append(attendee);
}
return stringBuilder.toString();
}
private static String formatEventDates(Event event) {
final String dateFormatString =
event.isAllDay() ? "EEEE, MMM dd" : "EEEE, MMM dd @ hh:mm a";
final DateFormat dateFormat =
new SimpleDateFormat(dateFormatString,
Locale.US);
Date startDate = event.dtStart.getDate();
Date endDate = event.dtEnd.getDate();
Calendar cal1 = Calendar.getInstance();
Calendar cal2 = Calendar.getInstance();
cal1.setTime(startDate);
cal2.setTime(endDate);
boolean sameDay = cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) &&
cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR);
if (sameDay && event.isAllDay()) {
return dateFormat.format(startDate);
}
return sameDay ?
String.format("%s - %s",
dateFormat.format(startDate),
new SimpleDateFormat("hh:mm a", Locale.US).format(endDate)) :
String.format("%s - %s", dateFormat.format(startDate), dateFormat.format(endDate));
}
private Uri createAttachmentFromString(Context context, String name, String content) {
final File parentDir = new File (context.getCacheDir(), name);
parentDir.mkdirs();
final File cache = new File(parentDir, "invite.ics");
try {
IOUtils.writeStringToFile(cache, content);
return AcraContentProvider.getUriForFile(context, cache);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
} }

View File

@ -35,8 +35,6 @@ import com.etesync.syncadapter.resource.LocalResource;
import com.etesync.syncadapter.ui.DebugInfoActivity; import com.etesync.syncadapter.ui.DebugInfoActivity;
import com.etesync.syncadapter.ui.ViewCollectionActivity; import com.etesync.syncadapter.ui.ViewCollectionActivity;
import org.apache.commons.collections4.ListUtils;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
@ -101,7 +99,7 @@ abstract public class SyncManager {
* Dirty and deleted resources. We need to save them so we safely ignore ones that were added after we started. * Dirty and deleted resources. We need to save them so we safely ignore ones that were added after we started.
*/ */
private List<LocalResource> localDeleted; private List<LocalResource> localDeleted;
private LocalResource[] localDirty; protected LocalResource[] localDirty;
public SyncManager(Context context, Account account, AccountSettings settings, Bundle extras, String authority, SyncResult syncResult, String journalUid, CollectionInfo.Type serviceType, String accountName) throws Exceptions.IntegrityException, Exceptions.GenericCryptoException { public SyncManager(Context context, Account account, AccountSettings settings, Bundle extras, String authority, SyncResult syncResult, String journalUid, CollectionInfo.Type serviceType, String accountName) throws Exceptions.IntegrityException, Exceptions.GenericCryptoException {
this.context = context; this.context = context;

View File

@ -322,6 +322,10 @@
<string name="sync_successfully_contacts" formatted="false">Contacts modified (%s)</string> <string name="sync_successfully_contacts" formatted="false">Contacts modified (%s)</string>
<string name="sync_successfully_modified" formatted="false">%s modified.</string> <string name="sync_successfully_modified" formatted="false">%s modified.</string>
<string name="sync_successfully_modified_full" formatted="false">%s added.\n%s updated.\n%s deleted.</string> <string name="sync_successfully_modified_full" formatted="false">%s added.\n%s updated.\n%s deleted.</string>
<string name="sync_calendar_attendees_notification_title" formatted="false">%s</string>
<string name="sync_calendar_attendees_notification_content">Send invitations to guests?</string>
<string name="sync_calendar_attendees_email_subject" formatted="false">Invitation: %s @ %s</string>
<string name="sync_calendar_attendees_email_content" formatted="false">You have been invited to the following event:\n\n%s\nWhen: %s\nAttendees: %s</string>
<!-- cert4android --> <!-- cert4android -->
<string name="certificate_notification_connection_security">EteSync: Connection security</string> <string name="certificate_notification_connection_security">EteSync: Connection security</string>