Merge pull request 'fix/bug-78267' (#835) from fix/bug-78267 into release/v9.2.0

Reviewed-on: https://git.onlyoffice.com/ONLYOFFICE/web-apps/pulls/835
This commit is contained in:
Oleg Korshul
2025-11-13 20:02:42 +00:00
7 changed files with 92 additions and 34 deletions

View File

@ -594,6 +594,10 @@ define([
// weight = range for main key + “cost” of extra keys // weight = range for main key + “cost” of extra keys
return keyIndex * 100 + extras; return keyIndex * 100 + extras;
} }
if (first.ascShortcut.asc_IsLocked() && !second.ascShortcut.asc_IsLocked()) return -1;
if (!first.ascShortcut.asc_IsLocked() && second.ascShortcut.asc_IsLocked()) return 1;
let wFirst = getWeight(first.ascShortcut); let wFirst = getWeight(first.ascShortcut);
let wSecond = getWeight(second.ascShortcut); let wSecond = getWeight(second.ascShortcut);

View File

@ -81,7 +81,7 @@ define([
'<div class="recent-wrap">', '<div class="recent-wrap">',
'<div class="recent-icon">', '<div class="recent-icon">',
'<div>', '<div>',
'<svg><use href="#<% if (typeof format !== "undefined") { %><%= format %><% } else { %>blank<% } %>"></use></svg>', '<svg><use href="#<% if (typeof format !== "undefined" && format && format.length > 0) { %><%= format %><% } else { %>neutral<% } %>"></use></svg>',
'<div class= <% if (typeof format !== "undefined") {%> "img-format-<%=format %>"<% } else {%> "svg-file-recent"<%} %>></div>', '<div class= <% if (typeof format !== "undefined") {%> "img-format-<%=format %>"<% } else {%> "svg-file-recent"<%} %>></div>',
'</div>', '</div>',
'</div>', '</div>',

View File

@ -103,7 +103,7 @@ define([
'</div>', '</div>',
'<% if (action.isLocked) { %>', '<% if (action.isLocked) { %>',
'<button type="button" class="btn-toolbar">', '<button type="button" class="btn-toolbar">',
'<i class="icon options__icon toolbar__icon btn-lock icon-lock">&nbsp;</i>', '<i class="icon options__icon toolbar__icon btn-lock icon-lock">&nbsp;</i>',
'</button>', '</button>',
'<% } else { %>', '<% } else { %>',
'<button type="button" class="action-edit btn-toolbar">', '<button type="button" class="action-edit btn-toolbar">',

View File

@ -97,13 +97,22 @@ define([
getFocusedComponents: function() { getFocusedComponents: function() {
const dynamicComponents = []; const dynamicComponents = [];
this.shortcutsCollection.each(function(record) { this.shortcutsCollection.each(function(record) {
dynamicComponents.push(record.get('keysInput'), record.get('removeBtn')); if(record.get('removeBtn')) {
dynamicComponents.push(record.get('keysInput'), record.get('removeBtn'));
}
}); });
return dynamicComponents.concat(this.getFooterButtons()); return dynamicComponents.concat(this.getFooterButtons());
}, },
getDefaultFocusableComponent: function() { getDefaultFocusableComponent: function() {
return this.shortcutsCollection.at(0).get('keysInput'); const firstFocusableItem = this.shortcutsCollection.find(function(item) {
return item.get('removeBtn');
});
if(firstFocusableItem) {
return firstFocusableItem.get('keysInput');
} else {
return this.getFooterButtons()[0];
}
}, },
_setDefaults: function() { _setDefaults: function() {
@ -157,7 +166,7 @@ define([
}, },
/** /**
* Finds all actions that already have the given shortcut assigned. * Finds all actions that currently use the specified shortcut and returns both the action and the shortcut.
* *
* If `extraAction` is provided and its `extraAction.actionType` matches the current item, * If `extraAction` is provided and its `extraAction.actionType` matches the current item,
* the method will check `extraAction.shortcuts` instead of the original shortcuts. * the method will check `extraAction.shortcuts` instead of the original shortcuts.
@ -167,7 +176,7 @@ define([
* @param {Object} [extraAction] Optional object that can replace the shortcuts of a matching action. * @param {Object} [extraAction] Optional object that can replace the shortcuts of a matching action.
* @param {number} extraAction.actionType The type of the action to match. * @param {number} extraAction.actionType The type of the action to match.
* @param {CAscShortcut[]} extraAction.shortcuts Custom list of shortcuts to check for this action. * @param {CAscShortcut[]} extraAction.shortcuts Custom list of shortcuts to check for this action.
* @returns {Object[]} Array of action objects that already use the given shortcut. * @returns {Object[]} Array of objects containing `action` and the matching `shortcut`.
*/ */
_findAssignedActions: function(ascShortcut, extraAction) { _findAssignedActions: function(ascShortcut, extraAction) {
const shortcutIndex = ascShortcut.asc_GetShortcutIndex(); const shortcutIndex = ascShortcut.asc_GetShortcutIndex();
@ -184,17 +193,20 @@ define([
item.shortcuts = extraAction.shortcuts; item.shortcuts = extraAction.shortcuts;
} }
const existsVisible = _.some(item.shortcuts, function(shortcut) { const foundShortcut = _.find(item.shortcuts, function(shortcut) {
return shortcut.ascShortcut.asc_GetShortcutIndex() == shortcutIndex && return shortcut.ascShortcut.asc_GetShortcutIndex() == shortcutIndex &&
!shortcut.ascShortcut.asc_IsHidden(); !shortcut.ascShortcut.asc_IsHidden();
}); });
if (existsVisible) { if (foundShortcut) {
foundItems.push(item); foundItems.push({
action: item.action,
shortcut: foundShortcut
});
} }
} }
return _.map(foundItems, function(item) { return item.action; }); return foundItems;
}, },
/** /**
@ -230,9 +242,7 @@ define([
'<div class="item ' + (index == 0 ? 'first' : '') + '">' + '<div class="item ' + (index == 0 ? 'first' : '') + '">' +
'<div class="keys-input"></div>' + '<div class="keys-input"></div>' +
(isLocked (isLocked
? '<button type="button" class="btn-toolbar">' + ? '<i class="lock-info-icon icon toolbar__icon btn-menu-about">&nbsp;</i>'
'<i class="icon toolbar__icon btn-menu-about">&nbsp;</i>' +
'</button>'
: '<button type="button" class="btn-toolbar remove-btn">' + : '<button type="button" class="btn-toolbar remove-btn">' +
'<i class="icon toolbar__icon btn-cc-remove">&nbsp;</i>' + '<i class="icon toolbar__icon btn-cc-remove">&nbsp;</i>' +
'</button>' '</button>'
@ -252,10 +262,21 @@ define([
placeHolder : me.txtInputPlaceholder, placeHolder : me.txtInputPlaceholder,
disabled : isLocked disabled : isLocked
}); });
const removeButton = new Common.UI.Button({
el: $item.find('.remove-btn'), let removeButton;
}); if(isLocked) {
item.set({ keysInput: keysInput, removeBtn: removeButton }); $item.find('.lock-info-icon').tooltip({
title: me.txtCantBeEdited,
placement: 'cursor',
zIndex : parseInt(me.$window.css('z-index')) + 10
});
} else {
removeButton = new Common.UI.Button({
el: $item.find('.remove-btn')
});
}
item.set({ keysInput: keysInput, removeBtn: removeButton});
const $keysInput = $item.find('.keys-input input'); const $keysInput = $item.find('.keys-input input');
$keysInput.on('keydown', function(e) { $keysInput.on('keydown', function(e) {
@ -356,11 +377,20 @@ define([
}); });
$item.find('.remove-btn').on('click', function() { $item.find('.remove-btn').on('click', function() {
const removedIndex = me.shortcutsCollection.findIndex(function(record) {
return record == item;
});
me.shortcutsCollection.remove(item); me.shortcutsCollection.remove(item);
if(me.shortcutsCollection.length == 0) { if(me.shortcutsCollection.length == 0) {
me.onAddShortcut(); me.onAddShortcut();
} }
me.$window.find('#shortcuts-list .item input').last().focus();
let newFocusableIndex = removedIndex < me.shortcutsCollection.length ? removedIndex : removedIndex - 1;
if(me.shortcutsCollection.at(newFocusableIndex).get('removeBtn')) {
me.shortcutsCollection.at(newFocusableIndex).get('removeBtn').focus();
} else {
me.getFooterButtons()[0].focus();;
}
}); });
}); });
this.fixHeight(true); this.fixHeight(true);
@ -378,19 +408,22 @@ define([
this.shortcutsCollection.each(function(item) { this.shortcutsCollection.each(function(item) {
const ascShortcut = item.get('ascShortcut'); const ascShortcut = item.get('ascShortcut');
const assignedActionNames = []; const assignedActionNames = [];
const assignedActions = me._findAssignedActions(ascShortcut, { const assignedItem = me._findAssignedActions(ascShortcut, {
actionType: me.options.action.type, actionType: me.options.action.type,
shortcuts: me.shortcutsCollection.toJSON().slice(0, _.indexOf(me.shortcutsCollection.models, item)) shortcuts: me.shortcutsCollection.toJSON().slice(0, _.indexOf(me.shortcutsCollection.models, item))
}); });
const isDefaultShortcut = me._isDefaultShortcut(ascShortcut); const isDefaultShortcut = me._isDefaultShortcut(ascShortcut);
const isDisabled = !isDefaultShortcut && const isDisabled = !isDefaultShortcut &&
_.some(assignedActions, function(action) { return action.isLocked; }); _.some(assignedItem, function(item) {
return item.action.isLocked || item.shortcut.ascShortcut.asc_IsLocked();
});
isButtonDisabled = isButtonDisabled || isDisabled; isButtonDisabled = isButtonDisabled || isDisabled;
for (let i = 0; i < assignedActions.length; i++) { for (let i = 0; i < assignedItem.length; i++) {
const action = assignedActions[i]; const action = assignedItem[i].action;
if(action.isLocked == isDisabled) { const ascShortcut = assignedItem[i].shortcut.ascShortcut;
if((action.isLocked || ascShortcut.asc_IsLocked()) == isDisabled) {
assignedActionNames.push('“' + action.name + '”'); assignedActionNames.push('“' + action.name + '”');
} }
} }
@ -480,7 +513,8 @@ define([
txtRestoreToDefault: 'Restore to default', txtRestoreToDefault: 'Restore to default',
txtTypeDesiredShortcut: 'Type desired shortcut', txtTypeDesiredShortcut: 'Type desired shortcut',
txtRestoreDescription: 'All shortcuts for action “%1” will be restored to deafult.', txtRestoreDescription: 'All shortcuts for action “%1” will be restored to deafult.',
txtRestoreContinue: 'Do you want to continue?' txtRestoreContinue: 'Do you want to continue?',
txtCantBeEdited: 'This shortcut cant be edited'
}, Common.Views.ShortcutsEditDialog || {})) }, Common.Views.ShortcutsEditDialog || {}))
}); });

View File

@ -68,6 +68,8 @@
border: 1px solid @border-divider; border: 1px solid @border-divider;
box-shadow: 0 1px 0 0 @border-divider-ie; box-shadow: 0 1px 0 0 @border-divider-ie;
box-shadow: 0 1px 0 0 @border-divider; box-shadow: 0 1px 0 0 @border-divider;
color: @text-normal-ie;
color: @text-normal;
} }
.action-keys-item-comma { .action-keys-item-comma {
display: flex; display: flex;
@ -104,6 +106,15 @@
opacity: 1; opacity: 1;
} }
} }
&.selected {
button {
:not(:hover).icon {
background-position-x: -20px;
background-position-x: @button-small-active-icon-offset-x;
}
}
}
} }
} }
@ -147,6 +158,13 @@
flex: 1; flex: 1;
.margin-right(8px); .margin-right(8px);
} }
.lock-info-icon {
width: @x-small-btn-icon-size-ie;
width: @x-small-btn-icon-size;
height: @x-small-btn-icon-size-ie;
height: @x-small-btn-icon-size;
}
} }
.item:not(.first) { .item:not(.first) {
margin-top: 8px; margin-top: 8px;

View File

@ -1197,6 +1197,7 @@
"Common.Views.ShortcutsEditDialog.txtRestoreToDefault": "Restore to default", "Common.Views.ShortcutsEditDialog.txtRestoreToDefault": "Restore to default",
"Common.Views.ShortcutsEditDialog.txtTitle": "Edit shortcut", "Common.Views.ShortcutsEditDialog.txtTitle": "Edit shortcut",
"Common.Views.ShortcutsEditDialog.txtTypeDesiredShortcut": "Type desired shortcut", "Common.Views.ShortcutsEditDialog.txtTypeDesiredShortcut": "Type desired shortcut",
"Common.Views.ShortcutsEditDialog.txtCantBeEdited": "This shortcut cant be edited",
"Common.Views.SignDialog.textBold": "Bold", "Common.Views.SignDialog.textBold": "Bold",
"Common.Views.SignDialog.textCertificate": "Certificate", "Common.Views.SignDialog.textCertificate": "Certificate",
"Common.Views.SignDialog.textChange": "Change", "Common.Views.SignDialog.textChange": "Change",

View File

@ -386,20 +386,21 @@
div { div {
width: 100%; width: 100%;
height: 100%; height: 100%;
svg {
display: none;
width: 24px;
height: 30px;
.pixel-ratio__2_5 & {
display: block;
}
}
div{ div{
background: ~"url(@{common-image-const-path}/doc-formats/formats.png)"; background: ~"url(@{common-image-const-path}/doc-formats/formats.png)";
background-size: 1200px 30px; background-size: 1200px 30px;
svg {
display: none;
width: 24px;
height: 30px;
.pixel-ratio__2_5 & {
display: block;
}
}
&:not(.svg-file-recent) { &:not(.svg-file-recent) {
.pixel-ratio__1_25 & { .pixel-ratio__1_25 & {
background-image: ~"url(@{common-image-const-path}/doc-formats/formats@1.25x.png)"; background-image: ~"url(@{common-image-const-path}/doc-formats/formats@1.25x.png)";