mirror of
https://github.com/google/blockly.git
synced 2026-05-24 13:00:08 +02:00
feat: Display toasts when items are cut/copied/pasted (#9842)
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
*/
|
||||
|
||||
import {Msg} from './msg.js';
|
||||
import {names} from './shortcut_items.js';
|
||||
import {Toast} from './toast.js';
|
||||
import {getShortcutKeysShort} from './utils/shortcut_formatting.js';
|
||||
import * as userAgent from './utils/useragent.js';
|
||||
@@ -15,6 +16,8 @@ const constrainedMoveHintId = 'constrainedMoveHint';
|
||||
const helpHintId = 'helpHint';
|
||||
const blockNavigationHintId = 'blockNavigationHint';
|
||||
const workspaceNavigationHintId = 'workspaceNavigationHint';
|
||||
const copiedHintId = 'copiedHint';
|
||||
const cutHintId = 'cutHint';
|
||||
|
||||
/**
|
||||
* Nudge the user to use unconstrained movement.
|
||||
@@ -102,3 +105,45 @@ export function showWorkspaceNavigationHint(workspace: WorkspaceSvg) {
|
||||
const id = workspaceNavigationHintId;
|
||||
Toast.show(workspace, {message, id});
|
||||
}
|
||||
|
||||
/**
|
||||
* Nudge the user to paste after a copy.
|
||||
*
|
||||
* @param workspace Workspace.
|
||||
*/
|
||||
export function showCopiedHint(workspace: WorkspaceSvg) {
|
||||
Toast.show(workspace, {
|
||||
message: Msg['KEYBOARD_NAV_COPIED_HINT'].replace(
|
||||
'%1',
|
||||
getShortcutKeysShort(names.PASTE),
|
||||
),
|
||||
duration: 7,
|
||||
id: copiedHintId,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Nudge the user to paste after a cut.
|
||||
*
|
||||
* @param workspace Workspace.
|
||||
*/
|
||||
export function showCutHint(workspace: WorkspaceSvg) {
|
||||
Toast.show(workspace, {
|
||||
message: Msg['KEYBOARD_NAV_CUT_HINT'].replace(
|
||||
'%1',
|
||||
getShortcutKeysShort(names.PASTE),
|
||||
),
|
||||
duration: 7,
|
||||
id: cutHintId,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear active paste-related hints, if any.
|
||||
*
|
||||
* @param workspace The workspace.
|
||||
*/
|
||||
export function clearPasteHints(workspace: WorkspaceSvg) {
|
||||
Toast.hide(workspace, cutHintId);
|
||||
Toast.hide(workspace, copiedHintId);
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import * as contextmenu from './contextmenu.js';
|
||||
import * as dropDownDiv from './dropdowndiv.js';
|
||||
import * as eventUtils from './events/utils.js';
|
||||
import {getFocusManager} from './focus_manager.js';
|
||||
import {clearPasteHints, showCopiedHint, showCutHint} from './hints.js';
|
||||
import {hasContextMenu} from './interfaces/i_contextmenu.js';
|
||||
import {isCopyable as isICopyable} from './interfaces/i_copyable.js';
|
||||
import {isDeletable as isIDeletable} from './interfaces/i_deletable.js';
|
||||
@@ -210,7 +211,11 @@ export function registerCopy() {
|
||||
isDraggable(focused) && focused.workspace == targetWorkspace
|
||||
? focused.getRelativeToSurfaceXY()
|
||||
: undefined;
|
||||
return !!clipboard.copy(focused, copyCoords);
|
||||
const copied = !!clipboard.copy(focused, copyCoords);
|
||||
if (copied) {
|
||||
showCopiedHint(workspace);
|
||||
}
|
||||
return copied;
|
||||
},
|
||||
keyCodes: [ctrlC],
|
||||
displayText: () => Msg['COPY_SHORTCUT'],
|
||||
@@ -258,6 +263,9 @@ export function registerCut() {
|
||||
workspace.getAudioManager().play('delete');
|
||||
e.preventDefault();
|
||||
}
|
||||
if (copyData) {
|
||||
showCutHint(workspace);
|
||||
}
|
||||
return !!copyData;
|
||||
},
|
||||
keyCodes: [ctrlX],
|
||||
@@ -303,6 +311,8 @@ export function registerPaste() {
|
||||
const copyWorkspace = clipboard.getLastCopiedWorkspace();
|
||||
if (!copyWorkspace) return false;
|
||||
|
||||
clearPasteHints(workspace);
|
||||
|
||||
const targetWorkspace = copyWorkspace.isFlyout
|
||||
? copyWorkspace.targetWorkspace
|
||||
: copyWorkspace;
|
||||
|
||||
@@ -282,6 +282,23 @@ suite('Keyboard Shortcut Items', function () {
|
||||
sinon.assert.calledOnce(this.copySpy);
|
||||
sinon.assert.calledOnce(this.hideChaffSpy);
|
||||
});
|
||||
|
||||
test('Shows a toast when copying a block', function () {
|
||||
const toastSpy = sinon.spy(Blockly.Toast, 'show');
|
||||
this.injectionDiv.dispatchEvent(keyEvent);
|
||||
sinon.assert.called(toastSpy);
|
||||
assert.include(toastSpy.args[0][1]['message'], 'Copied. Press');
|
||||
toastSpy.restore();
|
||||
});
|
||||
|
||||
test('Shows a toast when copying a workspace comment', function () {
|
||||
setSelectedComment(this.workspace);
|
||||
const toastSpy = sinon.spy(Blockly.Toast, 'show');
|
||||
this.injectionDiv.dispatchEvent(keyEvent);
|
||||
sinon.assert.called(toastSpy);
|
||||
assert.include(toastSpy.args[0][1]['message'], 'Copied. Press');
|
||||
toastSpy.restore();
|
||||
});
|
||||
});
|
||||
|
||||
suite('Cut', function () {
|
||||
@@ -362,6 +379,23 @@ suite('Keyboard Shortcut Items', function () {
|
||||
sinon.assert.calledOnce(this.copySpy);
|
||||
sinon.assert.calledOnce(this.disposeSpy);
|
||||
});
|
||||
|
||||
test('Shows a toast when cutting a block', function () {
|
||||
const toastSpy = sinon.spy(Blockly.Toast, 'show');
|
||||
this.injectionDiv.dispatchEvent(keyEvent);
|
||||
sinon.assert.called(toastSpy);
|
||||
assert.include(toastSpy.args[0][1]['message'], 'Cut. Press');
|
||||
toastSpy.restore();
|
||||
});
|
||||
|
||||
test('Shows a toast when cutting a workspace comment', function () {
|
||||
setSelectedComment(this.workspace);
|
||||
const toastSpy = sinon.spy(Blockly.Toast, 'show');
|
||||
this.injectionDiv.dispatchEvent(keyEvent);
|
||||
sinon.assert.called(toastSpy);
|
||||
assert.include(toastSpy.args[0][1]['message'], 'Cut. Press');
|
||||
toastSpy.restore();
|
||||
});
|
||||
});
|
||||
|
||||
suite('Paste', function () {
|
||||
@@ -375,6 +409,26 @@ suite('Keyboard Shortcut Items', function () {
|
||||
const isPasteEnabled = pasteShortcut.preconditionFn();
|
||||
assert.isFalse(isPasteEnabled);
|
||||
});
|
||||
|
||||
test('Hides cut/copy toasts', function () {
|
||||
setSelectedBlock(this.workspace);
|
||||
const copyEvent = createKeyDownEvent(Blockly.utils.KeyCodes.C, [
|
||||
Blockly.utils.KeyCodes.CTRL_CMD,
|
||||
]);
|
||||
this.injectionDiv.dispatchEvent(copyEvent);
|
||||
this.clock.runAll();
|
||||
|
||||
const toastSpy = sinon.spy(Blockly.Toast, 'hide');
|
||||
|
||||
const pasteEvent = createKeyDownEvent(Blockly.utils.KeyCodes.V, [
|
||||
Blockly.utils.KeyCodes.CTRL_CMD,
|
||||
]);
|
||||
this.injectionDiv.dispatchEvent(pasteEvent);
|
||||
|
||||
sinon.assert.calledWith(toastSpy, this.workspace, 'cutHint');
|
||||
sinon.assert.calledWith(toastSpy, this.workspace, 'copiedHint');
|
||||
toastSpy.restore();
|
||||
});
|
||||
});
|
||||
|
||||
suite('Undo', function () {
|
||||
|
||||
Reference in New Issue
Block a user