GUACAMOLE-724: Replace CSS grid layout with simpler, equialent, and more compatible flex layout.

This commit is contained in:
Michael Jumper
2021-07-03 13:58:54 -07:00
parent 760a96a47d
commit 1f2007eb28
4 changed files with 108 additions and 79 deletions

View File

@@ -150,24 +150,14 @@ angular.module('client').directive('guacTiledClients', [function guacTiledClient
$scope.hasMultipleClients = ManagedClientGroup.hasMultipleClients;
/**
* @borrows ManagedClientGroup.getTileGridCSS
* @borrows ManagedClientGroup.getClientGrid
*/
$scope.getTileGridCSS = ManagedClientGroup.getTileGridCSS;
$scope.getClientGrid = ManagedClientGroup.getClientGrid;
/**
* Returns whether the given ManagedClient has any associated share
* links.
*
* @param {ManagedClient} client
* The ManagedClient to test.
*
* @returns {Boolean}
* true if the given ManagedClient has at least one associated
* share link, false otherwise.
* @borrows ManagedClient.isShared
*/
$scope.isShared = function isShared(client) {
return ManagedClient.isShared(client);
};
$scope.isShared = ManagedClient.isShared;
}];

View File

@@ -17,13 +17,50 @@
* under the License.
*/
.tiled-client-list {
padding: 0;
margin: 0;
line-height: 0;
/*
* Overall tiled grid layout.
*/
.tiled-client-grid {
width: 100%;
height: 100%;
}
.tiled-client-list li.client-tile {
.tiled-client-grid,
.tiled-client-grid .tiled-client-row,
.tiled-client-grid .tiled-client-cell,
.tiled-client-grid .client-tile {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-box-flex: 1;
-webkit-flex: 1;
-ms-flex: 1;
flex: 1;
}
.tiled-client-grid {
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
}
.tiled-client-grid .tiled-client-row {
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-webkit-flex-direction: row;
-ms-flex-direction: row;
flex-direction: row;
}
/*
* Rendering of individual clients within tiles.
*/
.tiled-client-grid .client-tile {
position: relative;
display: -webkit-box;
display: -webkit-flex;
@@ -37,7 +74,7 @@
line-height: 1.5;
}
.tiled-client-list li.client-tile .client-tile-name {
.tiled-client-grid .client-tile .client-tile-name {
margin: 0;
background: #444;
padding: 0 0.25em;
@@ -46,35 +83,35 @@
display: none;
}
.tiled-client-list.multiple-clients li.client-tile .client-tile-name {
.tiled-client-grid.multiple-clients .client-tile .client-tile-name {
display: block;
}
.tiled-client-list.multiple-clients li.client-tile {
.tiled-client-grid.multiple-clients .client-tile {
border: 1px solid #444;
}
.tiled-client-list li.client-tile.focused {
.tiled-client-grid .client-tile.focused {
border-color: #3161a9;
}
.tiled-client-list li.client-tile.focused .client-tile-name {
.tiled-client-grid .client-tile.focused .client-tile-name {
background-color: #3161a9;
}
.tiled-client-list li.client-tile .main {
.tiled-client-grid .client-tile .main {
-webkit-box-flex: 1;
-webkit-flex: 1;
-ms-flex: 1;
flex: 1;
}
.tiled-client-list .client-tile-shared-indicator {
.tiled-client-grid .client-tile-shared-indicator {
display: none;
max-height: 1em;
height: 100%;
}
.tiled-client-list .shared .client-tile-shared-indicator {
.tiled-client-grid .shared .client-tile-shared-indicator {
display: inline;
}

View File

@@ -1,22 +1,23 @@
<ul class="tiled-client-list"
ng-class="{ 'multiple-clients' : hasMultipleClients(clientGroup) }"
ng-attr-style="{{ getTileGridCSS(clientGroup) }}">
<div class="tiled-client-grid"
ng-class="{ 'multiple-clients' : hasMultipleClients(clientGroup) }">
<li class="client-tile"
ng-repeat="client in clientGroup.clients"
ng-class="{
'focused' : client.clientProperties.focused,
'shared' : isShared(client)
}"
ng-attr-style="{{ getTileGridCSS(clientGroup, $index) }}"
guac-click="getFocusAssignmentCallback(client)">
<div class="tiled-client-row" ng-repeat="clientRow in getClientGrid(clientGroup)">
<div class="tiled-client-cell" ng-repeat="client in clientRow">
<h3 class="client-tile-name"><img class="client-tile-shared-indicator" src="images/share-white.svg"> {{ client.title }}</h3>
<guac-client client="client" emulate-absolute-mouse="emulateAbsoluteMouse"></guac-client>
<div class="client-tile" ng-if="client"
ng-class="{
'focused' : client.clientProperties.focused,
'shared' : isShared(client)
}"
guac-click="getFocusAssignmentCallback(client)">
<h3 class="client-tile-name"><img class="client-tile-shared-indicator" src="images/share-white.svg"> {{ client.title }}</h3>
<guac-client client="client" emulate-absolute-mouse="emulateAbsoluteMouse"></guac-client>
<!-- Client-specific status/error dialog -->
<guac-client-notification client="client"></guac-client-notification>
<!-- Client-specific status/error dialog -->
<guac-client-notification client="client"></guac-client-notification>
</div>
</li>
</div>
</div>
</ul>
</div>

View File

@@ -282,47 +282,48 @@ angular.module('client').factory('ManagedClientGroup', ['$injector', function de
};
/**
* Returns the CSS that should used to achieve a proper grid arrangement
* of the client tiles represented by the given ManagedClientGroup. The
* CSS should be assigned to the element displaying the given
* ManagedClientGroup or, if an index is provided, the element representing
* the client having the given index within the group.
*
* NOTE: Much of this is unnecessary if support for IE is dropped. When
* that is eventually unavoidable (migration to Angular), this can be
* simplified.
* Returns a two-dimensional array of all ManagedClients within the given
* group, arranged in the grid defined by {@link ManagedClientGroup#rows}
* and {@link ManagedClientGroup#columns}. If any grid cell lacks a
* corresponding client (because the number of clients does not divide
* evenly into a grid), that cell will be null.
*
* For the sake of AngularJS scope watches, the results of calling this
* function are cached and will always favor modifying an existing array
* over creating a new array, even for nested arrays.
*
* @param {ManagedClientGroup} group
* The ManagedClientGroup to determine CSS for.
* The ManagedClientGroup defining the tiled grid arrangement of
* ManagedClients.
*
* @param {number} [index]
* The index of the relevant client within the group, if not producing
* CSS for the group itself.
*
* @returns {string}
* The CSS that should be assigned to the element representing the
* given group or, if an index is provided, the CSS that should be
* assigned to the element representing the client having the given
* index within the group.
* @returns {ManagedClient[][]}
* A two-dimensional array of all ManagedClients within the given
* group.
*/
ManagedClientGroup.getTileGridCSS = function getTileGridCSS(group, index) {
ManagedClientGroup.getClientGrid = function getClientGrid(group) {
// Produce CSS defining a regular grid if no specific client is
// requested
if (arguments.length <= 1)
return 'display: -ms-grid;'
+ 'display: grid;'
+ '-ms-grid-rows: (1fr)[' + group.rows + '];'
+ 'grid-template-rows: repeat(' + group.rows + ', 1fr);'
+ '-ms-grid-columns: (1fr)[' + group.columns + '];'
+ 'grid-template-columns: repeat(' + group.columns + ', 1fr);';
var index = 0;
// For IE10+, the row/column coordinates of each child of a grid
// layout must be explicitly defined
var row = Math.floor(index / group.columns);
var column = index - row * group.columns;
return '-ms-grid-row: ' + (row + 1) + ';'
+ '-ms-grid-column: ' + (column + 1) + ';';
// Operate on cached copy of grid
var clientGrid = group._grid || (group._grid = []);
// Delete any rows in excess of the required size
clientGrid.splice(group.rows);
for (var row = 0; row < group.rows; row++) {
// Prefer to use existing column arrays, deleting any columns in
// excess of the required size
var currentRow = clientGrid[row] || (clientGrid[row] = []);
currentRow.splice(group.columns);
for (var column = 0; column < group.columns; column++) {
currentRow[column] = group.clients[index++] || null;
}
}
return clientGrid;
};