this repo has no description
0
fork

Configure Feed

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

wip

+252 -6
+252 -6
index.html
··· 979 979 font-size: 0.75rem; 980 980 margin-top: 3px; 981 981 } 982 + 983 + /* Styles for filter container */ 984 + .filter-container { 985 + display: flex; 986 + align-items: center; 987 + margin-bottom: 15px; 988 + padding: 10px 15px; 989 + background-color: var(--card-bg); 990 + border: 1px solid var(--border-color); 991 + border-radius: 4px; 992 + } 993 + 994 + .filter-title { 995 + font-family: 'JetBrains Mono', monospace; 996 + color: var(--accent-color); 997 + font-size: 0.9rem; 998 + margin-right: 15px; 999 + } 1000 + 1001 + .filter-options { 1002 + display: flex; 1003 + gap: 15px; 1004 + } 1005 + 1006 + .filter-option { 1007 + position: relative; 1008 + display: flex; 1009 + align-items: center; 1010 + cursor: pointer; 1011 + user-select: none; 1012 + } 1013 + 1014 + .filter-checkbox { 1015 + position: absolute; 1016 + opacity: 0; 1017 + height: 0; 1018 + width: 0; 1019 + } 1020 + 1021 + .checkbox-custom { 1022 + position: relative; 1023 + display: inline-block; 1024 + width: 16px; 1025 + height: 16px; 1026 + background-color: rgba(77, 250, 123, 0.05); 1027 + border: 1px solid var(--accent-alt); 1028 + border-radius: 3px; 1029 + margin-right: 8px; 1030 + transition: all 0.2s ease; 1031 + } 1032 + 1033 + .filter-checkbox:checked + .checkbox-custom::after { 1034 + content: ''; 1035 + position: absolute; 1036 + top: 2px; 1037 + left: 5px; 1038 + width: 5px; 1039 + height: 8px; 1040 + border: solid var(--accent-color); 1041 + border-width: 0 2px 2px 0; 1042 + transform: rotate(45deg); 1043 + } 1044 + 1045 + .filter-checkbox:checked + .checkbox-custom { 1046 + background-color: rgba(77, 250, 123, 0.15); 1047 + border-color: var(--accent-color); 1048 + } 1049 + 1050 + .filter-label { 1051 + font-size: 0.85rem; 1052 + color: var(--text-color); 1053 + } 1054 + 1055 + .filter-option:hover .checkbox-custom { 1056 + background-color: rgba(77, 250, 123, 0.1); 1057 + border-color: var(--accent-color); 1058 + } 982 1059 983 1060 @media (max-width: 600px) { 984 1061 .feed-item-author { ··· 1056 1133 <p class="loading-text">Growing Content...</p> 1057 1134 </div> 1058 1135 <div id="feed-items" class="tab-content active feed-container" data-tab="posts"></div> 1059 - <div id="link-items" class="tab-content feed-container" data-tab="links"></div> 1136 + <div class="tab-content" data-tab="links"> 1137 + <div class="filter-container"> 1138 + <div class="filter-title">Filter:</div> 1139 + <div class="filter-options"> 1140 + <label class="filter-option"> 1141 + <input type="checkbox" id="filter-papers" class="filter-checkbox" data-filter="academic"> 1142 + <span class="checkbox-custom"></span> 1143 + <span class="filter-label">Papers</span> 1144 + </label> 1145 + <label class="filter-option"> 1146 + <input type="checkbox" id="filter-videos" class="filter-checkbox" data-filter="youtube"> 1147 + <span class="checkbox-custom"></span> 1148 + <span class="filter-label">Videos</span> 1149 + </label> 1150 + </div> 1151 + </div> 1152 + <div id="link-items" class="feed-container"></div> 1153 + </div> 1060 1154 <div id="people-items" class="tab-content" data-tab="people"> 1061 1155 <h2 class="people-header">EEG Sources</h2> 1062 1156 <div class="people-container"></div> ··· 1931 2025 url.hostname.includes('arxiv.org') || 1932 2026 url.hostname.includes('nature.com') || 1933 2027 url.hostname.includes('science.org') || 1934 - url.hostname.includes('mdpi.com') 2028 + url.hostname.includes('mdpi.com') || 2029 + url.hostname.includes('doi.org') 1935 2030 ) { 1936 2031 // Set display text based on source 1937 2032 if (url.hostname.includes('arxiv.org')) { ··· 1966 2061 else if (url.hostname.includes('wikipedia')) linkType = 'wikipedia'; 1967 2062 else if (url.hostname === 'twitter.com' || url.hostname === 'x.com') linkType = 'twitter'; 1968 2063 else if (url.hostname.includes('linkedin.com')) linkType = 'linkedin'; 1969 - else if (url.hostname.includes('youtube.com') || url.hostname === 'youtu.be') linkType = 'youtube'; 2064 + else if ( 2065 + url.hostname.includes('youtube.com') || 2066 + url.hostname === 'youtu.be' || 2067 + url.hostname === 'watch.eeg.cl.cam.ac.uk' || 2068 + url.hostname === 'crank.recoil.org' || 2069 + url.hostname === 'watch.ocaml.org' 2070 + ) linkType = 'youtube'; 1970 2071 else if (url.hostname.includes('medium.com')) linkType = 'medium'; 1971 2072 else if (url.hostname.includes('stackoverflow.com')) linkType = 'stackoverflow'; 1972 2073 else if (url.hostname === 'dev.to') linkType = 'dev'; ··· 2269 2370 if (parts.length >= 2 && parts[0] === 'in') { 2270 2371 displayText = parts[1]; 2271 2372 } 2272 - } else if (url.hostname.includes('youtube.com') || url.hostname === 'youtu.be') { 2373 + } else if ( 2374 + url.hostname.includes('youtube.com') || 2375 + url.hostname === 'youtu.be' || 2376 + url.hostname === 'watch.eeg.cl.cam.ac.uk' || 2377 + url.hostname === 'crank.recoil.org' || 2378 + url.hostname === 'watch.ocaml.org' 2379 + ) { 2273 2380 iconPath = 'brands-youtube.svg'; 2274 - displayText = 'YouTube Video'; 2381 + 2382 + // Custom display text for specific video platforms 2383 + if (url.hostname.includes('youtube.com') || url.hostname === 'youtu.be') { 2384 + displayText = 'YouTube Video'; 2385 + } else if (url.hostname === 'watch.eeg.cl.cam.ac.uk') { 2386 + displayText = 'EEG Video'; 2387 + } else if (url.hostname === 'crank.recoil.org') { 2388 + displayText = 'Crank Video'; 2389 + } else if (url.hostname === 'watch.ocaml.org') { 2390 + displayText = 'OCaml Video'; 2391 + } else { 2392 + displayText = 'Video'; 2393 + } 2275 2394 } else if (url.hostname === 'ocaml.org' && url.pathname.startsWith('/p/')) { 2276 2395 const parts = url.pathname.substring(1).split('/').filter(part => part); 2277 2396 if (parts.length >= 2) { ··· 2342 2461 url.hostname.includes('arxiv.org') || 2343 2462 url.hostname.includes('nature.com') || 2344 2463 url.hostname.includes('science.org') || 2345 - url.hostname.includes('mdpi.com') 2464 + url.hostname.includes('mdpi.com') || 2465 + url.hostname.includes('doi.org') 2346 2466 ) { 2347 2467 iconPath = 'free-icons/svgs/regular-file-pdf.svg'; 2348 2468 ··· 2525 2645 2526 2646 // Initialize tabs 2527 2647 setupTabs(); 2648 + 2649 + // Setup link filtering based on checkboxes 2650 + setupLinkFilters(); 2651 + 2652 + // Function to handle link filtering 2653 + function setupLinkFilters() { 2654 + const filterCheckboxes = document.querySelectorAll('.filter-checkbox'); 2655 + 2656 + filterCheckboxes.forEach(checkbox => { 2657 + checkbox.addEventListener('change', updateFilter); 2658 + }); 2659 + 2660 + function updateFilter() { 2661 + // Get all checked filters 2662 + const activeFilters = Array.from(document.querySelectorAll('.filter-checkbox:checked')) 2663 + .map(checkbox => checkbox.getAttribute('data-filter')); 2664 + 2665 + // Get all link items 2666 + const allLinkItems = document.querySelectorAll('.link-item'); 2667 + const monthYearHeaders = document.querySelectorAll('.month-year-header'); 2668 + 2669 + // Show all items if no filters are selected 2670 + if (activeFilters.length === 0) { 2671 + allLinkItems.forEach(item => { 2672 + item.style.display = ''; 2673 + }); 2674 + monthYearHeaders.forEach(header => { 2675 + header.style.display = ''; 2676 + }); 2677 + return; 2678 + } 2679 + 2680 + // Track visible items per month/year 2681 + const visibleByMonthYear = new Map(); 2682 + 2683 + // Process all items 2684 + allLinkItems.forEach(item => { 2685 + const linkUrl = item.querySelector('.link-item-url'); 2686 + let shouldShow = false; 2687 + 2688 + // Papers filter - check for PDF icon 2689 + if (activeFilters.includes('academic')) { 2690 + const hasPdfIcon = linkUrl && ( 2691 + linkUrl.innerHTML.includes('regular-file-pdf.svg') || 2692 + (linkUrl.getAttribute('data-link-type') === 'academic') 2693 + ); 2694 + if (hasPdfIcon) shouldShow = true; 2695 + } 2696 + 2697 + // Videos filter - check for YouTube icon or video domains 2698 + if (activeFilters.includes('youtube')) { 2699 + const hasYoutubeIcon = linkUrl && ( 2700 + linkUrl.innerHTML.includes('brands-youtube.svg') || 2701 + (linkUrl.getAttribute('data-link-type') === 'youtube') 2702 + ); 2703 + 2704 + // Also check for specific video site URLs 2705 + const url = linkUrl?.getAttribute('href'); 2706 + const isVideoSite = url && ( 2707 + url.includes('youtube.com') || 2708 + url.includes('youtu.be') || 2709 + url.includes('watch.eeg.cl.cam.ac.uk') || 2710 + url.includes('crank.recoil.org') || 2711 + url.includes('watch.ocaml.org') 2712 + ); 2713 + 2714 + if (hasYoutubeIcon || isVideoSite) shouldShow = true; 2715 + } 2716 + 2717 + // Set visibility 2718 + item.style.display = shouldShow ? '' : 'none'; 2719 + 2720 + // Track visible items by month/year 2721 + if (shouldShow) { 2722 + const year = item.getAttribute('data-year'); 2723 + const month = item.getAttribute('data-month'); 2724 + const key = `${year}-${month}`; 2725 + visibleByMonthYear.set(key, (visibleByMonthYear.get(key) || 0) + 1); 2726 + } 2727 + }); 2728 + 2729 + // Hide month-year headers with no visible items 2730 + monthYearHeaders.forEach(header => { 2731 + const year = header.getAttribute('data-year'); 2732 + const month = header.getAttribute('data-month'); 2733 + const key = `${year}-${month}`; 2734 + 2735 + if (visibleByMonthYear.has(key)) { 2736 + header.style.display = ''; // Show if has visible items 2737 + } else { 2738 + header.style.display = 'none'; // Hide if no visible items 2739 + } 2740 + }); 2741 + 2742 + // Update timeline sidebar to match visible items 2743 + const timelineYears = document.querySelectorAll('.timeline-year'); 2744 + const timelineMonths = document.querySelectorAll('.timeline-month'); 2745 + 2746 + // First get all years that have visible items 2747 + const visibleYears = new Set(); 2748 + visibleByMonthYear.forEach((count, key) => { 2749 + const [year] = key.split('-'); 2750 + visibleYears.add(year); 2751 + }); 2752 + 2753 + // Hide years without visible items 2754 + if (activeFilters.length > 0) { 2755 + timelineYears.forEach(yearEl => { 2756 + const year = yearEl.getAttribute('data-year'); 2757 + yearEl.style.display = visibleYears.has(year) ? '' : 'none'; 2758 + }); 2759 + 2760 + // Hide months without visible items 2761 + timelineMonths.forEach(monthEl => { 2762 + const year = monthEl.getAttribute('data-year'); 2763 + const month = monthEl.getAttribute('data-month'); 2764 + const key = `${year}-${month}`; 2765 + monthEl.style.display = visibleByMonthYear.has(key) ? '' : 'none'; 2766 + }); 2767 + } else { 2768 + // Show all timeline elements when no filters 2769 + timelineYears.forEach(yearEl => yearEl.style.display = ''); 2770 + timelineMonths.forEach(monthEl => monthEl.style.display = ''); 2771 + } 2772 + } 2773 + } 2528 2774 2529 2775 // Make timeline items clickable to scroll to relevant posts or links 2530 2776 document.querySelectorAll('.timeline-year, .timeline-month').forEach(item => {