You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

wordle-share.js 3.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. const copyToClipboard = (s) => {
  2. document.addEventListener('copy', (e) => {
  3. e.preventDefault();
  4. e.clipboardData?.setData('text/plain', s);
  5. document.removeEventListener('copy', listener);
  6. });
  7. if (!navigator.clipboard) {
  8. document.execCommand('copy');
  9. } else {
  10. navigator.clipboard.writeText(s).catch((e) => {
  11. console.log(e);
  12. console.log('failed to copy');
  13. });
  14. }
  15. };
  16. const buildGuesses = () => {
  17. const rows = document
  18. .querySelector('game-app')
  19. .shadowRoot.querySelector('game-theme-manager')
  20. .querySelectorAll('game-row');
  21. const isDarkMode = window.localStorage.darkTheme === 'true';
  22. return [...rows]
  23. .map((row) => {
  24. const guess = row.attributes.letters.value;
  25. if (!guess) {
  26. return null;
  27. }
  28. const colors = [...row.shadowRoot.querySelectorAll('game-tile')]
  29. .map((letter) => {
  30. switch (letter.attributes.evaluation.value) {
  31. case 'present':
  32. return '🟨';
  33. case 'correct':
  34. return '🟩';
  35. default:
  36. return isDarkMode ? '⬛' : '⬜';
  37. }
  38. })
  39. .join('');
  40. return `${colors} [spoiler]${guess.toUpperCase()}[/spoiler]`;
  41. })
  42. .filter((el) => !!el);
  43. };
  44. const buildShareCopy = () => {
  45. const number = document.querySelector('[data-day-offset]').dataset.dayOffset;
  46. const hardMode =
  47. document.querySelector('[data-is-hard-mode]').dataset.isHardMode === 'true'
  48. ? '*'
  49. : '';
  50. const guesses = buildGuesses();
  51. const guessesCopy = guesses.join('\n');
  52. return `Wordle ${number} ${guesses.length}/6${hardMode}\n\n${guessesCopy}`;
  53. };
  54. const handleClick = (e) => {
  55. e.preventDefault();
  56. e.stopPropagation();
  57. const shareCopy = buildShareCopy();
  58. const toastContainer = document
  59. .querySelector('game-app')
  60. .shadowRoot.querySelector('game-theme-manager')
  61. .querySelector('#system-toaster');
  62. const toast = document.createElement('game-toast');
  63. toast.setAttribute('text', 'Copied results to clipboard');
  64. toast.setAttribute('duration', '2000');
  65. toastContainer.appendChild(toast);
  66. copyToClipboard(shareCopy);
  67. };
  68. const buildButton = () => {
  69. const button = document.createElement('button');
  70. button.id = 'extended-share-button';
  71. button.innerText = 'Share ++';
  72. button.addEventListener('click', handleClick);
  73. button.style.cssText = `
  74. align-items: center;
  75. background-color: var(--key-bg-correct);
  76. border-radius: 4px;
  77. border: none;
  78. color: var(--key-evaluated-text-color);
  79. cursor: pointer;
  80. display: flex;
  81. filter: brightness(100%);
  82. font-family: inherit;
  83. font-size: 20px;
  84. font-weight: bold;
  85. height: 52px;
  86. justify-content: center;
  87. margin-top: 10px;
  88. text-transform: uppercase;
  89. userSelect: none;
  90. width: 80%;
  91. `;
  92. return button;
  93. };
  94. const readyStateCheckInterval = setInterval(() => {
  95. const script = document.createElement('script');
  96. script.innerText = `
  97. (() => {
  98. const app = new window.wordle.bundle.GameApp();
  99. const offset = document.createElement('span');
  100. offset.dataset.dayOffset = app.dayOffset;
  101. document.body.appendChild(offset);
  102. const hardMode = document.createElement('span');
  103. hardMode.dataset.isHardMode = app.hardMode;
  104. document.body.appendChild(hardMode);
  105. })();
  106. `;
  107. document.body.appendChild(script);
  108. const el = document
  109. .querySelector('game-app')
  110. .shadowRoot.querySelector('game-theme-manager')
  111. .querySelector('game-modal game-stats');
  112. if (el && !el.querySelector('#extended-share-button')) {
  113. clearInterval(readyStateCheckInterval);
  114. const button = buildButton();
  115. const shareContainer = el.shadowRoot.querySelector('.share');
  116. shareContainer.style.flexDirection = 'column';
  117. shareContainer
  118. .querySelectorAll('#extended-share-button')
  119. .forEach((el) => el.remove());
  120. shareContainer.appendChild(button);
  121. }
  122. }, 1000);