Greasy Fork is available in English.

dcinside Recommendation Filter

하루종일 갤질만 하는 당신을 위해

  1. // ==UserScript==
  2. // @name dcinside Recommendation Filter
  3. // @name:ko 디시인사이드 추천수 필터
  4. // @namespace https://greatest.deepsurf.us/ko/scripts/520015-dcinside-recommendation-filter
  5. // @version 1.1.0
  6. // @description 하루종일 갤질만 하는 당신을 위해
  7. // @author 봄처럼
  8. // @match https://gall.dcinside.com/*
  9. // @icon https://www.google.com/s2/favicons?domain=gall.dcinside.com
  10. // @grant none
  11. // @run-at document-end
  12. // @license MIT
  13. // ==/UserScript==
  14.  
  15. // 최소 추천수 설정
  16. const MIN_RECOMMEND_COUNT = 3;
  17.  
  18. // 초기 상태 설정
  19. let isFeatureActive = false;
  20. let observer = null; // MutationObserver 중복 실행 방지용
  21.  
  22. // 사용자 스크립트 고유 스타일 추가 (없으면 다른 확장 프로그램이랑 충돌남)
  23. function injectCustomStyles() {
  24. const style = document.createElement('style');
  25. style.innerHTML = `
  26. tr.my-filtered {
  27. display: none !important;
  28. }
  29. `;
  30. document.head.appendChild(style);
  31. }
  32.  
  33. // 필터 적용
  34. function applyFilters() {
  35. const articles = document.querySelectorAll('tr.ub-content');
  36.  
  37. articles.forEach(article => {
  38. const recommendCell = article.querySelector('td.gall_recommend');
  39. if (recommendCell) {
  40. const recommendCount = parseInt(recommendCell.textContent.trim(), 10);
  41.  
  42. if (isFeatureActive && recommendCount < MIN_RECOMMEND_COUNT) {
  43. article.classList.add('my-filtered'); // 필터 적용
  44. } else {
  45. article.classList.remove('my-filtered'); // 필터 해제
  46. }
  47. }
  48. });
  49. }
  50.  
  51. // 텍스트 색상 업데이트 (주간/야간 모드)
  52. function updateTextColor(targetElement) {
  53. if (isFeatureActive) {
  54. targetElement.style.color = '#FFFFFF'; // 활성화 중에는 항상 흰색
  55. } else {
  56. const isDarkMode = document.getElementById('css-darkmode') !== null; // 다크 모드 여부 확인
  57. targetElement.style.color = isDarkMode ? '#cccccc' : '#333333'; // 비활성화 상태에서 모드에 따라 변경
  58. }
  59. }
  60.  
  61. // 필터 토글 및 UI 업데이트
  62. function toggleFilter(targetElement) {
  63. isFeatureActive = !isFeatureActive;
  64. applyFilters(); // 필터 재적용
  65.  
  66. targetElement.innerHTML = isFeatureActive ? '추천<br>많은 글' : '추천';
  67. targetElement.style.backgroundColor = isFeatureActive ? '#34a853' : 'rgba(74, 81, 167, 0)';
  68. updateTextColor(targetElement); // 활성화 여부에 따른 텍스트 색상 변경
  69.  
  70. localStorage.setItem('isFeatureActive', isFeatureActive ? 'true' : 'false');
  71. }
  72.  
  73. // 타겟 버튼 초기화
  74. function initTargetButton() {
  75. // 동적으로 th:nth-child(7) 또는 th:nth-child(6) 중 하나를 선택
  76. let targetElement = document.querySelector("table > thead > tr > th:nth-child(7)");
  77. if (!targetElement) {
  78. targetElement = document.querySelector("table > thead > tr > th:nth-child(6)");
  79. }
  80.  
  81. if (!targetElement || targetElement.hasAttribute('data-clicked')) return;
  82.  
  83. targetElement.setAttribute('data-clicked', 'true');
  84. targetElement.style.cssText = `
  85. cursor: pointer;
  86. background-color: rgba(74, 81, 167, 0);
  87. border-radius: 5px;
  88. padding: 0px 0px;
  89. text-align: center;
  90. `;
  91.  
  92. const storedState = localStorage.getItem('isFeatureActive');
  93. isFeatureActive = storedState === 'true'; // 이전 상태 복원
  94. targetElement.innerHTML = isFeatureActive ? '추천<br>많은 글' : '추천';
  95. targetElement.style.backgroundColor = isFeatureActive ? '#34a853' : 'rgba(74, 81, 167, 0)';
  96. updateTextColor(targetElement); // 초기 텍스트 색상 설정
  97.  
  98. targetElement.addEventListener('click', (event) => {
  99. event.stopPropagation();
  100. toggleFilter(targetElement);
  101. });
  102.  
  103. // DOM 변화 감지로 다크모드 상태 변화 실시간 반영
  104. const observer = new MutationObserver(() => updateTextColor(targetElement));
  105. observer.observe(document.body, { childList: true, subtree: true });
  106. }
  107.  
  108. // DOM 변경 감지 설정 (중복 방지)
  109. function observeDOMChanges() {
  110. if (observer) return; // 이미 Observer가 설정된 경우 종료
  111.  
  112. observer = new MutationObserver(() => {
  113. initTargetButton(); // 버튼 초기화
  114. applyFilters(); // 필터 재적용
  115. });
  116.  
  117. observer.observe(document.body, { childList: true, subtree: true });
  118. }
  119.  
  120. // 초기 실행
  121. window.addEventListener('load', () => {
  122. injectCustomStyles(); // 스타일 추가
  123. initTargetButton(); // 버튼 초기화
  124. applyFilters(); // 초기 필터 적용
  125. observeDOMChanges(); // DOM 변경 감지
  126. });