зеркало из https://github.com/mozilla/pjs.git
bug 373380 Adding initial iTIP invitation support r=lilmatt
This commit is contained in:
Родитель
d126ebd815
Коммит
701e2b05d2
|
@ -45,6 +45,7 @@ function createEventWithDialog(calendar, startDate, endDate, summary, event)
|
||||||
|
|
||||||
var onNewEvent = function(event, calendar, originalEvent) {
|
var onNewEvent = function(event, calendar, originalEvent) {
|
||||||
doTransaction('add', event, calendar, null, null);
|
doTransaction('add', event, calendar, null, null);
|
||||||
|
checkForAttendees(event, originalEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event) {
|
if (event) {
|
||||||
|
@ -105,6 +106,7 @@ function createTodoWithDialog(calendar, dueDate, summary, todo)
|
||||||
|
|
||||||
var onNewItem = function(item, calendar, originalItem) {
|
var onNewItem = function(item, calendar, originalItem) {
|
||||||
doTransaction('add', item, calendar, null, null);
|
doTransaction('add', item, calendar, null, null);
|
||||||
|
checkForAttendees(item, originalItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (todo) {
|
if (todo) {
|
||||||
|
@ -129,6 +131,7 @@ function createTodoWithDialog(calendar, dueDate, summary, todo)
|
||||||
|
|
||||||
var onNewItem = function(item, calendar, originalItem) {
|
var onNewItem = function(item, calendar, originalItem) {
|
||||||
calendar.addItem(item, null);
|
calendar.addItem(item, null);
|
||||||
|
checkForAttendees(item, originalItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
setDefaultAlarmValues(todo);
|
setDefaultAlarmValues(todo);
|
||||||
|
@ -149,6 +152,7 @@ function modifyEventWithDialog(item, job)
|
||||||
else {
|
else {
|
||||||
doTransaction('move', item, calendar, originalItem, null);
|
doTransaction('move', item, calendar, originalItem, null);
|
||||||
}
|
}
|
||||||
|
checkForAttendees(item, originalItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item) {
|
if (item) {
|
||||||
|
@ -418,3 +422,114 @@ calTransaction.prototype = {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* checkForAttendees
|
||||||
|
* Checks to see if the attendees were added or changed between the original
|
||||||
|
* and new item. If there is a change, it launches the calIITipTransport
|
||||||
|
* service and sends the invitations
|
||||||
|
*/
|
||||||
|
function checkForAttendees(aItem, aOriginalItem)
|
||||||
|
{
|
||||||
|
// iTIP is only supported in Lightning right now
|
||||||
|
if (!gDataMigrator.isLightning) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var sendInvite = false;
|
||||||
|
var itemAtt = aItem.getAttendees({});
|
||||||
|
|
||||||
|
if (itemAtt.length > 0) {
|
||||||
|
var originalAtt = aOriginalItem.getAttendees({});
|
||||||
|
|
||||||
|
if ( (originalAtt.length > 0) &&
|
||||||
|
(originalAtt.length == itemAtt.length) )
|
||||||
|
{
|
||||||
|
for (var i=0; i < itemAtt.length; i++) {
|
||||||
|
if (originalAtt[i].id != itemAtt[i].id) {
|
||||||
|
sendInvite = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// We have attendees on item, not on original, attendees were
|
||||||
|
// added.
|
||||||
|
sendInvite = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXX Until we rethink attendee support and until such support
|
||||||
|
// is worked into the event dialog (which has been done in the prototype
|
||||||
|
// dialog to a degree) then we are going to simply hack in some attendee
|
||||||
|
// support so that we can round-trip iTIP invitations.
|
||||||
|
if (sendInvite) {
|
||||||
|
// Since there is no way to determine the type of transport an
|
||||||
|
// attendee requires, we default to email
|
||||||
|
var emlSvc = Components.classes["@mozilla.org/calendar/itip-transport;1?type=email"]
|
||||||
|
.createInstance(Components.interfaces.calIItipTransport);
|
||||||
|
|
||||||
|
var itipItem = Components.classes["@mozilla.org/calendar/itip-item;1"]
|
||||||
|
.createInstance(Components.interfaces.calIItipItem);
|
||||||
|
|
||||||
|
var sbs = Components.classes["@mozilla.org/intl/stringbundle;1"]
|
||||||
|
.getService(Components.interfaces.nsIStringBundleService);
|
||||||
|
|
||||||
|
var sb = sbs.createBundle("chrome://lightning/locale/lightning.properties");
|
||||||
|
var recipients = [];
|
||||||
|
|
||||||
|
// We have to modify our item a little, so we clone it.
|
||||||
|
var item = aItem.clone();
|
||||||
|
|
||||||
|
// Fix up our attendees for invitations using some good defaults
|
||||||
|
item.removeAllAttendees();
|
||||||
|
for each (var attendee in itemAtt) {
|
||||||
|
attendee.role = "REQ-PARTICIPANT";
|
||||||
|
attendee.participationStatus = "NEEDS-ACTION";
|
||||||
|
attendee.rsvp = true;
|
||||||
|
item.addAttendee(attendee);
|
||||||
|
recipients.push(attendee);
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXX The event dialog has no means to set us as the organizer
|
||||||
|
// since we defaulted to email above, we know we need to prepend
|
||||||
|
// mailto when we convert it to an attendee
|
||||||
|
var organizer = Components.classes["@mozilla.org/calendar/attendee;1"]
|
||||||
|
.createInstance(Components.interfaces.calIAttendee);
|
||||||
|
organizer.id = "mailto:" + emlSvc.defaultIdentity;
|
||||||
|
organizer.role = "REQ-PARTICIPANT";
|
||||||
|
organizer.participationStatus = "ACCEPTED";
|
||||||
|
organizer.isOrganizer = true;
|
||||||
|
|
||||||
|
// Add our organizer to the item. Again, the event dialog really doesn't
|
||||||
|
// have a mechanism for creating an item with a method, so let's add
|
||||||
|
// that too while we're at it. We'll also fake Sequence ID support.
|
||||||
|
item.organizer = organizer;
|
||||||
|
item.setProperty("METHOD", "REQUEST");
|
||||||
|
item.setProperty("SEQUENCE", "1");
|
||||||
|
|
||||||
|
var summary
|
||||||
|
if (item.getProperty("SUMMARY")) {
|
||||||
|
summary = item.getProperty("SUMMARY");
|
||||||
|
} else {
|
||||||
|
summary = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize and set our properties on the item
|
||||||
|
itipItem.init(item.icalString);
|
||||||
|
itipItem.isSend = true;
|
||||||
|
itipItem.receivedMethod = "REQUEST";
|
||||||
|
itipItem.responseMethod = "REQUEST";
|
||||||
|
itipItem.autoResponse = Components.interfaces.calIItipItem.USER;
|
||||||
|
|
||||||
|
// Get ourselves some default text - when we handle organizer properly
|
||||||
|
// We'll need a way to configure the Common Name attribute and we should
|
||||||
|
// use it here rather than the email address
|
||||||
|
var subject = sb.formatStringFromName("itipRequestSubject",
|
||||||
|
[summary], 1);
|
||||||
|
var body = sb.formatStringFromName("itipRequestBody",
|
||||||
|
[emlSvc.defaultIdentity, summary],
|
||||||
|
2);
|
||||||
|
|
||||||
|
// Send it!
|
||||||
|
emlSvc.sendItems(recipients.length, recipients, subject, body, itipItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -67,7 +67,7 @@
|
||||||
&lightning.imipbar.description;
|
&lightning.imipbar.description;
|
||||||
</description>
|
</description>
|
||||||
<spacer flex="1"/>
|
<spacer flex="1"/>
|
||||||
<button id="imip-button1" align="center" pack="end"/>
|
<button id="imip-button1" align="center" pack="end" hidden="true"/>
|
||||||
<button id="imip-button2" align="center" pack="end" hidden="true"/>
|
<button id="imip-button2" align="center" pack="end" hidden="true"/>
|
||||||
</hbox>
|
</hbox>
|
||||||
</hbox>
|
</hbox>
|
||||||
|
|
|
@ -59,7 +59,7 @@ function checkForItipItem()
|
||||||
var sinkProps = msgWindow.msgHeaderSink.properties;
|
var sinkProps = msgWindow.msgHeaderSink.properties;
|
||||||
// This property was set by LightningTextCalendarConverter.js
|
// This property was set by LightningTextCalendarConverter.js
|
||||||
itipItem = sinkProps.getPropertyAsInterface("itipItem",
|
itipItem = sinkProps.getPropertyAsInterface("itipItem",
|
||||||
Components.interfaces.calIItipItem)
|
Components.interfaces.calIItipItem);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// This will throw on every message viewed that doesn't have the
|
// This will throw on every message viewed that doesn't have the
|
||||||
// itipItem property set on it. So we eat the errors and move on.
|
// itipItem property set on it. So we eat the errors and move on.
|
||||||
|
@ -77,10 +77,14 @@ function checkForItipItem()
|
||||||
itipItem.targetCalendar = getTargetCalendar();
|
itipItem.targetCalendar = getTargetCalendar();
|
||||||
|
|
||||||
var imipMethod = getMsgImipMethod();
|
var imipMethod = getMsgImipMethod();
|
||||||
if (imipMethod.length) {
|
if (imipMethod &&
|
||||||
|
imipMethod.length != 0 &&
|
||||||
|
imipMethod.toLowerCase() != "nomethod")
|
||||||
|
{
|
||||||
itipItem.receivedMethod = imipMethod;
|
itipItem.receivedMethod = imipMethod;
|
||||||
} else {
|
} else {
|
||||||
// Thunderbird 1.5 case, we cannot get the imipMethod
|
// There is no METHOD in the content-type header (spec violation).
|
||||||
|
// Fall back to using the one from the itipItem's ICS.
|
||||||
imipMethod = itipItem.receivedMethod;
|
imipMethod = itipItem.receivedMethod;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,6 +131,8 @@ function onImipStartHeaders()
|
||||||
{
|
{
|
||||||
var imipBar = document.getElementById("imip-bar");
|
var imipBar = document.getElementById("imip-bar");
|
||||||
imipBar.setAttribute("collapsed", "true");
|
imipBar.setAttribute("collapsed", "true");
|
||||||
|
document.getElementById("imip-button1").setAttribute("hidden", "true");
|
||||||
|
document.getElementById("imip-button2").setAttribute("hidden", "true");
|
||||||
|
|
||||||
// A new message is starting.
|
// A new message is starting.
|
||||||
// Clear our iMIP/iTIP stuff so it doesn't contain stale information.
|
// Clear our iMIP/iTIP stuff so it doesn't contain stale information.
|
||||||
|
@ -152,9 +158,12 @@ function setupBar(imipMethod)
|
||||||
var description = document.getElementById("imip-description");
|
var description = document.getElementById("imip-description");
|
||||||
|
|
||||||
// Bug 348666: here is where we would check if this event was already
|
// Bug 348666: here is where we would check if this event was already
|
||||||
// added to calendar or not and display correct information here
|
// added to calendar or not and display correct information
|
||||||
|
|
||||||
|
if (imipMethod == "REQUEST") {
|
||||||
if (description.firstChild.data) {
|
if (description.firstChild.data) {
|
||||||
description.firstChild.data = ltnGetString("lightning","imipBarText");
|
description.firstChild.data = ltnGetString("lightning",
|
||||||
|
"imipBarRequestText");
|
||||||
}
|
}
|
||||||
|
|
||||||
var button = document.getElementById("imip-button1");
|
var button = document.getElementById("imip-button1");
|
||||||
|
@ -164,14 +173,29 @@ function setupBar(imipMethod)
|
||||||
button.setAttribute("oncommand",
|
button.setAttribute("oncommand",
|
||||||
"setAttendeeResponse('ACCEPTED', 'CONFIRMED');");
|
"setAttendeeResponse('ACCEPTED', 'CONFIRMED');");
|
||||||
|
|
||||||
if (imipMethod == "REQUEST") {
|
// Create a DECLINE button
|
||||||
// Then create a DECLINE button
|
|
||||||
button = document.getElementById("imip-button2");
|
button = document.getElementById("imip-button2");
|
||||||
button.removeAttribute("hidden");
|
button.removeAttribute("hidden");
|
||||||
button.setAttribute("label", ltnGetString("lightning",
|
button.setAttribute("label", ltnGetString("lightning",
|
||||||
"imipDeclineInvitation.label"));
|
"imipDeclineInvitation.label"));
|
||||||
button.setAttribute("oncommand",
|
button.setAttribute("oncommand",
|
||||||
"setAttendeeResponse('DECLINED', 'CONFIRMED');");
|
"setAttendeeResponse('DECLINED', 'CONFIRMED');");
|
||||||
|
} else if (imipMethod == "REPLY") {
|
||||||
|
// Bug xxxx we currently cannot process REPLY messages so just let
|
||||||
|
// the user know what this is, and don't give them any options.
|
||||||
|
if (description.firstChild.data) {
|
||||||
|
description.firstChild.data = ltnGetString("lightning",
|
||||||
|
"imipBarReplyText");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Bug xxxx TBD: Something went wrong or we found a message we don't
|
||||||
|
// support yet. We can show a "This method is not supported in this
|
||||||
|
// version" or simply hide the iMIP bar at this point
|
||||||
|
if (description.firstChild.data) {
|
||||||
|
description.firstChild.data = ltnGetString("lightning",
|
||||||
|
"imipBarUnsupportedText");
|
||||||
|
}
|
||||||
|
Components.utils.reportError("Unknown imipMethod: " + imipMethod);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,10 +55,14 @@ imipHtml.description=Description:
|
||||||
|
|
||||||
imipAddToCalendar.label=Add To Calendar
|
imipAddToCalendar.label=Add To Calendar
|
||||||
imipAddedItemToCal=Event Added to Calendar
|
imipAddedItemToCal=Event Added to Calendar
|
||||||
imipBarText=This message contains an invitation to an event.
|
imipBarRequestText=This message contains an invitation to an event.
|
||||||
|
imipBarReplyText=This message contains a reply to an invitation.
|
||||||
|
imipBarUnsupportedText=This message contains an event that this version of Lightning cannot process.
|
||||||
imipAcceptInvitation.label=Accept
|
imipAcceptInvitation.label=Accept
|
||||||
imipDeclineInvitation.label=Decline
|
imipDeclineInvitation.label=Decline
|
||||||
|
|
||||||
itipReplySubject=Event Invitation Reply: %1$S
|
itipReplySubject=Event Invitation Reply: %1$S
|
||||||
itipReplyBodyAccept=%1$S has accepted your event invitation.
|
itipReplyBodyAccept=%1$S has accepted your event invitation.
|
||||||
itipReplyBodyDecline=%1$S has declined your event invitation.
|
itipReplyBodyDecline=%1$S has declined your event invitation.
|
||||||
|
itipRequestSubject=Event Invitation: %1$S
|
||||||
|
itipRequestBody=%1$S has invited you to %2$S
|
||||||
|
|
Загрузка…
Ссылка в новой задаче