This is a preliminary document describing an adaptable system for displaying IM messages using web technologies such as HTML, Javascript, and CSS. Comments and criticism are encouraged, and an example Template file implementing AdiumMessageStyle compatibility on a javascript "client" can be found at http://dscoder.com/MessageStyle/Template.html
. A Cocoa (Mac OS X) application using the same Template file can be found at http://dscoder.com/MessageStyleTester.zip
Message Display Timeline
1) Load a Template html file from a client-specific path and display it using an HTML/CSS/JS engine
2) Create a global javascript object called 'client' that implements the Client API below
3) Call addMessages(), updateObject(), and close() in javascript when appropriate, passing objects that implement the API described below.
Message Style File Structure
StyleName.MessageStyle/
----->
Contents/
------>
Info.plist
Resources/
------>
main.css
(optional) Variants/
(optional) Overrides.js
(optional) other files
Info.plist:
A file of the form:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleGetInfoString</key>
<string>My Style Name</string>
<key>CFBundleIdentifier</key>
<string>com.mycompany.mystylename.style</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>1.0</string>
<key>CFBundleName</key>
<string>My Style Short Name</string>
<key>CFBundlePackageType</key>
<string>AdIM</string>
<key>Any Client Key</key>
<type>Value</type>
</dict>
</plist>
See http://www.apple.com/DTDs/PropertyList-1.0.dtd
for a full description of the property list format.
main.css:
A CSS file specifying the default stylesheet for message display.
Variants:
A folder containing additional CSS files which can be used to vary message display (such as alternate color settings).
Overrides.js
The functions declared in this javascript file will replace ones of the same name in the template javascript
Other files:
Any files here can be accessed via client.getResourceURL() or client.getResourceContents()
View Exposed API (Stuff the Client calls when things happen)
The following functions must be implemented in a Template.js file.
close()
Called by the client when the message window is about to be closed.
addMessages()
Called by the client when one or more Messages are available for display. The Messages are passed as arguments (and accessed using the builtin arguments object in javascript functions).
updateObject(object, propertyname)
Called by the client when one of the values in a wrapped object changes. This can be used to (for example) update a progress bar as a file transfer progresses.
Client Exposed API (Stuff that the Client makes available to JS)
The Message Style system relies heavily on communication between javascript and the native code of the embedding client. Each object type below should be a wrapper that retrieves the appropriate values from client-specific datatypes in native code.
Everything
id()
Returns a unique identifier for this object. The Adium implementation uses CF UUIDs.
type()
Returns the type of object this is (because js introspection of native objects is somewhat fragile). This is one of: "Client", "Chat", "Contact", "Message", "Event".
Client
chat()
Returns a Chat representing the current conversation.
debugLog(string) [Optional]
Logs string to a debug log/console/etc...
getTemplateContents(string)
Returns the contents of the template (client-resource-folder-relative) file named in the argument as a string. The exact process for loading the template file based on its name is opaque.
getTemplateURL(string)
Returns a full url to the specified template. The exact lookup process is opaque.
getResourceContents(string)
getResourceURL(string)
As getTemplate*, except relative to the Resources folder of the Message Style, rather than of the client.
valueForKey(string)
Returns a value for one of the following keys, or a client-specific key. Returns null if queried for an unsupported key. The search path for values is: User settings, Style settings stored in Info.plist, Default settings
FontSize
FontFamily
Variant
...
availableKeys()
Returns an array of available client data keys.
setValueForKey(string key, string value) [Optional]
Persistently stores value for later lookup; This is to allow theme-specific settings.
Chat
name()
Returns a protocol-specific identifier for this conversation.
displayName()
Returns an identifier for this conversation suitable for display to users.
users()
Returns an array of Contacts representing the people talking in this conversation
me()
Returns a contact representing the user.
messages()
Returns an array of all the Messages sent in this conversation.
startTime()
Returns a javascript Date object representing the time the chat started.
localizedStartTime()
Returns a string suitable for displaying the start time in the user's localization of choice.
classes()
Returns an array of strings representing metadata about the chat; suitable for use as CSS class names. Common values include:
encrypted
conference
...
Contact
Represents a participant in a conversation.
name()
Returns the UID of the contact.
displayName()
Returns a name for this contact suitable for display to users, such as an alias or handle.
iconURL()
Returns a full url to an icon representing the contact, or null if one is not available.
presence()
Returns an associative array (i.e. an object, in js) of information about this contact's current presence information. Exactly what is included varies with the client and protocol, but common key/value pairs include:
type : string with common values being
"away"
"available"
"busy"
...
idleSince : js Date object representing the last time the contact was active
message : string with a status message (such as an AIM away message)
iconURL : URL of an icon representing this status
Message
direction()
Returns one of "incoming", "outgoing" or null depending on whether the Message is being sent by the user, received by the user, or not being sent/received (status messages).
sender()
Returns the Contact that sent this message.
recipients()
Returns an array of the Contacts that received this message.
timeStamp()
Returns a javascript Date object representing when this message was sent.
localizedTimeStamp()
Returns a string suitable for displaying the time stamp in the user's localization of choice.
classes()
Returns a space-separated list of strings representing metadata about the message; suitable for use as CSS class names. These classes should have an underscore prepended to avoid conflicting with author classes. Common values include:
_encrypted
_offline
_history
_message
...
HTMLContent()
Returns an HTML fragment of the contents of the message.
textContent()
Returns a plaintext string of the contents of the message; useful for filtering, etc...
textDirection()
Returns either "ltr" or "rtl" depending on the direction of text in the message.
Event
Events are a subtype of a message that represent any message that is not text sent by another user; this includes status changes, file transfer requests, and conference invitations. Events can have actions, which should be represented by buttons that call native methods when clicked.
eventType()
Returns a string identifying what type of event this is. Common values include:
filetransfer
audiocall
videocall
status
HTMLTitle()
Returns an HTML string of the user-visible title for this event, such as "Call from Susan"
textTitle()
Returns the same title as a plaintext string
defaultActionTitle()
Returns the text that should be on the first button shown on this message, or null if no button should be shown. For example a file transfer request would probably have "accept".
secondaryActionTitle()
Returns the text that should be on the second button shown on this message, or null if no button should be shown. For example a file transfer request would probably have "decline".
info()
Returns an associative array (i.e. an object, in js) of information about the event. A file transfer event might have the following keys:
percentDone
totalFileSize
completedFileSize
downloadSpeed
Specific keys in the info dictionary can be specified as "info.keyname" when making calls to updateObject().
iconURL()
Returns a full URL to an icon representing this event.
defaultAction()
Returns a javascript Function object that should be called when the first button is clicked.
secondaryAction()
Returns a javascript Function object that should be called when the second button is clicked.