Recommended and optional Real-time Collaboration configuration options
TinyMCE’s Real-time Collaboration (RTC) plugin will be retired and deactivated on December 31, 2023, and is no longer available for purchase. |
This section covers the recommended and optional configuration options for the RTC plugin. None of these options are required but assist with creating a consistent user experience between your application and TinyMCE Real-time Collaboration (RTC).
Recommended configuration options
For the best user experience, Tiny recommends including these configuration options:
rtc_server_disconnected
If the RTC session fails to connect, or is disconnected due to an error, the user will be blocked from editing (using setProgressState) along with an error notification:
RTC has lost connection to the server, please reload the page. More information may be available in the console.
The rtc_server_disconnected
callback can be used to provide an alternative response to this condition.
- Required plugin
- Type
-
Function
- Input parameters
-
Field Type Description reason
string
The cause of the disconnection. The value will be one of the reasons described below.
message
string
A suggested description for the error, translated into the active user interface language, suitable for displaying to a user. This string may contain HTML, and in some cases is the same string displayed in the editor notification.
Reasons for disconnection
It is critical to at least handle the client_update_required reason. This indicates the RTC plugin in the current editor instance is out-of-date compared to other users on the session. The behavior in this scenario depends on the configuration:
* If the rtc_server_disconnected is set, no message is displayed to the user for this error. It is up to the integrator to manage cleanly reloading the page.
* If the rtc_server_disconnected is not set, the suggested error message will be displayed in a notification asking the user to reload the page.
|
The reason
field will have one of the following values.
client_update_required
-
This error indicates the RTC plugin is out-of-date and cannot connect to an active session for the supplied
rtc_document_id
. This can happen on startup, but is more common at runtime during editor upgrades. The suggested message recommends the user reload the page. encryption
-
Indicates a failure at startup either: in the cryptography process or the configured
rtc_encryption_provider
function. This may be caused by an error in the editor configuration. jwt
-
Indicates a problem with the configured
rtc_token_provider
function. Either the provider returned a rejected promise, the returned object structure was incorrect, or the token was invalid. content
-
Indicates a problem with the configured
rtc_initial_content_provider
function. Either the provider returned a rejected promise or the returned object structure was incorrect. general
-
A generic error for reasons that do not yet have a category. Details will be printed to the browser console.
Example of handling server disconnection
tinymce.init({
selector: 'textarea', // change this value according to your HTML
plugins: 'rtc',
rtc_document_id: 'unique-document-id',
rtc_encryption_provider: () => Promise.resolve({ key: 'a secret key' }),
rtc_token_provider: () => Promise.resolve({ token: 'signed-JWT-token' }),
rtc_server_disconnected: ({ reason, message }) => {
// perform some action in response to the RTC session disconnecting, such as:
tinymce.activeEditor.notificationManager.open({
text: 'Disconnected: ' + reason + '\n' + message,
type: 'error'
});
}
});
rtc_user_details_provider
By default, a user’s unique ID (userId
, the sub
field from their JWT) will be displayed as the username in remote caret tooltips.
To display a descriptive name on the caret, the userId
needs to be resolved into user details that include the user’s display name (fullName
). This resolution is done on each client to avoid sending any personal information through the RTC server.
Only the fullName
is required, but the whole object will be stored within the RTC caret information for use with the rtc_client_connected
and rtc_client_disconnected
callbacks to avoid duplicate lookup queries. The user details are also passed to the RtcClientConnected
and RtcClientDisconnected
events.
This provider function is called once for each connecting client. Clients that reconnect may trigger a new call to the provider function rather than using cached data.
- Required plugin
- Type
-
Function (Returns a Promise)
- Input parameters
-
Field Type Description userId
string
User ID to resolve into user details.
- Return data
-
Field Type Description fullName
string
The full display name of user. For example:
"John Doe"
.any custom field
any
Extra user data for use in the
rtc_client_connected
API.
Example of providing static user details
tinymce.init({
selector: 'textarea', // change this value according to your HTML
plugins: 'rtc',
rtc_document_id: 'unique-document-id',
rtc_encryption_provider: () => Promise.resolve({ key: 'a secret key' }),
rtc_token_provider: () => Promise.resolve({ token: 'signed-JWT-token' }),
rtc_user_details_provider: ({ userId }) => Promise.resolve({ fullName: "John Doe" })
});
Example of providing user details from your server
tinymce.init({
selector: 'textarea', // change this value according to your HTML
plugins: 'rtc',
rtc_document_id: 'unique-document-id',
rtc_encryption_provider: () => Promise.resolve({ key: 'a secret key' }),
rtc_token_provider: () => Promise.resolve({ token: 'signed-JWT-token' }),
rtc_user_details_provider: ({ userId }) =>
fetch('/getUserDetails', {
method: 'POST',
credentials: 'include',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({ userId })
})
.then((response) => response.json())
.then(({ fullnamefromserver })) => ({ fullName: fullnamefromserver })
.catch((error) => console.log('Failed to retrieve user details\n' + error))
});
Optional configuration options
The following configuration options have been provide to assist with integrating Real-time Collaboration (RTC) into webpages and applications:
rtc_snapshot
Real-time collaboration integrations regularly store the content, eliminating the need for a save button. The TinyMCE RTC plugin provides a version number to assist with storing the HTML content snapshots. These snapshots are not stored on the RTC server and must be handled by the integrator.
For any given document ID, the server guarantees the version number will only increase. It can be safely used for conflict resolution. For each document ID and version combination, the snapshot content is guaranteed to be identical.
The snapshot callback will be executed in response to local changes, with access to the serialized editor content. The content is retrieved through a getContent
function to reduce CPU load if the callback decides to not use the editor content.
- Required plugin
- Type
-
Function
- Input parameters
-
Field Type Description documentId
string
The document ID from the
rtc_document_id
option.version
integer
An increasing version number, specific to the current document ID, between 0 and 2147483648 (231).
getContent
Function
Render the content for this specific version to HTML.
Example of getting content snapshots
tinymce.init({
selector: 'textarea', // change this value according to your HTML
plugins: 'rtc',
rtc_document_id: 'unique-document-id',
rtc_encryption_provider: () => Promise.resolve({ key: 'a secret key' }),
rtc_token_provider: () => Promise.resolve({ token: 'signed-JWT-token' }),
rtc_snapshot: ({ version, getContent }) => {
console.log('Current version', version);
console.log('HTML', getContent());
}
});
rtc_initial_content_provider
By default, the initial editor content is retrieved from the element targeted using the TinyMCE selector
option.
The rtc_initial_content_provider
option allows alternative initial content be retrieved for a new RTC session. This option works with frameworks and integrations (such as the TinyMCE integrations) that don’t provide access to the target element directly. If the target element contains content and a rtc_initial_content_provider
has been provided, the content from the rtc_initial_content_provider
will be used as the initial editor content.
The rtc_initial_content_provider
is used for new documents (documentId
) and is not for opening or reopening existing documents. If the document already exists, the content on the RTC Server with the provided documentId
will be loaded into the editor when it is intitalized.
- Required plugin
- Type
-
Function (Returns a Promise)
- Input parameters
-
Field Type Description documentId
string
The document ID configured using the
rtc_document_id
option. - Return data
-
Field Type Description content
string
String containing the HTML to be imported into the editor when there is no existing session.
Example of providing static content
tinymce.init({
selector: 'textarea', // change this value according to your HTML
plugins: 'rtc',
rtc_document_id: 'unique-document-id',
rtc_encryption_provider: () => Promise.resolve({ key: 'a secret key' }),
rtc_token_provider: () => Promise.resolve({ token: 'signed-JWT-token' }),
rtc_initial_content_provider: () => Promise.resolve({ content: "<p>Hello world!</p>" })
})
Example of providing dynamic content from the server
tinymce.init({
selector: 'textarea', // change this value according to your HTML
plugins: 'rtc',
rtc_document_id: 'unique-document-id',
rtc_encryption_provider: () => Promise.resolve({ key: 'a secret key' }),
rtc_token_provider: () => Promise.resolve({ token: 'signed-JWT-token' }),
rtc_initial_content_provider: ({ documentId }) => {
return fetch(`/getContent/${documentId}`, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
}).then((response) => response.json());
}
});
rtc_client_info
The rtc_client_info
option allows status flags from the local editor environment to be provided to other connecting clients. For example: "This user is on a mobile device". This option should not be used to communicate sensitive information; the authenticity of the data cannot be guaranteed.
This option accepts an object that must be serializable (JSON.stringify
will be used to transmit it between clients). Other clients receive a copy of this object in their rtc_client_connected
events.
- Required plugin
- Type
-
Object
Example of client status information
tinymce.init({
selector: 'textarea', // change this value according to your HTML
plugins: 'rtc',
rtc_document_id: 'unique-document-id',
rtc_encryption_provider: () => Promise.resolve({ key: 'a secret key' }),
rtc_token_provider: () => Promise.resolve({ token: 'signed-JWT-token' }),
rtc_client_info: { onMobile: true, region: 'us' }
});
rtc_client_connected
This option allows applications to show when a user enters the RTC session. When used in combination with rtc_client_disconnected
, a user interface of connected users can be kept up to date.
Only one rtc_client_connected
event will be fired per client connection. Connecting to a session with multiple existing clients will fire separate rtc_client_connected
events for each existing client. If a user connects using two or more editors (such as on desktop and on mobile), a separate rtc_client_connected
event will be fired.
To help with generating a user interface for connected users, an object for user details is provided by the rtc_user_details_provider
option.
- Required plugin
- Type
-
Function
- Input parameters
Field | Type | Description |
---|---|---|
|
|
This is the user’s unique ID (the |
|
|
This is a copy of the object returned by |
|
|
This is a unique identifier, generated by the RTC protocol, that can be used to differentiate between the same user connecting multiple times. |
|
|
This will be a number between 1 and 8, corresponding to one of the 8 colors defined in TinyMCE CSS. TinyMCE supports 8 distinct caret colors. If more than 8 clients connect to a session, the numbers will be reused. |
|
|
This is a copy of the |
TinyMCE cannot guarantee the accuracy of data which comes from a remote object. Tiny recommends only using the client information data for status flags. To obtain authentic client information, use the rtc_user_details_provider data returned through the userDetails field.
|
Example using client connect and disconnect events with custom user details
While all fields are provided to both the rtc_client_connected
and rtc_client_disconnected
functions, this example only handles the relevant fields for each callback function.
const connectedUsers = {}
tinymce.init({
selector: 'textarea', // change this value according to your HTML
plugins: 'rtc',
rtc_document_id: 'unique-document-id',
rtc_encryption_provider: () => Promise.resolve({ key: 'a secret key' }),
rtc_token_provider: () => Promise.resolve({ token: 'signed-JWT-token' }),
rtc_user_details_provider: ({userId}) => Promise.resolve({ fullName: "John Doe", jobTitle: "Engineer" }),
rtc_client_connected: ({userDetails: {fullName, jobTitle}, userId, caretNumber, clientId, clientInfo}) => {
connectedUsers[clientId] = {
caretNumber,
clientInfo,
userDetails,
userId
}
console.log(`${jobTitle} ${fullName} connected with caret number ${caretNumber}`, clientInfo)
}
rtc_client_disconnected: ({clientId, userDetails: {fullName, jobTitle}}) => {
delete connectedUsers[clientId]
console.log(`${jobTitle} ${fullName} disconnected`)
}
})
rtc_client_disconnected
The rtc_client_disconnected
option can be used with the rtc_client_connected
option to maintain a list of connected users.
- Required plugin
- Type
-
Function
- Input parameters
Field | Type | Description |
---|---|---|
|
|
This is the user’s unique ID (the |
|
|
This is a copy of the object returned by |
|
|
This is a unique identifier, generated by the RTC protocol, that can be used to differentiate between the same user connecting multiple times. |
|
|
This will be a number between 1 and 8, corresponding to one of the 8 colors defined in TinyMCE CSS. TinyMCE supports 8 distinct caret colors. If more than 8 clients connect to a session, the numbers will be reused. |
|
|
This is a copy of the |
Example using client connect and disconnect events with custom user details
While all fields are provided to both the rtc_client_connected
and rtc_client_disconnected
functions, this example only handles the relevant fields for each callback function.
const connectedUsers = {}
tinymce.init({
selector: 'textarea', // change this value according to your HTML
plugins: 'rtc',
rtc_document_id: 'unique-document-id',
rtc_encryption_provider: () => Promise.resolve({ key: 'a secret key' }),
rtc_token_provider: () => Promise.resolve({ token: 'signed-JWT-token' }),
rtc_user_details_provider: ({userId}) => Promise.resolve({ fullName: "John Doe", jobTitle: "Engineer" }),
rtc_client_connected: ({userDetails: {fullName, jobTitle}, userId, caretNumber, clientId, clientInfo}) => {
connectedUsers[clientId] = {
caretNumber,
clientInfo,
userDetails,
userId
}
console.log(`${jobTitle} ${fullName} connected with caret number ${caretNumber}`, clientInfo)
}
rtc_client_disconnected: ({clientId, userDetails: {fullName, jobTitle}}) => {
delete connectedUsers[clientId]
console.log(`${jobTitle} ${fullName} disconnected`)
}
})
rtc_unsupported_content_notification
The rtc_unsupported_content_notification
option can be used to disable the notification about unsupported HTML inside the RTC enabled editor. Existing documents containing HTML generated using plugins not yet supported by the RTC plugin could lead to unexpected behavior. For a list of RTC supported plugins, see: Supported TinyMCE functionality for Real-time Collaboration.
- Required plugin
- Type
-
Boolean
- Default
-
true
Example of blocking unsupported content notifications
tinymce.init({
selector: 'textarea', // change this value according to your HTML
plugins: 'rtc',
rtc_document_id: 'unique-document-id',
rtc_encryption_provider: () => Promise.resolve({ key: 'a secret key' }),
rtc_token_provider: () => Promise.resolve({ token: 'signed-JWT-token' }),
rtc_unsupported_content_notification: false
});