- Add Accept/Decline buttons to the summary display; both currently have the
   same effect:

 - Add the (someday: "accepted") item to the user's first calendar.

Also, teach the timezone heuristics about Eastern Time.

NPTOB.  Not as cool as vlad.
This commit is contained in:
shaver%mozilla.org 2005-04-24 18:33:50 +00:00
Родитель 2b6804c5fa
Коммит da5cc1b648
4 изменённых файлов: 227 добавлений и 27 удалений

Просмотреть файл

@ -47,6 +47,7 @@ MODULE = lightning
EXTRA_COMPONENTS = \
lightningTextCalendarConverter.js \
calItipProtocolHandler.js \
$(NULL)
include $(topsrcdir)/config/rules.mk

Просмотреть файл

@ -0,0 +1,188 @@
/* -*- Mode: javascript; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
const CI = Components.interfaces;
const ITIP_HANDLER_MIMETYPE = "application/x-itip-internal";
const ITIP_HANDLER_PROTOCOL = "moz-cal-handle-itip";
const CAL_ITIP_PROTO_HANDLER_CID =
Components.ID("{6E957006-B4CE-11D9-B053-001124736B74}");
const CAL_ITIP_PROTO_HANDLER_CONTRACTID =
"@mozilla.org/network/protocol;1?name=" + ITIP_HANDLER_PROTOCOL;
const CALMGR_CONTRACTID = "@mozilla.org/calendar/manager;1";
const ItipProtocolHandlerFactory =
{
createInstance: function (outer, iid) {
if (outer != null)
throw Components.results.NS_ERROR_NO_AGGREGATION;
return (new ItipProtocolHandler()).QueryInterface(iid);
}
};
const CAL_ITIP_CONTENT_HANDLER_CID =
Components.ID("{47C31F2B-B4DE-11D9-BFE6-001124736B74}");
const CAL_ITIP_CONTENT_HANDLER_CONTRACTID =
"@mozilla.org/uriloader/content-handler;1?type=" +
ITIP_HANDLER_MIMETYPE;
const ItipContentHandlerFactory =
{
createInstance: function (outer, iid) {
if (outer != null)
throw Components.results.NS_ERROR_NO_AGGREGATION;
return (new ItipContentHandler()).QueryInterface(iid);
}
};
function NYI()
{
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
}
function ItipChannel(URI)
{
this.URI = this.originalURI = URI;
}
ItipChannel.prototype = {
QueryInterface: function (aIID) {
if (!aIID.equals(CI.nsISupports) &&
!aIID.equals(CI.nsIChannel) &&
!aIID.equals(CI.nsIRequest))
throw Components.results.NS_ERROR_NO_INTERFACE;
return this;
},
contentType: ITIP_HANDLER_MIMETYPE,
loadAttributes: null,
contentLength: 0,
owner: null,
loadGroup: null,
notificationCallbacks: null,
securityInfo: null,
open: NYI,
asyncOpen: function (observer, ctxt) {
observer.onStartRequest(this, ctxt);
},
asyncRead: function (listener, ctxt) {
return listener.onStartRequest(this, ctxt);
},
isPending: function () { return true; },
status: Components.results.NS_OK,
cancel: function (status) { this.status = status; },
suspend: NYI,
resume: NYI,
};
function ItipProtocolHandler() { }
ItipProtocolHandler.prototype = {
QueryInterface: function (aIID) {
if (!aIID.equals(CI.nsISupports) &&
!aIID.equals(CI.nsIProtocolHandler))
throw Components.results.NS_ERROR_NO_INTERFACE;
return this;
},
protocolFlags: CI.nsIProtocolHandler.URI_NORELATIVE,
allowPort: function () { return false; },
isSecure: false,
newURI: function (spec, charSet, baseURI)
{
var cls = Components.classes["@mozilla.org/network/standard-url;1"];
var url = cls.createInstance(CI.nsIStandardURL);
url.init(CI.nsIStandardURL.URLTYPE_STANDARD, 0, spec, charSet, baseURI);
dump("Creating new URI for " + spec + "\n");
return url.QueryInterface(CI.nsIURI);
},
newChannel: function (URI) {
dump("Creating new ItipChannel for " + URI + "\n");
return new ItipChannel(URI);
},
};
function ItipContentHandler() { }
ItipContentHandler.prototype = {
QueryInterface: function (aIID) {
if (!aIID.equals(CI.nsISupports) &&
!aIID.equals(CI.nsIContentHandler))
throw Components.results.NS_ERROR_NO_INTERFACE;
return this;
},
handleContent: function (contentType, windowTarget, request)
{
dump("Handling some itip content, whee\n");
var channel = request.QueryInterface(CI.nsIChannel);
var uri = channel.URI.spec;
if (uri.indexOf(ITIP_HANDLER_PROTOCOL + ":") != 0) {
dump("unexpected uri " + uri + "\n");
return Components.results.NS_ERROR_FAILURE;
}
// moz-cal-handle-itip:///?
var paramString = uri.substring(ITIP_HANDLER_PROTOCOL.length + 4);
var paramArray = paramString.split("&");
var paramBlock = { };
paramArray.forEach(function (v) {
var parts = v.split("=");
paramBlock[parts[0]] = unescape(unescape(parts[1]));
});
// dump("content-handler: have params " + paramBlock.toSource() + "\n");
var event = Components.classes["@mozilla.org/calendar/event;1"].
createInstance(CI.calIEvent);
event.icalString = paramBlock.data;
dump("Processing iTIP event '" + event.title + "' from " +
event.organizer.id + " (" + event.id + ")\n");
var calMgr = Components.classes[CALMGR_CONTRACTID].getService(CI.calICalendarManager);
var cals = calMgr.getCalendars({});
cals[0].addItem(event, null);
}
};
var myModule = {
registerSelf: function (compMgr, fileSpec, location, type) {
debug("*** Registering Lightning " + ITIP_HANDLER_PROTOCOL + ": handler\n");
compMgr = compMgr.QueryInterface(CI.nsIComponentRegistrar);
compMgr.registerFactoryLocation(CAL_ITIP_PROTO_HANDLER_CID,
"Lightning " + ITIP_HANDLER_PROTOCOL + ": handler",
CAL_ITIP_PROTO_HANDLER_CONTRACTID,
fileSpec, location, type);
debug("*** Registering Lightning " + ITIP_HANDLER_MIMETYPE + " handler\n");
compMgr.registerFactoryLocation(CAL_ITIP_CONTENT_HANDLER_CID,
"Lightning " + ITIP_HANDLER_MIMETYPE + " handler",
CAL_ITIP_CONTENT_HANDLER_CONTRACTID,
fileSpec, location, type);
},
getClassObject: function (compMgr, cid, iid) {
if (!iid.equals(Components.interfaces.nsIFactory))
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
if (cid.equals(CAL_ITIP_PROTO_HANDLER_CID))
return ItipProtocolHandlerFactory;
if (cid.equals(CAL_ITIP_CONTENT_HANDLER_CID))
return ItipContentHandlerFactory;
throw Components.results.NS_ERROR_NO_INTERFACE;
},
canUnload: function(compMgr) {
return true;
}
};
function NSGetModule(compMgr, fileSpec) {
return myModule;
}

Просмотреть файл

@ -2,6 +2,22 @@
const CI = Components.interfaces;
function makeTableRow(val) {
return "<tr><td>" + val[0] + "</td><td>" + val[1] + "</td></tr>\n";
}
function makeButton(type, content) {
return "<button type='submit' value='" + type + "'>" + content + "</button>";
}
function startForm(calendarData) {
var form = "<form method='GET' action='moz-cal-handle-itip:'>\n";
form += "<input type='hidden' name='preferredCalendar' value=''>\n";
// We use escape instead of encodeURI*, because we need to deal with single quotes, sigh
form += "<input type='hidden' name='data' value='" + escape(calendarData) + "'>\n";
return form;
}
function ltnMimeConverter() { }
ltnMimeConverter.prototype = {
@ -14,21 +30,33 @@ ltnMimeConverter.prototype = {
},
convertToHTML: function(contentType, data) {
dump("converting " + contentType + " to HTML\n");
// dump("converting " + contentType + " to HTML\n");
var event = Components.classes["@mozilla.org/calendar/event;1"]
.createInstance(CI.calIEvent);
event.icalString = data;
var html = "<center><table bgcolor='#CCFFFF'>\n";
var html = "<script src='chrome://lightning/content/text-calendar-handler.js'></script>\n";
html += "<center>\n";
html += startForm(data);
html += "<table bgcolor='#CCFFFF'>\n";
var organizer = event.organizer;
html += "<tr><td>Invitation from</td><td><a href='" +
organizer.id + "'>" + organizer.commonName + "</a></td></tr>\n";
html += "<tr><td>Subject:</td><td>" + event.title + "</td></tr>\n";
html += "</table></center>";
var rows = [["Invitation from", "<a href='" + organizer.id + "'>" +
organizer.commonName + "</a>"],
["Topic:", event.title],
["Start:", event.startDate.jsDate.toLocaleTimeString()],
["End:", event.endDate.jsDate.toLocaleTimeString()]];
html += rows.map(makeTableRow).join("\n");
html += "<tr><td colspan='2'>";
html += makeButton("accept", "Accept meeting") + " ";
html += makeButton("decline", "Decline meeting") + " ";
html += "</td></tr>\n";
html += "</table>\n</form>\n</center>";
// dump("Generated HTML:\n\n" + html + "\n\n");
return html;
}
},
};
var myModule = {
@ -61,17 +89,9 @@ var myModule = {
myCID: Components.ID("{c70acb08-464e-4e55-899d-b2c84c5409fa}"),
/* ProgID for this class */
myContractID: "@mozilla.org/lightning/mime-converter;1",
/* factory object */
myFactory: {
/*
* Construct an instance of the interface specified by iid, possibly
* aggregating it with the provided outer. (If you don't know what
* aggregation is all about, you don't need to. It reduces even the
* mightiest of XPCOM warriors to snivelling cowards.)
*/
createInstance: function (outer, iid) {
if (outer != null)
throw Components.results.NS_ERROR_NO_AGGREGATION;
@ -80,17 +100,6 @@ var myModule = {
}
},
/*
* The canUnload method signals that the component is about to be unloaded.
* C++ components can return false to indicate that they don't wish to be
* unloaded, but the return value from JS components' canUnload is ignored:
* mark-and-sweep will keep everything around until it's no longer in use,
* making unconditional ``unload'' safe.
*
* You still need to provide a (likely useless) canUnload method, though:
* it's part of the nsIModule interface contract, and the JS loader _will_
* call it.
*/
canUnload: function(compMgr) {
return true;
}

Просмотреть файл

@ -147,7 +147,9 @@ function calendarDefaultTimezone() {
// XXX this table needs a _lot_ more stuff in it.
const tzTable = {
"GMT-0700 Pacific Daylight Time" : "/mozilla.org/20050126_1/America/Los_Angeles",
"GMT-0800 Pacific Standard Time" : "/mozilla.org/20050126_1/America/Los_Angeles"
"GMT-0800 Pacific Standard Time" : "/mozilla.org/20050126_1/America/Los_Angeles",
"GMT-0400 EDT" : "/mozilla.org/20050126_1/America/New_York",
"GMT-0500 EST" : "/mozilla.org/20050126_1/America/New_York",
};
// returns a ICS timezone string