The OnMessageMoving & OnMessageMoved methods would be internal to the
RoundCubeClient object. Inside those methods there needs to be a way to run
the configured plugins. That is the area which which will require a good deal
of planning.
> What does this mean?
>> What I would do is hold the collection of message objects as a property
> of a RoundCubeClient object.
What I mean here is the following:
var rc = new RoundCubeClient();
var folders = rc.getFolders();
var messages = rc.getMessages();
rc.renderFolders(folders);
rc.activateFolder(RC.INBOX); // RC.INBOX is a constant defining the Inbox
Internally I see the RoundCubeClient acting as the traffic cop for all data
going to and from the server. It will hold references to all of the data. It
will also render that data to the web page. But the HTML elements rendered to
the MessageTray and FolderTray are only renderings of the data held in the
RoundCubeClient. A plugin could completely replace the content in the
MessageTray and then call rc.activateFolder(RC.INBOX) to render the MessageTray
with a list of messages in the Inbox.
On the server we would have a folder called plugins. We could follow the way
that WordPress plugins work. They just have you drop folders into the plugins
folder and the folder name is used to define the plugin. So for an RSS reader
plugin I would have the following structure.
plugins\
RssReaderPlugin\
RssReader.xml
RssReader.js
RssReader.php
RssReaderConfig.php
media\
RssReader.css
RssReaderIcon.png
A few things here are implicit requirements. First the new plugin must be
added to the plugins folder and the folder name must end in Plugin. You could
deactivate a plugin by simply added _off to the folder name, which is a
convenient way to preload this folder with several inactive plugins.
The remaining files like the xml, js and php files are named to match the
folder name. If these files do not exist the plugin will not be activated.
As for Javascript libraries, scriptaculous.js is 2.3k and if it needs one of
the other scripts it loads them as needed. Fortunately this is run as an
application and these scripts will just load when the application is first
started. I assume that the mail messages which I view sometimes are much
bigger than a few kb, so I think it is acceptable. It is something we can keep
an eye on. What I like about Scriptaculous is that we could use it as the
standard JS library and all plugins will be able to assume that is there. To
script against it they can use the Scriptaculous wiki for the documentation.
Here are the file sizes:
4.5K Jan 17 21:22 builder.js
28K Jan 17 21:22 controls.js
30K Jan 17 21:22 dragdrop.js
32K Jan 17 21:22 effects.js
2.2K Jul 4 2006 events.js
63K Jan 17 21:31 prototype.js
2.3K Jan 17 21:22 scriptaculous.js
10K Jan 17 21:22 slider.js
19K Jan 17 21:22 unittest.js
Brennan
On Thu, 18 Jan 2007 17:34:12 +1100, Sam Bailey <[EMAIL PROTECTED]> wrote:
> Looks good so far. I've also used those libraries before, so that makes
> it a bit easier for me. The only worry with the libraries is that they
> are quite large. On the flip side though using them takes away the
> worries of cross-browser javascript from the RoundCube team.
>
> Would the plugin call the OnMessageMoving & OnMessageMoved functions or
> does the plugin write what is in those functions? No hang on I think
> I've got it now. The plugin or RC core function writes the contents of
> the functions to do what is necessary right?
>
> Based on that I like it - and it sets out a basic structure that the
> plugin or RC function needs to follow. Just like filling in the gaps.
>
> Why would you swap out the message tray content? Maybe I'm thinking too
> specifically in reference the the RSS reader.
>
> What does this mean?
>> What I would do is hold the collection of message objects as a property
> of a RoundCubeClient object.
>>
> May we should start a list of event handlers/wrappers. Obviously there
> will be a lot of them, but maybe try and get the basics down. Then we
> can try to get them interacting together safely.
>
> I haven't used JSON before, only AJAX requests, so I'll be off to learn
> how it all works. Don't worry about the stylesheet, as long as it is
> functional that is all we need for the moment.
>
> The above message may seem a bit jumpy in terms of content, sorry about
> that - I think my brain as been overheating today.
>
> Sam
>
> Brennan Stehling wrote:
>> Ok,
>>
>> Here is a simple working example.
>>
>> http://brennan.offwhite.net/rcdev/test1.html
>>
>> It is using Scriptaculous and the little events library from Dean
> Edwards.
>>
>> http://wiki.script.aculo.us/scriptaculous/
>> http://dean.edwards.name/weblog/2005/10/add-event2/
>>
>> The custom code is inline in the page. This simulates a message tray
> and a folder tray. You can drag messages onto folders. The first message
> is not allowed and the event is canceled. The other messages are allowed
> and write output to the top to indicate which message was drop into which
> folder.
>>
>> It could be extended further to loop through other folder handler
> methods.
>>
>> What I have not done is completely model the data in Javascript. What I
> would do is hold the collection of message objects as a property of a
> RoundCubeClient object. The MessageTray would be swapped out with content
> when a message is being displayed and changed back to the list of messages
> when a folder is activated. But plugin events could also write to the
> MessageTray.
>>
>> The next step could be to load the collection of Message objects using a
> JSON message pulled from the server which is rendered to the MessageTray.
> And then the event wrappers can be place around certain actions.
>>
>> The really useful piece in the above example is the addEvent method from
> the Dean Edwards events library which is just 70 lines long. You can
> attach events to HTML elements. I used it here to attach a double-click
> even to the messages.
>>
>> Go ahead and see what you could can do with this example. I did not do
> much with the stylesheet to display this in a friendly way, but it could be
> made to look much better.
>>
>> Brennan
>>
>> On Thu, 18 Jan 2007 11:35:46 +1100, Sam Bailey <[EMAIL PROTECTED]>
> wrote:
>>> Brennan,
>>>
>>> Fleshing out the proof of concept sounds like a good way to go with it.
>>> Specifically using JSON with event wrappers is a great idea as it keeps
>>> the flexibility required for a plugin API. How do we go about this?
>>>
>>> Do you want to use the RSS Reader as the example for a proof of concept
>>> or just create a basic API etc?
>>>
>>> A core + custom plugin arrangement is what I was thinking about in my
>>> original discussion, sort of an option 1 & 2. I can host the
>>> example/concept on my server if required.
>>>
>>> Sam
>>>
>>> Brennan Stehling wrote:
>>>> Sam,
>>>>
>>>> I think application extensibility is absolutely important. The
>>> applications which take off are the ones which can be customized to
> this
>>> degree. People love applications which can be extended because they
> are
>>> not limited and if they want a feature they usually can find it sooner
> or
>>> later. And if they really, really want it they could build it
> themselves.
>>>> To add plugin support to RC I would start documenting what a plugin
>>> would be able to do from a functional standpoint. And I would consider
> how
>>> other applications have been built for extensibility. The main one
> that
>>> comes to mind is the Apache Web Server. Much of the functionality that
>>> people use is optional. But it is the most widely used web server
> because
>>> it can do so much. And if there is a shortcoming you can quickly
> overcome
>>> it by extending Apache with a module. Apache even allows extensions in
>>> different languages like Perl, PHP and Python so you start with C which
> few
>>> developers can do well but open up the extensibility to a very large
> pool
>>> of capable developers. By using JSON as the communications layer there
> is
>>> no reason the backend has to be PHP because JSON has been ported to all
> of
>>> the top programming languages.
>>>> For RoundCube I could see some of the existing features broken out
> into
>>> plugins/extensions which come bundled with the installation with a few
>>> additional plugins disabled. The core plugins are excellent examples
> for
>>> those who choose to create a custom plugin. And as we add features to
> RC
>>> we make a more rich plugin architecture.
>>>> One important point is that the plugin developers who create custom
>>> plugins are responsible for testing their own plugins with the RC
> releases.
>>> The core RC team will not be able to test every plugin and should not
> be
>>> expected to support them.
>>>> A feature I would want a plugin to be able to do is handle new
> messages
>>> as they are coming in and when messages are moved between folders.
> From an
>>> event-driven standpoint I would like the event to be raised before the
>>> action is taken with the option to cancel it, and then again once the
>>> action has completed. For the folders, I would have these...
>>>> OnMessageMoving(source, cancelEventArgs) - before moving
>>>> OnMessageMoved(source, eventArgs) - after moved
>>>>
>>>> In each case the source would be the message which is moving and the
>>> event args would have a property naming the sourceFolder and
>>> destinationFolder. And the cancelEventArgs.cancel property could be
> set to
>>> false to tell the caller not to move the message.
>>>> I think this would be a good construct for many of the plugin actions.
>>> It is common with event-driven software.
>>>> I can easily think of a great way to use this as a plugin. I get
> emails
>>> from my WordPress blog when people post comments with a very specific
>>> subject. If I want the comment on my blog deleted I could drag the
> email
>>> to the trash and the plugin would check if it is a blog comment message
>>> take the necessary action to delete the comment on my blog. And moving
> it
>>> to my Blog folder could mark a blog comment as approved. Instantly I
> could
>>> have RC integrated with WP. And if the plugin fails to authenticate
> with
>>> my WP blog it could cancel the move and show me a warning. This is
>>> something you clearly do not want in the RC core but would be
> beneficial to
>>> many users who also use WP.
>>>> That leads to the next point of extensibility. Some plugins will need
>>> preferences set. So we would need a way for a plugin to display
> settings
>>> on the preferences screen.
>>>> I think we could gradually add more event wrappers to various parts of
>>> the interface. With each RC release we can add new wrapper and the
> plugin
>>> developers can add handlers for each of the wrappers if they want to
>>> implement some behavior. But a plugin may just use one wrapper for a
>>> specific need. We just want to stabilize the initial wrappers so we do
> not
>>> keep changing how they work in later releases and break existing
> plugins.
>>>> Another use for a plugin would be for rendering messages. When I send
>>> myself an invite from Google Calendar it sends along an .ics file.
> Outlook
>>> knows how to handle it which I think supported this feature first and
>>> Google copied it. I think Apple created the .ics format which MS
> copied.
>>> (wonderful integration!) I would like to use an invitation plugin
> which
>>> can detect this calendar data and do something to the display of the
>>> message to integrate with some sort of calendar system that the plugin
>>> provides.
>>>> For the address book, when I add a new contact a plugin could relay
> the
>>> new contact to another system. A plugin could also handle lookups in a
>>> custom user store which we cannot predict for RC. LDAP integration is
>>> obvious, but if someone has a custom contact database they could create
> a
>>> plugin to integrate with it. And if one of the core plugins is an LDAP
>>> plugin they could use that as a starting point for their own plugin.
>>>> Sam,
>>>>
>>>> What we can do is flesh out a proof of concept to present to the team.
>>> Once we have put in the work to show a working demo it would be a few
> steps
>>> closer to seeing how it can be implemented with RC.
>>>> Brennan
--
Brennan Stehling
Offwhite.net LLC
[EMAIL PROTECTED]