You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@guacamole.apache.org by jm...@apache.org on 2017/01/29 20:03:57 UTC
[1/3] incubator-guacamole-client git commit: GUACAMOLE-190: Update
client thumbnail roughly every 5 seconds.
Repository: incubator-guacamole-client
Updated Branches:
refs/heads/master 5776104f4 -> c0e050c65
GUACAMOLE-190: Update client thumbnail roughly every 5 seconds.
Project: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/commit/fd1c652a
Tree: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/tree/fd1c652a
Diff: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/diff/fd1c652a
Branch: refs/heads/master
Commit: fd1c652a84173ac5dc4845dcaf4e0ecc3e456072
Parents: d8f9d26
Author: Michael Jumper <mj...@apache.org>
Authored: Tue Jan 17 10:52:00 2017 -0800
Committer: Michael Jumper <mj...@apache.org>
Committed: Fri Jan 27 19:32:29 2017 -0800
----------------------------------------------------------------------
.../webapp/app/client/types/ManagedClient.js | 140 ++++++++++++-------
.../app/client/types/ManagedClientThumbnail.js | 58 ++++++++
2 files changed, 149 insertions(+), 49 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/fd1c652a/guacamole/src/main/webapp/app/client/types/ManagedClient.js
----------------------------------------------------------------------
diff --git a/guacamole/src/main/webapp/app/client/types/ManagedClient.js b/guacamole/src/main/webapp/app/client/types/ManagedClient.js
index 213a42e..404b597 100644
--- a/guacamole/src/main/webapp/app/client/types/ManagedClient.js
+++ b/guacamole/src/main/webapp/app/client/types/ManagedClient.js
@@ -24,14 +24,15 @@ angular.module('client').factory('ManagedClient', ['$rootScope', '$injector',
function defineManagedClient($rootScope, $injector) {
// Required types
- var ClientProperties = $injector.get('ClientProperties');
- var ClientIdentifier = $injector.get('ClientIdentifier');
- var ClipboardData = $injector.get('ClipboardData');
- var ManagedClientState = $injector.get('ManagedClientState');
- var ManagedDisplay = $injector.get('ManagedDisplay');
- var ManagedFilesystem = $injector.get('ManagedFilesystem');
- var ManagedFileUpload = $injector.get('ManagedFileUpload');
- var ManagedShareLink = $injector.get('ManagedShareLink');
+ var ClientProperties = $injector.get('ClientProperties');
+ var ClientIdentifier = $injector.get('ClientIdentifier');
+ var ClipboardData = $injector.get('ClipboardData');
+ var ManagedClientState = $injector.get('ManagedClientState');
+ var ManagedClientThumbnail = $injector.get('ManagedClientThumbnail');
+ var ManagedDisplay = $injector.get('ManagedDisplay');
+ var ManagedFilesystem = $injector.get('ManagedFilesystem');
+ var ManagedFileUpload = $injector.get('ManagedFileUpload');
+ var ManagedShareLink = $injector.get('ManagedShareLink');
// Required services
var $document = $injector.get('$document');
@@ -46,7 +47,15 @@ angular.module('client').factory('ManagedClient', ['$rootScope', '$injector',
var guacHistory = $injector.get('guacHistory');
var guacImage = $injector.get('guacImage');
var guacVideo = $injector.get('guacVideo');
-
+
+ /**
+ * The minimum amount of time to wait between updates to the client
+ * thumbnail, in milliseconds.
+ *
+ * @type Number
+ */
+ var THUMBNAIL_UPDATE_FREQUENCY = 5000;
+
/**
* Object which serves as a surrogate interface, encapsulating a Guacamole
* client while it is active, allowing it to be detached and reattached
@@ -99,6 +108,15 @@ angular.module('client').factory('ManagedClient', ['$rootScope', '$injector',
this.name = template.name;
/**
+ * The most recently-generated thumbnail for this connection, as
+ * stored within the local connection history. If no thumbnail is
+ * stored, this will be null.
+ *
+ * @type ManagedClientThumbnail
+ */
+ this.thumbnail = template.thumbnail;
+
+ /**
* The current clipboard contents.
*
* @type ClipboardData
@@ -228,45 +246,6 @@ angular.module('client').factory('ManagedClient', ['$rootScope', '$injector',
};
/**
- * Store the thumbnail of the given managed client within the connection
- * history under its associated ID. If the client is not connected, this
- * function has no effect.
- *
- * @param {String} managedClient
- * The client whose history entry should be updated.
- */
- var updateHistoryEntry = function updateHistoryEntry(managedClient) {
-
- var display = managedClient.client.getDisplay();
-
- // Update stored thumbnail of previous connection
- if (display && display.getWidth() > 0 && display.getHeight() > 0) {
-
- // Get screenshot
- var canvas = display.flatten();
-
- // Calculate scale of thumbnail (max 320x240, max zoom 100%)
- var scale = Math.min(320 / canvas.width, 240 / canvas.height, 1);
-
- // Create thumbnail canvas
- var thumbnail = $document[0].createElement("canvas");
- thumbnail.width = canvas.width*scale;
- thumbnail.height = canvas.height*scale;
-
- // Scale screenshot to thumbnail
- var context = thumbnail.getContext("2d");
- context.drawImage(canvas,
- 0, 0, canvas.width, canvas.height,
- 0, 0, thumbnail.width, thumbnail.height
- );
-
- guacHistory.updateThumbnail(managedClient.id, thumbnail.toDataURL("image/png"));
-
- }
-
- };
-
- /**
* Requests the creation of a new audio stream, recorded from the user's
* local audio input device. If audio input is supported by the connection,
* an audio stream will be created which will remain open until the remote
@@ -403,12 +382,14 @@ angular.module('client').factory('ManagedClient', ['$rootScope', '$injector',
// Begin streaming audio input if possible
requestAudioStream(client);
+ // Update thumbnail with initial display contents
+ ManagedClient.updateThumbnail(managedClient);
break;
// Update history when disconnecting
case 4: // Disconnecting
case 5: // Disconnected
- updateHistoryEntry(managedClient);
+ ManagedClient.updateThumbnail(managedClient);
break;
}
@@ -431,6 +412,21 @@ angular.module('client').factory('ManagedClient', ['$rootScope', '$injector',
});
};
+ // Automatically update the client thumbnail
+ client.onsync = function syncReceived() {
+
+ var thumbnail = managedClient.thumbnail;
+ var timestamp = new Date().getTime();
+
+ // Update thumbnail if it doesn't exist or is old
+ if (!thumbnail || timestamp - thumbnail.timestamp >= THUMBNAIL_UPDATE_FREQUENCY) {
+ $rootScope.$apply(function updateClientThumbnail() {
+ ManagedClient.updateThumbnail(managedClient);
+ });
+ }
+
+ };
+
// Handle any received clipboard data
client.onclipboard = function clientClipboardReceived(stream, mimetype) {
@@ -651,6 +647,52 @@ angular.module('client').factory('ManagedClient', ['$rootScope', '$injector',
};
+ /**
+ * Store the thumbnail of the given managed client within the connection
+ * history under its associated ID. If the client is not connected, this
+ * function has no effect.
+ *
+ * @param {ManagedClient} managedClient
+ * The client whose history entry should be updated.
+ */
+ ManagedClient.updateThumbnail = function updateThumbnail(managedClient) {
+
+ var display = managedClient.client.getDisplay();
+
+ // Update stored thumbnail of previous connection
+ if (display && display.getWidth() > 0 && display.getHeight() > 0) {
+
+ // Get screenshot
+ var canvas = display.flatten();
+
+ // Calculate scale of thumbnail (max 320x240, max zoom 100%)
+ var scale = Math.min(320 / canvas.width, 240 / canvas.height, 1);
+
+ // Create thumbnail canvas
+ var thumbnail = $document[0].createElement("canvas");
+ thumbnail.width = canvas.width*scale;
+ thumbnail.height = canvas.height*scale;
+
+ // Scale screenshot to thumbnail
+ var context = thumbnail.getContext("2d");
+ context.drawImage(canvas,
+ 0, 0, canvas.width, canvas.height,
+ 0, 0, thumbnail.width, thumbnail.height
+ );
+
+ // Store updated thumbnail within client
+ managedClient.thumbnail = new ManagedClientThumbnail({
+ timestamp : new Date().getTime(),
+ canvas : thumbnail
+ });
+
+ // Update historical thumbnail
+ guacHistory.updateThumbnail(managedClient.id, thumbnail.toDataURL("image/png"));
+
+ }
+
+ };
+
return ManagedClient;
}]);
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/fd1c652a/guacamole/src/main/webapp/app/client/types/ManagedClientThumbnail.js
----------------------------------------------------------------------
diff --git a/guacamole/src/main/webapp/app/client/types/ManagedClientThumbnail.js b/guacamole/src/main/webapp/app/client/types/ManagedClientThumbnail.js
new file mode 100644
index 0000000..fd9b3de
--- /dev/null
+++ b/guacamole/src/main/webapp/app/client/types/ManagedClientThumbnail.js
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * Provides the ManagedClientThumbnail class used by ManagedClient.
+ */
+angular.module('client').factory('ManagedClientThumbnail', [function defineManagedClientThumbnail() {
+
+ /**
+ * Object which represents a thumbnail of the Guacamole client display,
+ * along with the time that the thumbnail was generated.
+ *
+ * @constructor
+ * @param {ManagedClientThumbnail|Object} [template={}]
+ * The object whose properties should be copied within the new
+ * ManagedClientThumbnail.
+ */
+ var ManagedClientThumbnail = function ManagedClientThumbnail(template) {
+
+ // Use empty object by default
+ template = template || {};
+
+ /**
+ * The time that this thumbnail was generated, as the number of
+ * milliseconds elapsed since midnight of January 1, 1970 UTC.
+ *
+ * @type Number
+ */
+ this.timestamp = template.timestamp;
+
+ /**
+ * The thumbnail of the Guacamole client display.
+ *
+ * @type HTMLCanvasElement
+ */
+ this.canvas = template.canvas;
+
+ };
+
+ return ManagedClientThumbnail;
+
+}]);
\ No newline at end of file
[3/3] incubator-guacamole-client git commit: GUACAMOLE-190: Merge
client thumbnail tab favicon.
Posted by jm...@apache.org.
GUACAMOLE-190: Merge client thumbnail tab favicon.
Project: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/commit/c0e050c6
Tree: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/tree/c0e050c6
Diff: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/diff/c0e050c6
Branch: refs/heads/master
Commit: c0e050c65add2a4bd83089cfd4e8527214328bb1
Parents: 5776104 69a25c4
Author: James Muehlner <ja...@guac-dev.org>
Authored: Sun Jan 29 12:01:00 2017 -0800
Committer: James Muehlner <ja...@guac-dev.org>
Committed: Sun Jan 29 12:01:00 2017 -0800
----------------------------------------------------------------------
.../app/client/controllers/clientController.js | 6 +
.../webapp/app/client/types/ManagedClient.js | 140 ++++++++++++------
.../app/client/types/ManagedClientThumbnail.js | 58 ++++++++
.../webapp/app/index/services/iconService.js | 148 +++++++++++++++++++
4 files changed, 303 insertions(+), 49 deletions(-)
----------------------------------------------------------------------
[2/3] incubator-guacamole-client git commit: GUACAMOLE-190:
Synchronize page icon with client thumbnail.
Posted by jm...@apache.org.
GUACAMOLE-190: Synchronize page icon with client thumbnail.
Project: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/commit/69a25c4e
Tree: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/tree/69a25c4e
Diff: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/diff/69a25c4e
Branch: refs/heads/master
Commit: 69a25c4e48f0c4d8fecf9cd7c95a859f30646e4f
Parents: fd1c652
Author: Michael Jumper <mj...@apache.org>
Authored: Tue Jan 17 10:52:46 2017 -0800
Committer: Michael Jumper <mj...@apache.org>
Committed: Fri Jan 27 19:32:35 2017 -0800
----------------------------------------------------------------------
.../app/client/controllers/clientController.js | 6 +
.../webapp/app/index/services/iconService.js | 148 +++++++++++++++++++
2 files changed, 154 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/69a25c4e/guacamole/src/main/webapp/app/client/controllers/clientController.js
----------------------------------------------------------------------
diff --git a/guacamole/src/main/webapp/app/client/controllers/clientController.js b/guacamole/src/main/webapp/app/client/controllers/clientController.js
index 9827de1..a66a0ce 100644
--- a/guacamole/src/main/webapp/app/client/controllers/clientController.js
+++ b/guacamole/src/main/webapp/app/client/controllers/clientController.js
@@ -35,6 +35,7 @@ angular.module('client').controller('clientController', ['$scope', '$routeParams
var clipboardService = $injector.get('clipboardService');
var guacClientManager = $injector.get('guacClientManager');
var guacNotification = $injector.get('guacNotification');
+ var iconService = $injector.get('iconService');
var preferenceService = $injector.get('preferenceService');
var tunnelService = $injector.get('tunnelService');
var userPageService = $injector.get('userPageService');
@@ -403,6 +404,11 @@ angular.module('client').controller('clientController', ['$scope', '$routeParams
});
+ // Update page icon when thumbnail changes
+ $scope.$watch('client.thumbnail.canvas', function thumbnailChanged(canvas) {
+ iconService.setIcons(canvas);
+ });
+
// Watch clipboard for new data, associating it with any pressed keys
$scope.$watch('client.clipboardData', function clipboardChanged(data) {
http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/69a25c4e/guacamole/src/main/webapp/app/index/services/iconService.js
----------------------------------------------------------------------
diff --git a/guacamole/src/main/webapp/app/index/services/iconService.js b/guacamole/src/main/webapp/app/index/services/iconService.js
new file mode 100644
index 0000000..ed9e057
--- /dev/null
+++ b/guacamole/src/main/webapp/app/index/services/iconService.js
@@ -0,0 +1,148 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * A service for updating or resetting the favicon of the current page.
+ */
+angular.module('index').factory('iconService', ['$rootScope', function iconService($rootScope) {
+
+ var service = {};
+
+ /**
+ * The URL of the image used for the low-resolution (64x64) favicon. This
+ * MUST match the URL which is set statically within index.html.
+ *
+ * @constant
+ * @type String
+ */
+ var DEFAULT_SMALL_ICON_URL = 'images/logo-64.png';
+
+ /**
+ * The URL of the image used for the high-resolution (144x144) favicon. This
+ * MUST match the URL which is set statically within index.html.
+ *
+ * @constant
+ * @type String
+ */
+ var DEFAULT_LARGE_ICON_URL = 'images/logo-144.png';
+
+ /**
+ * JQuery-wrapped array of all link tags which point to the small,
+ * low-resolution page icon.
+ *
+ * @type Element[]
+ */
+ var smallIcons = $('link[rel=icon][href="' + DEFAULT_SMALL_ICON_URL + '"]');
+
+ /**
+ * JQuery-wrapped array of all link tags which point to the large,
+ * high-resolution page icon.
+ *
+ * @type Element[]
+ */
+ var largeIcons = $('link[rel=icon][href="' + DEFAULT_LARGE_ICON_URL + '"]');
+
+ /**
+ * Generates an icon by scaling the provided image to fit the given
+ * dimensions, returning a canvas containing the generated icon.
+ *
+ * @param {HTMLCanvasElement} canvas
+ * A canvas element containing the image which should be scaled to
+ * produce the contents of the generated icon.
+ *
+ * @param {Number} width
+ * The width of the icon to generate, in pixels.
+ *
+ * @param {Number} height
+ * The height of the icon to generate, in pixels.
+ *
+ * @returns {HTMLCanvasElement}
+ * A new canvas element having the given dimensions and containing the
+ * provided image, scaled to fit.
+ */
+ var generateIcon = function generateIcon(canvas, width, height) {
+
+ // Create icon canvas having the provided dimensions
+ var icon = document.createElement('canvas');
+ icon.width = width;
+ icon.height = height;
+
+ // Calculate the scale factor necessary to fit the provided image
+ // within the icon dimensions
+ var scale = Math.min(width / canvas.width, height / canvas.height);
+
+ // Calculate the dimensions and position of the scaled image within
+ // the icon, offsetting the image such that it is centered
+ var scaledWidth = canvas.width * scale;
+ var scaledHeight = canvas.height * scale;
+ var offsetX = (width - scaledWidth) / 2;
+ var offsetY = (height - scaledHeight) / 2;
+
+ // Draw the icon, scaling the provided image as necessary
+ var context = icon.getContext('2d');
+ context.drawImage(canvas, offsetX, offsetY, scaledWidth, scaledHeight);
+ return icon;
+
+ };
+
+ /**
+ * Temporarily sets the icon of the current page to the contents of the
+ * given canvas element. The image within the canvas element will be
+ * automatically scaled and centered to fit within the dimensions of the
+ * page icons. The page icons will be automatically reset to their original
+ * values upon navigation.
+ *
+ * @param {HTMLCanvasElement} canvas
+ * The canvas element containing the icon. If this value is null or
+ * undefined, this function has no effect.
+ */
+ service.setIcons = function setIcons(canvas) {
+
+ // Do nothing if no canvas provided
+ if (!canvas)
+ return;
+
+ // Assign low-resolution (64x64) icon
+ var smallIcon = generateIcon(canvas, 64, 64);
+ smallIcons.attr('href', smallIcon.toDataURL('image/png'));
+
+ // Assign high-resolution (144x144) icon
+ var largeIcon = generateIcon(canvas, 144, 144);
+ largeIcons.attr('href', largeIcon.toDataURL('image/png'));
+
+ };
+
+ /**
+ * Resets the icons of the current page to their original values, undoing
+ * any previous calls to setIcons(). This function is automatically invoked
+ * upon navigation.
+ */
+ service.setDefaultIcons = function setDefaultIcons() {
+ smallIcons.attr('href', DEFAULT_SMALL_ICON_URL);
+ largeIcons.attr('href', DEFAULT_LARGE_ICON_URL);
+ };
+
+ // Automatically reset page icons after navigation
+ $rootScope.$on('$routeChangeSuccess', function resetIcon() {
+ service.setDefaultIcons();
+ });
+
+ return service;
+
+}]);