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.3KB

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