Skip to content

Commit fedcbaf

Browse files
clipboard copy functionality fallback to work on local / non SSL environment. (#419)
2 parents 6a0350c + 8f1e771 commit fedcbaf

File tree

1 file changed

+69
-24
lines changed

1 file changed

+69
-24
lines changed

gui/templates/unprofitable_channels.html

Lines changed: 69 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -102,43 +102,88 @@ <h4>Understanding the Metrics:</h4>
102102
<!-- JavaScript for sorting and copying -->
103103
<script>
104104
function copyToClipboard(text, element) {
105-
navigator.clipboard.writeText(text).then(function() {
106-
// Show visual feedback
107-
if (element) {
108-
// If using the SVG icon
109-
const originalIcon = element.querySelector('svg:first-child');
110-
const checkmark = element.querySelector('.checkmark');
111-
105+
// Check if we're in a secure context (HTTPS)
106+
if (navigator.clipboard && window.isSecureContext) {
107+
// Secure context: use the modern Clipboard API
108+
navigator.clipboard.writeText(text).then(function() {
109+
showCopySuccess(element);
110+
}).catch(function(err) {
111+
console.error('Failed to copy: ', err);
112+
fallbackCopy(text, element);
113+
});
114+
} else {
115+
// Non-secure context: use fallback method
116+
fallbackCopy(text, element);
117+
}
118+
119+
// Prevent default link behavior
120+
if (event && event.preventDefault) {
121+
event.preventDefault();
122+
}
123+
return false;
124+
}
125+
126+
function fallbackCopy(text, element) {
127+
// Create temporary input element
128+
const textArea = document.createElement("textarea");
129+
textArea.value = text;
130+
131+
// Make the textarea out of viewport
132+
textArea.style.position = "fixed";
133+
textArea.style.left = "-999999px";
134+
textArea.style.top = "-999999px";
135+
document.body.appendChild(textArea);
136+
137+
// Preserve scroll position
138+
const scrollPos = window.pageYOffset || document.documentElement.scrollTop;
139+
140+
// Select and copy
141+
textArea.focus();
142+
textArea.select();
143+
144+
let success = false;
145+
try {
146+
success = document.execCommand('copy');
147+
} catch (err) {
148+
console.error('Fallback: Oops, unable to copy', err);
149+
}
150+
151+
// Clean up
152+
document.body.removeChild(textArea);
153+
window.scrollTo(0, scrollPos);
154+
155+
// Show success visual feedback
156+
if (success) {
157+
showCopySuccess(element);
158+
}
159+
}
160+
161+
function showCopySuccess(element) {
162+
if (element) {
163+
// If using the SVG icon
164+
const originalIcon = element.querySelector('svg:first-child');
165+
const checkmark = element.querySelector('.checkmark');
166+
167+
if (originalIcon && checkmark) {
112168
// Hide original icon and show checkmark
113169
originalIcon.style.visibility = 'hidden';
114170
checkmark.style.visibility = 'visible';
115-
171+
116172
setTimeout(function() {
117173
// Restore original icon and hide checkmark
118174
originalIcon.style.visibility = 'visible';
119175
checkmark.style.visibility = 'hidden';
120176
}, 1500);
121177
} else {
122-
// If using the button
123-
const button = event.target;
124-
const originalText = button.textContent;
125-
button.textContent = "Copied!";
126-
button.style.backgroundColor = "#4CAF50";
127-
178+
// Simple text-based fallback if SVG elements aren't found
179+
const originalText = element.textContent || 'Copy';
180+
element.textContent = "Copied!";
181+
128182
setTimeout(function() {
129-
button.textContent = originalText;
130-
button.style.backgroundColor = "";
183+
element.textContent = originalText;
131184
}, 1500);
132185
}
133-
}, function() {
134-
console.error('Failed to copy text to clipboard');
135-
});
136-
137-
// Prevent default link behavior
138-
if (event && event.preventDefault) {
139-
event.preventDefault();
140186
}
141-
return false;
142187
}
143188

144189
// Sorting function from channels.html

0 commit comments

Comments
 (0)