Skip to content

Commit

Permalink
refacto clipboard
Browse files Browse the repository at this point in the history
  • Loading branch information
jparez committed Jan 16, 2025
1 parent 213da3f commit 17a272f
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 58 deletions.
3 changes: 3 additions & 0 deletions src/assets/images/ic_copy.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
86 changes: 40 additions & 46 deletions src/plugins/Clipboard.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict';

const OverlayPlugin = require('./util/OverlayPlugin');
const {chipTag} = require('./util/components');

const log = require('loglevel');
log.setDefaultLevel('debug');
Expand Down Expand Up @@ -75,35 +76,54 @@ module.exports = class Clipboard extends OverlayPlugin {
*/
renderWidget() {
// Create elements
this.widget = document.createElement('div');
this.container = document.createElement('div');
const {modal, container} = this.createTemplateModal({
title: this.i18n.CLIPBOARD_TITLE || 'Device Clipboard',
classes: 'gm-clipboard-plugin',
width: 378,
height: 484,
});
this.container = container;
this.widget = modal;

// Generate title
const title = document.createElement('div');
title.className = 'gm-title';
title.innerHTML = this.i18n.CLIPBOARD_TITLE || 'Device Clipboard';
this.container.appendChild(title);
const text = document.createElement('div');
text.innerHTML = this.i18n.CLIPBOARD_TEXT ||
'The content you type below will be copied directly to your virtual device\'s clipboard.';

this.clipboardInput = document.createElement('textarea');
this.clipboardInput.className = 'gm-clipboard-input';
this.clipboardInput.placeholder = this.i18n.CLIPBOARD_PLACEHOLDER || 'Write your content here';
this.clipboardInput.oninput = (event) => {
this.container.classList.remove('gm-clipboard-saved');
this.clipboard = event.target.value;
if (event.target.value.length > 0) {
this.submitBtn.disabled = false;
} else {
this.submitBtn.disabled = true;
}
};

// Setup
this.container.appendChild(this.clipboardInput);
this.widget.className = 'gm-overlay gm-clipboard-plugin gm-hidden';

// Add close button
const close = document.createElement('div');
close.className = 'gm-close-btn';
close.onclick = this.toggleWidget.bind(this);

this.widget.appendChild(close);
this.widget.appendChild(this.container);
const actionsDiv = document.createElement('div');
actionsDiv.className = 'gm-actions';
const appliedTag = chipTag.createChip({
text: this.i18n.CLIPBOARD_COPIED || 'Copied',
});

this.widget.onclose = () => {
this.clipboard = this.clipboardInput.value;
this.submitBtn = document.createElement('button');
this.submitBtn.innerHTML = this.i18n.CLIPBOARD_COPY || 'Copy to device';
this.submitBtn.className = 'gm-btn gm-clipboard-apply';
this.submitBtn.onclick = () => {
this.container.classList.add('gm-clipboard-saved');
this.sendDataToInstance();
};

actionsDiv.appendChild(appliedTag.element);
actionsDiv.appendChild(this.submitBtn);

// Setup
this.container.appendChild(text);
this.container.appendChild(this.clipboardInput);
this.container.appendChild(actionsDiv);

// Render into document
this.instance.root.appendChild(this.widget);
}
Expand All @@ -120,32 +140,6 @@ module.exports = class Clipboard extends OverlayPlugin {
}
}

/**
* Copy the instance clipboard (reflected to the text input field) into the client clipboard.
*
* @param {HTMLElement} clipboardInput Clipboard value (text input).
* @param {HTMLElement} clipboardCopyIndicator Clipboard copy indicator.
*/
copyInstanceClipboardToClient(clipboardInput, clipboardCopyIndicator) {
try {
navigator.clipboard.writeText(this.clipboardInput.value);
} catch (error) {
// Old, deprecated fallback
clipboardInput.focus();
clipboardInput.select();
document.execCommand('copy');
}

clipboardCopyIndicator.classList.remove('gm-invisible');
clipboardCopyIndicator.classList.remove('gm-hidden');
setTimeout(() => {
clipboardCopyIndicator.classList.add('gm-invisible');
setTimeout(() => {
clipboardCopyIndicator.classList.add('gm-hidden');
}, 500);
}, 2000);
}

/**
* Send information to instance.
*/
Expand Down
2 changes: 2 additions & 0 deletions src/scss/base/_genymotion.scss
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,8 @@
}

.gm-btn{
max-height: 40px;
height: 40px;
border: none;
background: none;
text-transform: uppercase;
Expand Down
54 changes: 47 additions & 7 deletions src/scss/components/_clipboard.scss
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,58 @@
*/
.device-renderer-instance .gm-clipboard-plugin {
.gm {
&-modal-body {
display: flex;
flex-direction: column;
}

&-clipboard-saved {
.gm-actions{
.gm-tag-success {
visibility: visible;
}
}
}

&-clipboard-input {
min-height: 300px;
height: 249px;
resize: none;
border: none;
margin: $spacing-m 0;
padding: $spacing-m 0 0 $spacing-m;

color: var(--gm-input-text-color);
background-color: #fff;
}
background-color: var(--gm-third-color);

&-text-copied {
padding: 15px 0 0 30px;
transition: opacity 0.5s ease-in-out;
background: url('../assets/images/ic_clipboard_inactive.svg') no-repeat left 10px !important;
&:focus {
outline: none;
}
}
&-actions{
display: flex;
justify-content: space-between;
align-items: center;
.gm-clipboard-apply {
display: flex;
align-items: center;
}
.gm-clipboard-apply::before {
content: "";
mask-image: url('../assets/images/ic_copy.svg');
-webkit-mask-image: url('../assets/images/ic_copy.svg');
-webkit-mask-size: contain;
mask-size: contain;
-webkit-mask-repeat: no-repeat;
mask-repeat: no-repeat;
-webkit-mask-position: center;
mask-position: center;
background: currentColor;
width: 32px;
height: 32px;
}
.gm-tag-success {
visibility: hidden;
}
}
}
}
14 changes: 9 additions & 5 deletions tests/unit/clipboard.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,16 @@ describe('Clipboard Plugin', () => {
sendEventSpy.mockRestore();
});

test('clipboard value', () => {
const button = document.getElementsByClassName('gm-clipboard-button')[0];
test('clipboard send value', () => {
expect(clipboard.clipboard).toBe('');

clipboard.clipboard = 'test value';
button.click(); // Open
button.click(); // Close
clipboard.clipboardInput.value = 'test value';
const event = new Event('input', {bubbles: true});
clipboard.clipboardInput.dispatchEvent(event);

expect(clipboard.clipboard).toBe('test value');

clipboard.submitBtn.click();

expect(sendEventSpy).toHaveBeenCalledTimes(1);
expect(instance.outgoingMessages[0]).toEqual({
Expand Down

0 comments on commit 17a272f

Please sign in to comment.