Pinning fave threads

Закрепление тем в разделе "Закладки" (Мастхэв для закладчиков)

  1. // ==UserScript==
  2. // @name Pinning fave threads
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.5
  5. // @description Закрепление тем в разделе "Закладки" (Мастхэв для закладчиков)
  6. // @author Nicky (https://zelenka.guru/members/2259792/)
  7. // @match https://zelenka.guru/*
  8. // @icon https://www.google.com/s2/favicons?sz=64&domain=zelenka.guru
  9. // @grant GM_getValue
  10. // @grant GM_setValue
  11. // @license MIT
  12. // ==/UserScript==
  13.  
  14. async function main() {
  15. var savedThreads = GM_getValue('savedThreads', []);
  16. var uniqueThreads = [];
  17.  
  18. function refreshButtons() {
  19. let controlsElements = document.querySelectorAll(".controls");
  20. let buttons = document.querySelectorAll(".pin");
  21.  
  22. buttons.forEach(button => button.parentNode.removeChild(button));
  23.  
  24. for (let controlEl of controlsElements) {
  25. let thread = controlEl.closest('.discussionListItem');
  26. let temp = thread.outerHTML;
  27.  
  28. let pinBtn = document.createElement("a");
  29. pinBtn.classList.add('pin', 'far', 'fa-thumbtack', 'Tooltip', 'threadControl');
  30. if (thread.closest('.stickyThreads')) {
  31. pinBtn.style.color = 'rgb(0, 186, 120)';
  32. pinBtn.title = 'Открепить';
  33. } else {
  34. pinBtn.title = 'Закрепить';
  35. }
  36. if (screen.width < 610) {
  37. pinBtn.style.cssText += 'display: inline-block; position: absolute; right: 20px; bottom: 20px;'
  38. }
  39. pinBtn.addEventListener('click', function(event) {
  40. event.preventDefault();
  41. if (thread.closest('.stickyThreads')) {
  42. unpinThread(temp, thread);
  43. } else {
  44. pinThread(temp);
  45. }
  46. });
  47.  
  48. if (screen.width < 610)
  49. thread.appendChild(pinBtn);
  50. else
  51. controlEl.appendChild(pinBtn);
  52. XenForo.Tooltip($(pinBtn));
  53. }
  54. }
  55.  
  56. async function pinThread(element) {
  57. savedThreads.push(element);
  58. GM_setValue("savedThreads", savedThreads);
  59. refreshList();
  60. refreshButtons();
  61. }
  62.  
  63. async function unpinThread(element, thread) {
  64. savedThreads = savedThreads.filter((string) => string !== element);
  65. GM_setValue("savedThreads", savedThreads);
  66. $(thread)[0].remove()
  67. refreshList();
  68. refreshButtons();
  69. }
  70.  
  71. function refreshList() {
  72. let stickyListThreads = document.querySelector('.stickyThreads');
  73.  
  74. if (!stickyListThreads) {
  75. $('.discussionListItems').prepend('<div class="stickyThreads">');
  76. stickyListThreads = document.querySelector('.stickyThreads');
  77. }
  78.  
  79. let latestThreads = document.querySelector('.latestThreads._insertLoadedContent');
  80.  
  81. for (let thread of savedThreads) {
  82. thread = $(thread);
  83. let temp = thread[0].outerHTML
  84. if (!uniqueThreads.includes(thread[0].outerHTML)) {
  85. uniqueThreads.push(temp);
  86. if (thread.closest('.stickyThreads').length == 0) {
  87. stickyListThreads.insertBefore(thread[0], stickyListThreads.firstChild);
  88. }
  89. }
  90.  
  91. }
  92. for (let thread of uniqueThreads) {
  93. if (!savedThreads.includes(thread)) {
  94. uniqueThreads = uniqueThreads.filter((string) => string !== thread);
  95. thread = $(thread);
  96. if (thread.closest('.stickyThreads')) {
  97. latestThreads.insertBefore(thread[0], latestThreads.firstChild);
  98. }
  99. }
  100. }
  101. let threads = Array.from(document.getElementsByClassName('discussionListItem'));
  102.  
  103. for (let thread of threads) {
  104. for (let savedThread of savedThreads) {
  105. if ($(savedThread)[0].id == $(thread)[0].id && $(thread).closest('.stickyThreads').length == 0) {
  106. $(thread).remove();
  107. break;
  108. }
  109. }
  110. }
  111. }
  112.  
  113. window.addEventListener('scroll', function() {
  114. if (window.innerHeight + window.pageYOffset >= document.documentElement.scrollHeight - 100) {
  115. refreshList();
  116. refreshButtons();
  117. }
  118. });
  119.  
  120. refreshList();
  121. refreshButtons();
  122. };
  123.  
  124. if (window.location.href.startsWith('https://zelenka.guru/?tab=fave')) {
  125. main();
  126. }
  127.  
  128. var observer = new MutationObserver(function(mutations) {
  129. mutations.forEach(function(mutation) {
  130. if (mutation.target.classList.contains('fave')) {
  131. main()
  132. }
  133. });
  134. });
  135.  
  136. observer.observe($('body')[0], {attributes: true, attributeFilter: ['class']});

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址