- Read the getting started guide
-
+
@@ -19,7 +19,8 @@
-
+
+
diff --git a/static/chat/index.js b/static/chat/index.js
index 6e4610e..0844021 100755
--- a/static/chat/index.js
+++ b/static/chat/index.js
@@ -1,106 +1,111 @@
$(function() {
- // Get handle to the chat div
- var $chatWindow = $('#messages');
+ // Get handle to the chat div
+ var $chatWindow = $('#messages');
- // Our interface to the Chat service
- var chatClient;
+ // Our interface to the Chat service
+ var chatClient;
- // A handle to the "general" chat channel - the one and only channel we
- // will have in this sample app
- var generalChannel;
+ // A handle to the "general" chat channel - the one and only channel we
+ // will have in this sample app
+ var generalChannel;
- // The server will assign the client a random username - store that value
- // here
- var username;
+ // The server will assign the client a random username - store that value
+ // here
+ var username;
- // Helper function to print info messages to the chat window
- function print(infoMessage, asHtml) {
- var $msg = $('
');
- if (asHtml) {
- $msg.html(infoMessage);
- } else {
- $msg.text(infoMessage);
- }
- $chatWindow.append($msg);
+ // Helper function to print info messages to the chat window
+ function print(infoMessage, asHtml) {
+ var $msg = $('
');
+ if (asHtml) {
+ $msg.html(infoMessage);
+ } else {
+ $msg.text(infoMessage);
}
+ $chatWindow.append($msg);
+ }
- // Helper function to print chat message to the chat window
- function printMessage(fromUser, message) {
- var $user = $('').text(fromUser + ':');
- if (fromUser === username) {
- $user.addClass('me');
- }
- var $message = $('').text(message);
- var $container = $('
');
- $container.append($user).append($message);
- $chatWindow.append($container);
- $chatWindow.scrollTop($chatWindow[0].scrollHeight);
+ // Helper function to print chat message to the chat window
+ function printMessage(fromUser, message) {
+ var $user = $('').text(fromUser + ':');
+ if (fromUser === username) {
+ $user.addClass('me');
}
+ var $message = $('').text(message);
+ var $container = $('
');
+ $container.append($user).append($message);
+ $chatWindow.append($container);
+ $chatWindow.scrollTop($chatWindow[0].scrollHeight);
+ }
+ // Alert the user they have been assigned a random username
+ print('Logging in...');
+
+ // Get an access token for the current user, passing a username (identity)
+ // and a device ID - for browser-based apps, we'll always just use the
+ // value "browser"
+ $.getJSON('/token', {
+ device: 'browser'
+ }, function(data) {
// Alert the user they have been assigned a random username
- print('Logging in...');
+ username = data.identity;
+ print('You have been assigned a random username of: '
+ + '' + username + '', true);
- // Get an access token for the current user, passing a username (identity)
- // and a device ID - for browser-based apps, we'll always just use the
- // value "browser"
- $.getJSON('/token', {
- device: 'browser'
- }, function(data) {
- // Alert the user they have been assigned a random username
- username = data.identity;
- print('You have been assigned a random username of: '
- + '' + username + '', true);
+ // Initialize the Chat client
+ Twilio.Chat.Client.create(data.token).then(client => {
+ chatClient = client;
+ chatClient.getSubscribedChannels().then(createOrJoinGeneralChannel);
+ });
+ });
- // Initialize the Chat client
- chatClient = new Twilio.Chat.Client(data.token);
- chatClient.getSubscribedChannels().then(createOrJoinGeneralChannel);
+ function createOrJoinGeneralChannel() {
+ // Get the general chat channel, which is where all the messages are
+ // sent in this simple application
+ print('Attempting to join "general" chat channel...');
+ chatClient.getChannelByUniqueName('general')
+ .then(function(channel) {
+ generalChannel = channel;
+ console.log('Found general channel:');
+ console.log(generalChannel);
+ setupChannel();
+ }).catch(function() {
+ // If it doesn't exist, let's create it
+ console.log('Creating general channel');
+ chatClient.createChannel({
+ uniqueName: 'general',
+ friendlyName: 'General Chat Channel'
+ }).then(function(channel) {
+ console.log('Created general channel:');
+ console.log(channel);
+ generalChannel = channel;
+ setupChannel();
+ }).catch(function(channel) {
+ console.log('Channel could not be created:');
+ console.log(channel);
+ });
+ });
+ }
+
+ // Set up channel after it has been found
+ function setupChannel() {
+ // Join the general channel
+ generalChannel.join().then(function(channel) {
+ print('Joined channel as '
+ + '' + username + '.', true);
});
- function createOrJoinGeneralChannel() {
- // Get the general chat channel, which is where all the messages are
- // sent in this simple application
- print('Attempting to join "general" chat channel...');
- var promise = chatClient.getChannelByUniqueName('general');
- promise.then(function(channel) {
- generalChannel = channel;
- console.log('Found general channel:');
- console.log(generalChannel);
- setupChannel();
- }).catch(function() {
- // If it doesn't exist, let's create it
- console.log('Creating general channel');
- chatClient.createChannel({
- uniqueName: 'general',
- friendlyName: 'General Chat Channel'
- }).then(function(channel) {
- console.log('Created general channel:');
- console.log(channel);
- generalChannel = channel;
- setupChannel();
- });
- });
- }
-
- // Set up channel after it has been found
- function setupChannel() {
- // Join the general channel
- generalChannel.join().then(function(channel) {
- print('Joined channel as '
- + '' + username + '.', true);
- });
-
- // Listen for new messages sent to the channel
- generalChannel.on('messageAdded', function(message) {
- printMessage(message.author, message.body);
- });
- }
-
- // Send a new message to the general channel
- var $input = $('#chat-input');
- $input.on('keydown', function(e) {
- if (e.keyCode == 13 && generalChannel) {
- generalChannel.sendMessage($input.val())
- $input.val('');
- }
+ // Listen for new messages sent to the channel
+ generalChannel.on('messageAdded', function(message) {
+ printMessage(message.author, message.body);
});
+ }
+
+ // Send a new message to the general channel
+ var $input = $('#chat-input');
+ $input.on('keydown', function(e) {
+ if (e.keyCode == 13) {
+ generalChannel.sendMessage($input.val())
+ $input.val('');
+ }
+ });
});
diff --git a/static/config-check.js b/static/config-check.js
index 01a81f5..04fa045 100644
--- a/static/config-check.js
+++ b/static/config-check.js
@@ -1,61 +1,58 @@
$(function() {
- $.get('/config', function(response) {
- configureField(response, 'TWILIO_ACCOUNT_SID', 'twilioAccountSID', false);
- configureField(response, 'TWILIO_API_KEY', 'twilioAPIKey', false);
- configureField(response, 'TWILIO_API_SECRET', 'twilioAPISecret', true);
- configureField(response, 'TWILIO_NOTIFICATION_SERVICE_SID', 'twilioNotificationServiceSID', false);
- configureField(response, 'TWILIO_CHAT_SERVICE_SID', 'twilioChatServiceSID', false);
- configureField(response, 'TWILIO_SYNC_SERVICE_SID', 'twilioSyncServiceSID', false);
+ $.get('/config', function(response) {
+ Object.keys(fields).forEach(configureField(fields, response));
+ Object.keys(buttons).forEach(configureButton(buttons, response));
+ });
- //configure individual product buttons
- if (response.TWILIO_ACCOUNT_SID && response.TWILIO_ACCOUNT_SID != '' &&
- response.TWILIO_API_KEY && response.TWILIO_API_KEY != '' && response.TWILIO_API_SECRET) {
+ // Button Ids' and Config Keys
+ var buttons = {
+ videoDemoButton: 'TwilioApiSecret',
+ chatDemoButton: 'TwilioChatServiceSid',
+ syncDemoButton: 'TwilioSyncServiceSid',
+ notifyDemoButton: 'TwilioNotificationServiceSid'
+ };
- $('#videoDemoButton').addClass('btn-success');
+ // Field Ids' and Masked Flag
+ var fields = {
+ twilioAccountSid: false,
+ twilioApiKey: false,
+ twilioApiSecret: true,
+ twilioNotificationServiceSid: false,
+ twilioChatServiceSid: false,
+ twilioSyncServiceSid: false
+ };
- if (response.TWILIO_CHAT_SERVICE_SID && response.TWILIO_CHAT_SERVICE_SID != '') {
- $('#chatDemoButton').addClass('btn-success');
- } else {
- $('#chatDemoButton').addClass('btn-danger');
- }
-
- if (response.TWILIO_SYNC_SERVICE_SID && response.TWILIO_SYNC_SERVICE_SID != '') {
- $('#syncDemoButton').addClass('btn-success');
- } else {
- $('#syncDemoButton').addClass('btn-danger');
- }
-
- if (response.TWILIO_NOTIFICATION_SERVICE_SID && response.TWILIO_NOTIFICATION_SERVICE_SID != '') {
- $('#notifyDemoButton').addClass('btn-success');
- } else {
- $('#notifyDemoButton').addClass('btn-danger');
- }
- }
- else {
- $('#videoDemoButton').addClass('btn-danger');
- $('#chatDemoButton').addClass('btn-danger');
- $('#syncDemoButton').addClass('btn-danger');
- $('#notifyDemoButton').addClass('btn-danger');
- }
- });
-
- var configureField = function(response, keyName, elementId, masked) {
- if (masked) {
- if (response[keyName]) {
- $('#' + elementId).html('Configured properly');
- $('#' + elementId).addClass('set');
- } else {
- $('#' + elementId).html('Not configured in .env');
- $('#' + elementId).addClass('unset');
- }
- } else {
- if (response[keyName] && response[keyName] != '') {
- $('#' + elementId).html(response[keyName]);
- $('#' + elementId).addClass('set');
- } else {
- $('#' + elementId).html('Not configured in .env');
- $('#' + elementId).addClass('unset');
- }
- }
+ var configureField = function(fields, response) {
+ var htmlContent = 'Not configured in .env';
+ var cssClass = 'unset';
+ return function(fieldId) {
+ var configKey = strToConfig(fieldId);
+ var isMasked = fields[fieldId];
+ if (!!response[configKey]) {
+ htmlContent = isMasked ? 'Configured properly' : response[configKey];
+ cssClass = 'set';
+ }
+ $('#' + fieldId).html(htmlContent).addClass(cssClass);
};
-});
\ No newline at end of file
+ };
+
+ var configureButton = function(buttons, response) {
+ var hasBasicConfig = !!response.TWILIO_ACCOUNT_SID &&
+ !!response.TWILIO_API_KEY &&
+ !!response.TWILIO_API_SECRET;
+ return function(buttonId) {
+ var configKey = strToConfig(buttons[buttonId]);
+ var cssClass = hasBasicConfig && !!response[configKey]
+ ? 'btn-success'
+ : 'btn-danger';
+ $('#' + buttonId).addClass(cssClass);
+ };
+ };
+
+ var strToConfig = function(string) {
+ return string
+ .split(/(?=[A-Z])/)
+ .map(function(e) { return e.toUpperCase(); })
+ .join('_');
+ }
+});
diff --git a/static/index.html b/static/index.html
index 66c98d3..d46f54b 100644
--- a/static/index.html
+++ b/static/index.html
@@ -1,59 +1,64 @@
-
- Twilio Server Starter Kit
+
+ Twilio Server Starter Kit
-
+
-
+
+
+
+
-
diff --git a/static/sync/index.js b/static/sync/index.js
index d9b2034..766b9f1 100755
--- a/static/sync/index.js
+++ b/static/sync/index.js
@@ -8,53 +8,57 @@ $(function () {
//Our interface to the Sync service
var syncClient;
- //Get an access token for the current user, passing a device ID
- //In browser-based apps, every tab is like its own unique device
- //synchronizing state -- so we'll use a random UUID to identify
- //this tab.
+ // Every browser Sync client relies on FPA tokens to authenticate and authorize it
+ // for access to your Sync data.
+ //
+ // In this quickstart, we're using our own token generator. You can generate a token
+ // in any backend language that Twilio supports, or generate a Twilio Function so
+ // Twilio can host it for you. See the docs for more details.
+ //
$.getJSON('/token', function (tokenResponse) {
- //Initialize the Sync client
+
+ // Once we have the token, we can initialize the Sync client and start subscribing
+ // to data. The client will initialize asynchronously while we load the rest of
+ // the user interface.
+ //
syncClient = new Twilio.Sync.Client(tokenResponse.token, { logLevel: 'info' });
syncClient.on('connectionStateChanged', function(state) {
if (state != 'connected') {
$message.html('Sync is not live (websocket connection ' + state + ')…');
} else {
+ // Now that we're connected, lets light up our board and play!
+ $buttons.attr('disabled', false);
$message.html('Sync is live!');
}
});
- //Let's pop a message on the screen to show that Sync is ready
- $message.html('Sync initialized!');
+ // Let's pop a message on the screen to show that Sync is working
+ $message.html('Loading board data…');
- //Now that Sync is active, lets enable our game board
- $buttons.attr('disabled', false);
-
- //This code will create and/or open a Sync document
- //Note the use of promises
+ // Our game state is stored in a Sync document. Here, we'll attach to that document
+ // (or create it, if it doesn't exist) and connect the necessary event handlers.
+ //
syncClient.document('SyncGame').then(function(syncDoc) {
- //Initialize game board UI to current state (if it exists)
var data = syncDoc.value;
if (data.board) {
updateUserInterface(data);
}
- //Let's subscribe to changes on this document, so when something
- //changes on this document, we can trigger our UI to update
+ // Any time the board changes, we want to show the new state. The 'updated'
+ // event is for this.
syncDoc.on('updated', function(event) {
console.debug("Board was updated", event.isLocal? "locally." : "by the other guy.");
updateUserInterface(event.value);
});
- //Whenever a board button is clicked, update that document.
+ // Let's make our buttons control the game state in Sync…
$buttons.on('click', function (e) {
- //Toggle the value: X, O, or empty
+ // Toggle the value: X, O, or empty
toggleCellValue($(e.target));
- //Send updated document to Sync
- //This should trigger "updated" events on other clients
+ // Send updated document to Sync. This will trigger "updated" events for all players.
var data = readGameBoardFromUserInterface();
syncDoc.set(data);
-
});
});
@@ -84,7 +88,7 @@ $(function () {
for (var row = 0; row < 3; row++) {
for (var col = 0; col < 3; col++) {
var selector = '[data-row="' + row + '"]' +
- '[data-col="' + col + '"]';
+ '[data-col="' + col + '"]';
board[row][col] = $(selector).html().replace(' ', '');
}
}
@@ -96,12 +100,10 @@ $(function () {
function updateUserInterface(data) {
for (var row = 0; row < 3; row++) {
for (var col = 0; col < 3; col++) {
- var selector = '[data-row="' + row + '"]' +
- '[data-col="' + col + '"]';
+ var this_cell = '[data-row="' + row + '"]' + '[data-col="' + col + '"]';
var cellValue = data.board[row][col];
- $(selector).html(cellValue === '' ? ' ' : cellValue);
+ $(this_cell).html(cellValue === '' ? ' ' : cellValue);
}
}
}
-
-});
\ No newline at end of file
+});
diff --git a/static/video/index.html b/static/video/index.html
index 65d81c6..602e825 100755
--- a/static/video/index.html
+++ b/static/video/index.html
@@ -12,17 +12,19 @@
+
Room Name:
+
-
+
diff --git a/static/video/quickstart.js b/static/video/quickstart.js
index 8fb03de..0f1acbd 100755
--- a/static/video/quickstart.js
+++ b/static/video/quickstart.js
@@ -124,8 +124,8 @@ function roomJoined(room) {
// Local video preview
document.getElementById('button-preview').onclick = function() {
var localTracksPromise = previewTracks
- ? Promise.resolve(previewTracks)
- : Twilio.Video.createLocalTracks();
+ ? Promise.resolve(previewTracks)
+ : Twilio.Video.createLocalTracks();
localTracksPromise.then(function(tracks) {
previewTracks = tracks;