Margin is an open annotation layer for the internet. Powered by the AT Protocol. margin.at
extension web atproto comments
fork

Configure Feed

Select the types of activity you want to include in your feed.

remove text selection popup

+2 -124
+2 -124
extension/content/content.js
··· 2 2 let sidebarHost = null; 3 3 let sidebarShadow = null; 4 4 let popoverEl = null; 5 - let selectionPopupEl = null; 5 + 6 6 7 7 let activeItems = []; 8 8 let currentSelection = null; ··· 470 470 471 471 document.addEventListener("mousemove", handleMouseMove); 472 472 document.addEventListener("click", handleDocumentClick, true); 473 - document.addEventListener("mouseup", handleTextSelection); 474 - } 475 - 476 - function handleTextSelection(e) { 477 - if (e.target.closest && e.target.closest("#margin-overlay-host")) return; 478 - 479 - const selection = window.getSelection(); 480 - const selectedText = selection?.toString().trim(); 481 - if (!selectedText || selectedText.length < 3) { 482 - hideSelectionPopup(); 483 - return; 484 - } 485 - 486 - const anchorNode = selection.anchorNode; 487 - if (anchorNode) { 488 - const parent = anchorNode.parentElement; 489 - if ( 490 - parent && 491 - (parent.tagName === "INPUT" || 492 - parent.tagName === "TEXTAREA" || 493 - parent.isContentEditable) 494 - ) { 495 - return; 496 - } 497 - } 498 - 499 - currentSelection = { 500 - text: selectedText, 501 - selector: { type: "TextQuoteSelector", exact: selectedText }, 502 - }; 503 - 504 - showSelectionPopup(e.clientX, e.clientY); 505 - } 506 - 507 - function showSelectionPopup(x, y) { 508 - hideSelectionPopup(); 509 - if (!sidebarShadow) return; 510 - 511 - const container = sidebarShadow.getElementById("margin-overlay-container"); 512 - if (!container) return; 513 - 514 - selectionPopupEl = document.createElement("div"); 515 - selectionPopupEl.className = "margin-selection-popup"; 516 - 517 - const popupWidth = 180; 518 - const viewportWidth = window.innerWidth; 519 - let left = x + 5; 520 - if (left + popupWidth > viewportWidth) { 521 - left = viewportWidth - popupWidth - 10; 522 - } 523 - 524 - selectionPopupEl.style.left = `${left}px`; 525 - selectionPopupEl.style.top = `${y + 10}px`; 526 - 527 - selectionPopupEl.innerHTML = ` 528 - <button class="selection-btn btn-annotate"> 529 - <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> 530 - <path d="M12 20h9M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z"/> 531 - </svg> 532 - Annotate 533 - </button> 534 - <button class="selection-btn btn-highlight"> 535 - <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> 536 - <path d="M9 11l3 3L22 4"/> 537 - <path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"/> 538 - </svg> 539 - Highlight 540 - </button> 541 - `; 542 - 543 - selectionPopupEl 544 - .querySelector(".btn-annotate") 545 - .addEventListener("click", (e) => { 546 - e.stopPropagation(); 547 - hideSelectionPopup(); 548 - showInlineComposeModal(); 549 - }); 550 - 551 - selectionPopupEl 552 - .querySelector(".btn-highlight") 553 - .addEventListener("click", async (e) => { 554 - e.stopPropagation(); 555 - hideSelectionPopup(); 556 - 557 - chrome.runtime.sendMessage( 558 - { 559 - type: "CREATE_HIGHLIGHT", 560 - data: { 561 - url: window.location.href, 562 - title: document.title, 563 - selector: currentSelection.selector, 564 - color: "#fcd34d", 565 - }, 566 - }, 567 - (res) => { 568 - if (res && res.success) { 569 - fetchAnnotations(); 570 - } 571 - }, 572 - ); 573 - }); 574 - 575 - container.appendChild(selectionPopupEl); 576 - 577 - setTimeout(() => { 578 - document.addEventListener("mousedown", closeSelectionPopupOutside, { 579 - once: true, 580 - }); 581 - }, 100); 582 - } 583 - 584 - function hideSelectionPopup() { 585 - if (selectionPopupEl) { 586 - selectionPopupEl.remove(); 587 - selectionPopupEl = null; 588 - } 589 - } 590 - 591 - function closeSelectionPopupOutside(e) { 592 - if (selectionPopupEl && !selectionPopupEl.contains(e.target)) { 593 - hideSelectionPopup(); 594 - } 595 473 } 596 474 597 475 function showInlineComposeModal() { ··· 762 640 const firstRect = firstRange.getClientRects()[0]; 763 641 const totalWidth = 764 642 Math.min(uniqueAuthors.length, maxShow + (overflow > 0 ? 1 : 0)) * 765 - 18 + 643 + 18 + 766 644 8; 767 645 const leftPos = firstRect.left - totalWidth; 768 646 const topPos = firstRect.top + firstRect.height / 2 - 12;