Skip to content

Commit d40a4d9

Browse files
committed
Make paste UI optimistically enabled on web when Web Clipboard API is available
Clipboard.has() now returns true on web when the Web Clipboard API is available, even if the in-memory clipboard doesn't have matching content. This ensures paste buttons and menu items are enabled when the system clipboard might contain valid GDevelop content from another tab. Also update hasClipboardEvents/Conditions/Actions() to return true optimistically when the in-memory clipboard is empty but the Web Clipboard API is available. All paste operations already handle invalid/missing content gracefully via Clipboard.read(), so enabling paste unconditionally is safe. https://claude.ai/code/session_014Tphwia3UUUdis3TUsRffE
1 parent 56569bd commit d40a4d9

File tree

2 files changed

+34
-8
lines changed

2 files changed

+34
-8
lines changed

newIDE/app/src/EventsSheet/ClipboardKind.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ export const CLIPBOARD_KIND = 'EventsAndInstructions';
2323
export const hasClipboardEvents = () => {
2424
if (!Clipboard.has(CLIPBOARD_KIND)) return false;
2525
const clipboardContent = Clipboard.get(CLIPBOARD_KIND);
26+
// If in-memory clipboard has no content but has() returned true,
27+
// it means Web Clipboard API is available and might have content.
28+
if (clipboardContent === null) return true;
2629
const eventsCount = SafeExtractor.extractNumberProperty(
2730
clipboardContent,
2831
'eventsCount'
@@ -35,6 +38,9 @@ export const hasClipboardEvents = () => {
3538
export const hasClipboardConditions = () => {
3639
if (!Clipboard.has(CLIPBOARD_KIND)) return false;
3740
const clipboardContent = Clipboard.get(CLIPBOARD_KIND);
41+
// If in-memory clipboard has no content but has() returned true,
42+
// it means Web Clipboard API is available and might have content.
43+
if (clipboardContent === null) return true;
3844
const conditionsCount = SafeExtractor.extractNumberProperty(
3945
clipboardContent,
4046
'conditionsCount'
@@ -47,6 +53,9 @@ export const hasClipboardConditions = () => {
4753
export const hasClipboardActions = () => {
4854
if (!Clipboard.has(CLIPBOARD_KIND)) return false;
4955
const clipboardContent = Clipboard.get(CLIPBOARD_KIND);
56+
// If in-memory clipboard has no content but has() returned true,
57+
// it means Web Clipboard API is available and might have content.
58+
if (clipboardContent === null) return true;
5059
const actionsCount = SafeExtractor.extractNumberProperty(
5160
clipboardContent,
5261
'actionsCount'

newIDE/app/src/Utils/Clipboard.js

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -63,19 +63,36 @@ export default class Clipboard {
6363
* Quickly check that the clipboard content *should* be containing valid JSON content
6464
* of the specified kind.
6565
*
66-
* This is a synchronous check against the in-memory clipboard (or Electron clipboard).
67-
* It does NOT read the system clipboard (which is async on the web).
68-
* Use `Clipboard.read` for a full async read that checks the system clipboard.
66+
* On Electron, this is a synchronous check against the system clipboard.
67+
* On the web, this checks the in-memory clipboard first. If nothing is found
68+
* but the Web Clipboard API is available, it optimistically returns true
69+
* because the system clipboard might contain valid content from another tab.
70+
* Paste operations use `Clipboard.read` which handles invalid content gracefully.
6971
*/
7072
static has(kind: ClipboardKind): boolean {
71-
let text = '';
7273
if (electronClipboard) {
73-
text = electronClipboard.readText();
74-
} else {
75-
text = internalClipboard;
74+
return (
75+
electronClipboard.readText().indexOf(mangleClipboardKind(kind)) === 12
76+
);
77+
}
78+
79+
// Check in-memory clipboard first.
80+
if (internalClipboard.indexOf(mangleClipboardKind(kind)) === 12) {
81+
return true;
82+
}
83+
84+
// If Web Clipboard API is available, the system clipboard might contain
85+
// valid content from another tab — optimistically return true.
86+
// Paste operations use Clipboard.read() which handles invalid content gracefully.
87+
if (
88+
typeof navigator !== 'undefined' &&
89+
navigator.clipboard &&
90+
navigator.clipboard.readText
91+
) {
92+
return true;
7693
}
7794

78-
return text.indexOf(mangleClipboardKind(kind)) === 12; /// 12 is the position of '000kind' value
95+
return false;
7996
}
8097

8198
/**

0 commit comments

Comments
 (0)