mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 05:07:41 +00:00
GUACAMOLE-1293: Merge client support for join/leave notifications.
This commit is contained in:
@@ -688,6 +688,21 @@ Guacamole.Client = function(tunnel) {
|
||||
*/
|
||||
this.onerror = null;
|
||||
|
||||
/**
|
||||
* Fired when an arbitrary message is received from the tunnel that should
|
||||
* be processed by the client.
|
||||
*
|
||||
* @event
|
||||
* @param {!number} msgcode
|
||||
* A status code sent by the remote server that indicates the nature of
|
||||
* the message that is being sent to the client.
|
||||
*
|
||||
* @param {string[]} args
|
||||
* An array of arguments to be processed with the message sent to the
|
||||
* client.
|
||||
*/
|
||||
this.onmsg = null;
|
||||
|
||||
/**
|
||||
* Fired when a audio stream is created. The stream provided to this event
|
||||
* handler will contain its own event handlers for received data.
|
||||
@@ -1400,6 +1415,12 @@ Guacamole.Client = function(tunnel) {
|
||||
|
||||
},
|
||||
|
||||
"msg" : function(parameters) {
|
||||
|
||||
if (guac_client.onmsg) guac_client.onmsg(parseInt(parameters[0]), parameters.slice(1));
|
||||
|
||||
},
|
||||
|
||||
"name": function(parameters) {
|
||||
if (guac_client.onname) guac_client.onname(parameters[0]);
|
||||
},
|
||||
@@ -1824,3 +1845,31 @@ Guacamole.Client.DefaultTransferFunction = {
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* A list of possible messages that can be sent by the server for processing
|
||||
* by the client.
|
||||
*
|
||||
* @type {!Object.<string, number>}
|
||||
*/
|
||||
Guacamole.Client.Message = {
|
||||
|
||||
/**
|
||||
* A client message that indicates that a user has joined an existing
|
||||
* connection. This message expects a single additional argument - the
|
||||
* name of the user who has joined the connection.
|
||||
*
|
||||
* @type {!number}
|
||||
*/
|
||||
"USER_JOINED": 0x0001,
|
||||
|
||||
/**
|
||||
* A client message that indicates that a user has left an existing
|
||||
* connection. This message expects a single additional argument - the
|
||||
* name of the user who has left the connection.
|
||||
*
|
||||
* @type {!number}
|
||||
*/
|
||||
"USER_LEFT": 0x0002
|
||||
|
||||
};
|
||||
|
@@ -293,7 +293,14 @@ public class ConfiguredGuacamoleSocket extends DelegatingGuacamoleSocket {
|
||||
if (GuacamoleProtocolCapability.TIMEZONE_HANDSHAKE.isSupported(protocolVersion)) {
|
||||
String timezone = info.getTimezone();
|
||||
if (timezone != null)
|
||||
writer.writeInstruction(new GuacamoleInstruction("timezone", info.getTimezone()));
|
||||
writer.writeInstruction(new GuacamoleInstruction("timezone", timezone));
|
||||
}
|
||||
|
||||
// Send client name, if supported and available
|
||||
if (GuacamoleProtocolCapability.NAME_HANDSHAKE.isSupported(protocolVersion)) {
|
||||
String name = info.getName();
|
||||
if (name != null)
|
||||
writer.writeInstruction(new GuacamoleInstruction("name", name));
|
||||
}
|
||||
|
||||
// Send args
|
||||
|
@@ -47,17 +47,22 @@ public class GuacamoleClientInformation {
|
||||
/**
|
||||
* The list of audio mimetypes reported by the client to be supported.
|
||||
*/
|
||||
private final List<String> audioMimetypes = new ArrayList<String>();
|
||||
private final List<String> audioMimetypes = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* The list of video mimetypes reported by the client to be supported.
|
||||
*/
|
||||
private final List<String> videoMimetypes = new ArrayList<String>();
|
||||
private final List<String> videoMimetypes = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* The list of image mimetypes reported by the client to be supported.
|
||||
*/
|
||||
private final List<String> imageMimetypes = new ArrayList<String>();
|
||||
private final List<String> imageMimetypes = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* The name of the user reported by the client.
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* The timezone reported by the client.
|
||||
@@ -150,6 +155,17 @@ public class GuacamoleClientInformation {
|
||||
return imageMimetypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the Guacamole user as reported by the client, or null
|
||||
* if the user name is not set.
|
||||
*
|
||||
* @return
|
||||
* A string value of the human-readable name reported by the client.
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the timezone as reported by the client, or null if the timezone
|
||||
* is not set. Valid timezones are specified in IANA zone key format,
|
||||
@@ -162,6 +178,16 @@ public class GuacamoleClientInformation {
|
||||
return timezone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the human-readable name of the user associated with this client.
|
||||
*
|
||||
* @param name
|
||||
* The human-readable name of the user associated with this client.
|
||||
*/
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the string value of the timezone, or null if the timezone will not
|
||||
* be provided by the client. Valid timezones are specified in IANA zone
|
||||
|
@@ -33,6 +33,21 @@ public enum GuacamoleProtocolCapability {
|
||||
*/
|
||||
ARBITRARY_HANDSHAKE_ORDER(GuacamoleProtocolVersion.VERSION_1_1_0),
|
||||
|
||||
/**
|
||||
* Support for the "msg" instruction. The "msg" instruction allows the
|
||||
* server to send messages to the client. Support for this instruction was
|
||||
* introduced in {@link GuacamoleProtocolVersion#VERSION_1_5_0}.
|
||||
*/
|
||||
MSG_INSTRUCTION(GuacamoleProtocolVersion.VERSION_1_5_0),
|
||||
|
||||
/**
|
||||
* Support for the "name" handshake instruction, allowing clients to send
|
||||
* the name of the Guacamole user to be passed to guacd and associated with
|
||||
* connections. Support for this instruction was introduced in
|
||||
* {@link GuacamoleProtocolVersion#VERSION_1_5_0}.
|
||||
*/
|
||||
NAME_HANDSHAKE(GuacamoleProtocolVersion.VERSION_1_5_0),
|
||||
|
||||
/**
|
||||
* Negotiation of Guacamole protocol version between client and server
|
||||
* during the protocol handshake. The ability to negotiate protocol
|
||||
|
@@ -53,11 +53,20 @@ public class GuacamoleProtocolVersion {
|
||||
*/
|
||||
public static final GuacamoleProtocolVersion VERSION_1_3_0 = new GuacamoleProtocolVersion(1, 3, 0);
|
||||
|
||||
/**
|
||||
* Protocol version 1.5.0, which introduces the "msg" instruction, allowing
|
||||
* the server to send message notifications that will be displayed on the
|
||||
* client. The version also adds support for the "name" handshake
|
||||
* instruction, allowing guacd to store the name of the user who is
|
||||
* accessing the connection.
|
||||
*/
|
||||
public static final GuacamoleProtocolVersion VERSION_1_5_0 = new GuacamoleProtocolVersion(1, 5, 0);
|
||||
|
||||
/**
|
||||
* The most recent version of the Guacamole protocol at the time this
|
||||
* version of GuacamoleProtocolVersion was built.
|
||||
*/
|
||||
public static final GuacamoleProtocolVersion LATEST = VERSION_1_3_0;
|
||||
public static final GuacamoleProtocolVersion LATEST = VERSION_1_5_0;
|
||||
|
||||
/**
|
||||
* A regular expression that matches the VERSION_X_Y_Z pattern, where
|
||||
|
@@ -792,6 +792,24 @@ angular.module('client').controller('clientController', ['$scope', '$routeParams
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines whether the attached client group has any associated client
|
||||
* messages to display.
|
||||
*
|
||||
* @returns {Boolean}
|
||||
* true if there are messages to display; otherwise false.
|
||||
*/
|
||||
$scope.hasMessages = function hasMessages() {
|
||||
|
||||
// No client group means no messages
|
||||
if (!$scope.clientGroup)
|
||||
return false;
|
||||
|
||||
// Otherwise, find messages within the clients in the group.
|
||||
return _.findIndex($scope.clientGroup.clients, ManagedClient.hasMessages) !== -1;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines whether the attached client group has any associated file
|
||||
* transfers, regardless of those file transfers' state.
|
||||
|
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Directive which displays a message for the client.
|
||||
*/
|
||||
angular.module('client').directive('guacClientMessage', [function guacClientMessage() {
|
||||
|
||||
return {
|
||||
restrict: 'E',
|
||||
replace: true,
|
||||
scope: {
|
||||
|
||||
/**
|
||||
* The message to display to the client.
|
||||
*
|
||||
* @type {!ManagedClientMessage}
|
||||
*/
|
||||
message : '='
|
||||
|
||||
},
|
||||
|
||||
templateUrl: 'app/client/templates/guacClientMessage.html',
|
||||
|
||||
controller: ['$scope', '$injector', '$element',
|
||||
function guacClientMessageController($scope, $injector, $element) {
|
||||
|
||||
// Required types
|
||||
const ManagedClientMessage = $injector.get('ManagedClientMessage');
|
||||
|
||||
// Required services
|
||||
var translationStringService = $injector.get('translationStringService');
|
||||
|
||||
/**
|
||||
* Uses the msgcode to retrieve the correct translation key for
|
||||
* the client message.
|
||||
*
|
||||
* @returns {string}
|
||||
*/
|
||||
$scope.getMessageKey = function getMessageKey() {
|
||||
|
||||
let msgString = "DEFAULT";
|
||||
if (Object.values(Guacamole.Client.Message).includes($scope.message.msgcode))
|
||||
msgString = Object.keys(Guacamole.Client.Message).find(key => Guacamole.Client.Message[key] === $scope.message.msgcode);
|
||||
|
||||
return "CLIENT.MESSAGE_" + translationStringService.canonicalize(msgString);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a set of key/value object pairs that represent the
|
||||
* arguments provided as part of the message in the form
|
||||
* "ARGS_0 = value". Guacamole's translation system relies on
|
||||
* the arguments being available in this format in order to be able
|
||||
* to handle substituting values for an arbitrary list of arguments.
|
||||
*
|
||||
* @returns {Object}
|
||||
*/
|
||||
$scope.getMessageArgs = function getMessageArgs() {
|
||||
return $scope.message.args.reduce(
|
||||
function(acc, value, index) {
|
||||
acc[`ARGS_${index}`] = value;
|
||||
return acc;
|
||||
},
|
||||
{}
|
||||
);
|
||||
};
|
||||
|
||||
}]
|
||||
|
||||
};
|
||||
}]);
|
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Directive which displays all client messages.
|
||||
*/
|
||||
angular.module('client').directive('guacMessageDialog', [function guacMessageDialog() {
|
||||
|
||||
return {
|
||||
restrict: 'E',
|
||||
replace: true,
|
||||
scope: {
|
||||
|
||||
/**
|
||||
* The client group whose messages should be managed by this
|
||||
* directive.
|
||||
*
|
||||
* @type ManagedClientGroup
|
||||
*/
|
||||
clientGroup : '='
|
||||
|
||||
},
|
||||
|
||||
templateUrl: 'app/client/templates/guacMessageDialog.html',
|
||||
controller: ['$scope', '$injector', function guacMessageDialogController($scope, $injector) {
|
||||
|
||||
// Required types
|
||||
const ManagedClient = $injector.get('ManagedClient');
|
||||
const ManagedClientGroup = $injector.get('ManagedClientGroup');
|
||||
|
||||
/**
|
||||
* Removes all messages.
|
||||
*/
|
||||
$scope.clearAllMessages = function clearAllMessages() {
|
||||
|
||||
// Nothing to clear if no client group attached
|
||||
if (!$scope.clientGroup)
|
||||
return;
|
||||
|
||||
// Remove each client's messages
|
||||
$scope.clientGroup.clients.forEach(client => {
|
||||
client.messages = [];
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @borrows ManagedClientGroup.hasMultipleClients
|
||||
*/
|
||||
$scope.hasMultipleClients = ManagedClientGroup.hasMultipleClients;
|
||||
|
||||
/**
|
||||
* @borrows ManagedClient.hasMessages
|
||||
*/
|
||||
$scope.hasMessages = ManagedClient.hasMessages;
|
||||
|
||||
}]
|
||||
|
||||
};
|
||||
}]);
|
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
p.client-message-text {
|
||||
margin: 5px;
|
||||
}
|
||||
|
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#message-dialog {
|
||||
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 20;
|
||||
|
||||
font-size: 0.8em;
|
||||
|
||||
width: 3in;
|
||||
max-width: 100%;
|
||||
max-height: 3in;
|
||||
|
||||
background: white;
|
||||
opacity: 0.75;
|
||||
|
||||
}
|
||||
|
||||
#message-dialog .message-dialog-box {
|
||||
|
||||
/* IE10 */
|
||||
display: -ms-flexbox;
|
||||
-ms-flex-align: stretch;
|
||||
-ms-flex-direction: column;
|
||||
|
||||
/* Ancient Mozilla */
|
||||
display: -moz-box;
|
||||
-moz-box-align: stretch;
|
||||
-moz-box-orient: vertical;
|
||||
|
||||
/* Ancient WebKit */
|
||||
display: -webkit-box;
|
||||
-webkit-box-align: stretch;
|
||||
-webkit-box-orient: vertical;
|
||||
|
||||
/* Old WebKit */
|
||||
display: -webkit-flex;
|
||||
-webkit-align-items: stretch;
|
||||
-webkit-flex-direction: column;
|
||||
|
||||
/* W3C */
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
flex-direction: column;
|
||||
|
||||
max-width: inherit;
|
||||
max-height: inherit;
|
||||
|
||||
border: 1px solid rgba(0, 0, 0, 0.5);
|
||||
box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.25);
|
||||
|
||||
}
|
||||
|
||||
#message-dialog .message-dialog-box .header {
|
||||
-ms-flex: 0 0 auto;
|
||||
-moz-box-flex: 0;
|
||||
-webkit-box-flex: 0;
|
||||
-webkit-flex: 0 0 auto;
|
||||
flex: 0 0 auto;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
#message-dialog .message-dialog-box .client-message-body {
|
||||
|
||||
-ms-flex: 1 1 auto;
|
||||
-moz-box-flex: 1;
|
||||
-webkit-box-flex: 1;
|
||||
-webkit-flex: 1 1 auto;
|
||||
flex: 1 1 auto;
|
||||
|
||||
overflow: auto;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Shrink maximum height if viewport is too small for default 3in dialog.
|
||||
*/
|
||||
@media all and (max-height: 3in) {
|
||||
|
||||
#message-dialog {
|
||||
max-height: 1.5in;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* If viewport is too small for even the 1.5in dialog, fit all available space.
|
||||
*/
|
||||
@media all and (max-height: 1.5in) {
|
||||
|
||||
#message-dialog {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#message-dialog .message-dialog-box {
|
||||
position: absolute;
|
||||
left: 0.5em;
|
||||
top: 0.5em;
|
||||
right: 0.5em;
|
||||
bottom: 0.5em;
|
||||
}
|
||||
|
||||
}
|
@@ -45,6 +45,11 @@
|
||||
{{'CLIENT.TEXT_CLIENT_STATUS_UNSTABLE' | translate}}
|
||||
</div>
|
||||
|
||||
<!-- Message dialog -->
|
||||
<div id="message-dialog" ng-show="hasMessages()">
|
||||
<guac-message-dialog client-group="clientGroup"></guac-message-dialog>
|
||||
</div>
|
||||
|
||||
<!-- Menu -->
|
||||
<div class="menu" ng-class="{open: menu.shown}" id="guac-menu">
|
||||
<div class="menu-content" ng-if="menu.shown" guac-touch-drag="menuDrag">
|
||||
|
@@ -0,0 +1,8 @@
|
||||
<div class="client-message" ng-click="clear()">
|
||||
|
||||
<!-- Message text -->
|
||||
<p class="client-message-text"
|
||||
translate="{{ getMessageKey() }}"
|
||||
translate-values="{{ getMessageArgs() }}"></p>
|
||||
|
||||
</div>
|
@@ -0,0 +1,21 @@
|
||||
<div class="message-dialog-box">
|
||||
|
||||
<!-- Message dialog header -->
|
||||
<div class="header">
|
||||
<h2>{{'CLIENT.SECTION_HEADER_CLIENT_MESSAGES' | translate}}</h2>
|
||||
<button ng-click="clearAllMessages()">{{'CLIENT.ACTION_CLEAR_CLIENT_MESSAGES' | translate}}</button>
|
||||
</div>
|
||||
|
||||
<!-- Received messages -->
|
||||
<div class="client-messages-body">
|
||||
<div class="client-messages-body-section" ng-repeat="client in clientGroup.clients" ng-show="hasMessages(client)">
|
||||
<h3 ng-show="hasMultipleClients(clientGroup)">{{ client.name }}</h3>
|
||||
<div class="messages">
|
||||
<guac-client-message
|
||||
message="message"
|
||||
ng-repeat="message in client.messages">
|
||||
</guac-client-message>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@@ -28,6 +28,7 @@ angular.module('client').factory('ManagedClient', ['$rootScope', '$injector',
|
||||
const ClientIdentifier = $injector.get('ClientIdentifier');
|
||||
const ClipboardData = $injector.get('ClipboardData');
|
||||
const ManagedArgument = $injector.get('ManagedArgument');
|
||||
const ManagedClientMessage = $injector.get('ManagedClientMessage');
|
||||
const ManagedClientState = $injector.get('ManagedClientState');
|
||||
const ManagedClientThumbnail = $injector.get('ManagedClientThumbnail');
|
||||
const ManagedDisplay = $injector.get('ManagedDisplay');
|
||||
@@ -174,6 +175,14 @@ angular.module('client').factory('ManagedClient', ['$rootScope', '$injector',
|
||||
*/
|
||||
this.filesystems = template.filesystems || [];
|
||||
|
||||
/**
|
||||
* All messages that have been sent to the client that should be
|
||||
* displayed.
|
||||
*
|
||||
* @type ManagedClientMessage[]
|
||||
*/
|
||||
this.messages = template.messages || [];
|
||||
|
||||
/**
|
||||
* All available share links generated for the this ManagedClient via
|
||||
* ManagedClient.createShareLink(). Each resulting share link is stored
|
||||
@@ -487,6 +496,19 @@ angular.module('client').factory('ManagedClient', ['$rootScope', '$injector',
|
||||
});
|
||||
};
|
||||
|
||||
// Handle messages received from guacd to display to the client.
|
||||
client.onmsg = function clientMessage(msgcode, args) {
|
||||
|
||||
msg = new ManagedClientMessage();
|
||||
msg.msgcode = msgcode;
|
||||
msg.args = args;
|
||||
|
||||
$rootScope.$apply(function updateMessages() {
|
||||
managedClient.messages.push(msg);
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
// Automatically update the client thumbnail
|
||||
client.onsync = function syncReceived() {
|
||||
|
||||
@@ -893,10 +915,26 @@ angular.module('client').factory('ManagedClient', ['$rootScope', '$injector',
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns whether the given client has any associated messages to display.
|
||||
*
|
||||
* @param {GuacamoleClient} client
|
||||
* The client for which messages should be checked.
|
||||
*
|
||||
* @returns {Boolean}
|
||||
* true if the given client has any messages, otherwise false.
|
||||
*/
|
||||
ManagedClient.hasMessages = function hasMessages(client) {
|
||||
return !!(client && client.messages && client.messages.length);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns whether the given client has any associated file transfers,
|
||||
* regardless of those file transfers' state.
|
||||
*
|
||||
* @param {GuacamoleClient} client
|
||||
* The client for which file transfers should be checked.
|
||||
*
|
||||
* @returns {boolean}
|
||||
* true if there are any file transfers associated with the
|
||||
* given client, false otherwise.
|
||||
|
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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 ManagedClientMessage class used for messages displayed in
|
||||
* a ManagedClient.
|
||||
*/
|
||||
angular.module('client').factory('ManagedClientMessage', [function defineManagedClientMessage() {
|
||||
|
||||
/**
|
||||
* Object which represents a message to be displayed to a Guacamole client.
|
||||
*
|
||||
* @constructor
|
||||
* @param {ManagedClientMessage|Object} [template={}]
|
||||
* The object whose properties should be copied within the new
|
||||
* ManagedClientMessage.
|
||||
*/
|
||||
var ManagedClientMessage = function ManagedClientMessage(template) {
|
||||
|
||||
// Use empty object by default
|
||||
template = template || {};
|
||||
|
||||
/**
|
||||
* The message code sent by the server that will be used to locate the
|
||||
* message within the Guacamole translation framework.
|
||||
*
|
||||
* @type Number
|
||||
*/
|
||||
this.msgcode = template.msgcode;
|
||||
|
||||
/**
|
||||
* Any arguments that should be passed through the translation system
|
||||
* and displayed as part of the message.
|
||||
*
|
||||
* @type String[]
|
||||
*/
|
||||
this.args = template.args;
|
||||
|
||||
};
|
||||
|
||||
return ManagedClientMessage;
|
||||
|
||||
}]);
|
@@ -60,6 +60,7 @@
|
||||
|
||||
"ACTION_ACKNOWLEDGE" : "@:APP.ACTION_ACKNOWLEDGE",
|
||||
"ACTION_CANCEL" : "@:APP.ACTION_CANCEL",
|
||||
"ACTION_CLEAR_CLIENT_MESSAGES" : "Clear",
|
||||
"ACTION_CLEAR_COMPLETED_TRANSFERS" : "Clear",
|
||||
"ACTION_CONTINUE" : "@:APP.ACTION_CONTINUE",
|
||||
"ACTION_DISCONNECT" : "Disconnect",
|
||||
@@ -128,6 +129,10 @@
|
||||
"INFO_CONNECTION_SHARED" : "This connection is now shared.",
|
||||
"INFO_NO_FILE_TRANSFERS" : "No file transfers.",
|
||||
|
||||
"MESSAGE_DEFAULT" : "",
|
||||
"MESSAGE_USER_JOINED" : "User {ARGS_1} has joined the connection.",
|
||||
"MESSAGE_USER_LEFT" : "User {ARGS_1} has left the connection.",
|
||||
|
||||
"NAME_INPUT_METHOD_NONE" : "None",
|
||||
"NAME_INPUT_METHOD_OSK" : "On-screen keyboard",
|
||||
"NAME_INPUT_METHOD_TEXT" : "Text input",
|
||||
@@ -138,11 +143,13 @@
|
||||
"NAME_MOUSE_MODE_ABSOLUTE" : "Touchscreen",
|
||||
"NAME_MOUSE_MODE_RELATIVE" : "Touchpad",
|
||||
|
||||
"SECTION_HEADER_CLIENT_MESSAGES" : "Messages",
|
||||
"SECTION_HEADER_CLIPBOARD" : "Clipboard",
|
||||
"SECTION_HEADER_DEVICES" : "Devices",
|
||||
"SECTION_HEADER_DISPLAY" : "Display",
|
||||
"SECTION_HEADER_FILE_TRANSFERS" : "File Transfers",
|
||||
"SECTION_HEADER_INPUT_METHOD" : "Input method",
|
||||
|
||||
"SECTION_HEADER_MOUSE_MODE" : "Mouse emulation mode",
|
||||
|
||||
"TEXT_ZOOM_AUTO_FIT" : "Automatically fit to browser window",
|
||||
|
@@ -341,6 +341,11 @@ public class TunnelRequestService {
|
||||
AuthenticatedUser authenticatedUser = session.getAuthenticatedUser();
|
||||
UserContext userContext = session.getUserContext(authProviderIdentifier);
|
||||
|
||||
// Attempt to get the user's name and set it for the tunnel client.
|
||||
String name = authenticatedUser.getIdentifier();
|
||||
if (name != null)
|
||||
info.setName(name);
|
||||
|
||||
try {
|
||||
|
||||
// Create connected tunnel using provided connection ID and client information
|
||||
|
Reference in New Issue
Block a user