clipboard-consent-dialog.js 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. /**
  2. * Clipboard Monitoring Consent Dialog
  3. *
  4. * Displays a modal dialog requesting user consent before enabling clipboard monitoring.
  5. * Complies with privacy best practices by providing clear disclosure.
  6. */
  7. class ClipboardConsentDialog {
  8. constructor() {
  9. this.dialog = null;
  10. this.overlay = null;
  11. this.onAllow = null;
  12. this.onDeny = null;
  13. }
  14. /**
  15. * Show the consent dialog
  16. * @returns {Promise<{allowed: boolean, rememberChoice: boolean}>}
  17. */
  18. show() {
  19. return new Promise((resolve) => {
  20. this.createDialog();
  21. // Set up button handlers
  22. const allowBtn = this.dialog.querySelector('#clipboard-consent-allow');
  23. const denyBtn = this.dialog.querySelector('#clipboard-consent-deny');
  24. const rememberCheckbox = this.dialog.querySelector('#clipboard-consent-remember');
  25. const handleResponse = (allowed) => {
  26. const rememberChoice = rememberCheckbox.checked;
  27. this.remove();
  28. resolve({ allowed, rememberChoice });
  29. };
  30. allowBtn.addEventListener('click', () => handleResponse(true));
  31. denyBtn.addEventListener('click', () => handleResponse(false));
  32. // ESC key to deny
  33. const handleEscape = (e) => {
  34. if (e.key === 'Escape') {
  35. handleResponse(false);
  36. document.removeEventListener('keydown', handleEscape);
  37. }
  38. };
  39. document.addEventListener('keydown', handleEscape);
  40. // Show dialog
  41. document.body.appendChild(this.overlay);
  42. document.body.appendChild(this.dialog);
  43. // Focus allow button
  44. setTimeout(() => allowBtn.focus(), 100);
  45. });
  46. }
  47. /**
  48. * Create the dialog HTML
  49. */
  50. createDialog() {
  51. // Create overlay
  52. this.overlay = document.createElement('div');
  53. this.overlay.className = 'fixed inset-0 bg-black bg-opacity-50 z-50 flex items-center justify-center';
  54. this.overlay.style.backdropFilter = 'blur(4px)';
  55. // Create dialog
  56. this.dialog = document.createElement('div');
  57. this.dialog.className = 'bg-[#1d293d] border border-[#45556c] rounded-lg shadow-xl max-w-md w-full mx-4 z-50';
  58. this.dialog.setAttribute('role', 'dialog');
  59. this.dialog.setAttribute('aria-labelledby', 'clipboard-consent-title');
  60. this.dialog.setAttribute('aria-describedby', 'clipboard-consent-description');
  61. this.dialog.innerHTML = `
  62. <div class="p-6">
  63. <!-- Header -->
  64. <div class="flex items-start gap-3 mb-4">
  65. <svg class="w-6 h-6 text-[#155dfc] flex-shrink-0 mt-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
  66. <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
  67. </svg>
  68. <div class="flex-1">
  69. <h2 id="clipboard-consent-title" class="text-lg font-semibold text-white mb-1">
  70. Enable Clipboard Monitoring?
  71. </h2>
  72. <p class="text-sm text-[#90a1b9]">
  73. GrabZilla can automatically detect video URLs when you copy them
  74. </p>
  75. </div>
  76. </div>
  77. <!-- Privacy Disclosure -->
  78. <div id="clipboard-consent-description" class="bg-[#314158] border border-[#45556c] rounded-lg p-4 mb-4">
  79. <div class="space-y-3">
  80. <div class="flex items-start gap-2">
  81. <svg class="w-4 h-4 text-[#00a63e] flex-shrink-0 mt-0.5" fill="currentColor" viewBox="0 0 20 20">
  82. <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"/>
  83. </svg>
  84. <p class="text-sm text-[#cad5e2]">
  85. <strong class="text-white">Only checks for video URLs</strong> from YouTube and Vimeo
  86. </p>
  87. </div>
  88. <div class="flex items-start gap-2">
  89. <svg class="w-4 h-4 text-[#00a63e] flex-shrink-0 mt-0.5" fill="currentColor" viewBox="0 0 20 20">
  90. <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"/>
  91. </svg>
  92. <p class="text-sm text-[#cad5e2]">
  93. <strong class="text-white">Never sent to external servers</strong> - stays on your device
  94. </p>
  95. </div>
  96. <div class="flex items-start gap-2">
  97. <svg class="w-4 h-4 text-[#00a63e] flex-shrink-0 mt-0.5" fill="currentColor" viewBox="0 0 20 20">
  98. <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"/>
  99. </svg>
  100. <p class="text-sm text-[#cad5e2]">
  101. <strong class="text-white">Can be disabled anytime</strong> using the toggle switch
  102. </p>
  103. </div>
  104. </div>
  105. </div>
  106. <!-- Remember Choice -->
  107. <label class="flex items-center gap-2 mb-6 cursor-pointer group">
  108. <input type="checkbox" id="clipboard-consent-remember"
  109. class="w-4 h-4 text-[#155dfc] bg-[#314158] border-[#45556c] rounded focus:ring-2 focus:ring-[#155dfc]">
  110. <span class="text-sm text-[#cad5e2] group-hover:text-white transition-colors">
  111. Remember my choice (don't ask again)
  112. </span>
  113. </label>
  114. <!-- Action Buttons -->
  115. <div class="flex gap-3">
  116. <button id="clipboard-consent-deny"
  117. class="flex-1 px-4 py-2.5 bg-[#314158] hover:bg-[#3d4f66] border border-[#45556c] text-white rounded-lg font-medium transition-colors focus:ring-2 focus:ring-[#155dfc] focus:outline-none">
  118. Don't Allow
  119. </button>
  120. <button id="clipboard-consent-allow"
  121. class="flex-1 px-4 py-2.5 bg-[#155dfc] hover:bg-[#1250e3] text-white rounded-lg font-medium transition-colors focus:ring-2 focus:ring-[#155dfc] focus:outline-none">
  122. Allow Clipboard Monitoring
  123. </button>
  124. </div>
  125. </div>
  126. `;
  127. }
  128. /**
  129. * Remove the dialog from DOM
  130. */
  131. remove() {
  132. if (this.dialog) {
  133. this.dialog.remove();
  134. this.dialog = null;
  135. }
  136. if (this.overlay) {
  137. this.overlay.remove();
  138. this.overlay = null;
  139. }
  140. }
  141. }
  142. // Export for use in main app
  143. if (typeof window !== 'undefined') {
  144. window.ClipboardConsentDialog = ClipboardConsentDialog;
  145. }
  146. if (typeof module !== 'undefined' && module.exports) {
  147. module.exports = ClipboardConsentDialog;
  148. }