Added in Book Boards! (NEW!) Updated rendering logic Updated search logic Updated extension loading logic Updated image handling logic
130 lines
3.7 KiB
JavaScript
130 lines
3.7 KiB
JavaScript
export async function populateSources(sourceList, targetType = 'image-board') {
|
|
console.log(`Requesting sources for type: ${targetType}...`);
|
|
const sources = await window.api.getSources();
|
|
sourceList.innerHTML = '';
|
|
let initialSource = '';
|
|
|
|
console.log("Raw sources received:", sources);
|
|
|
|
if (sources && sources.length > 0) {
|
|
sources.forEach((source) => {
|
|
|
|
if (targetType !== 'all' && source.type !== targetType) {
|
|
return;
|
|
}
|
|
|
|
const button = document.createElement('button');
|
|
|
|
button.className = 'source-button hover:bg-gray-700 hover:text-white transition-all duration-200';
|
|
|
|
button.dataset.source = source.name;
|
|
button.title = source.name;
|
|
|
|
let mainDomain = source.url;
|
|
try {
|
|
const urlToParse = source.url || source.baseUrl || "";
|
|
if (urlToParse) {
|
|
const hostname = new URL(urlToParse).hostname;
|
|
const parts = hostname.split('.');
|
|
if (parts.length > 2 && ['api', 'www'].includes(parts[0])) {
|
|
mainDomain = parts.slice(1).join('.');
|
|
} else {
|
|
mainDomain = hostname;
|
|
}
|
|
} else {
|
|
mainDomain = source.name;
|
|
}
|
|
} catch (e) {
|
|
mainDomain = source.name;
|
|
}
|
|
|
|
const favicon = document.createElement('img');
|
|
favicon.className = 'source-icon rounded';
|
|
favicon.src = `https://www.google.com/s2/favicons?domain=${mainDomain}&sz=32`;
|
|
favicon.alt = source.name;
|
|
|
|
const textWrapper = document.createElement('div');
|
|
textWrapper.className = 'source-text-wrapper';
|
|
|
|
const nameSpan = document.createElement('span');
|
|
nameSpan.className = 'source-name';
|
|
nameSpan.textContent = source.name;
|
|
|
|
const urlSpan = document.createElement('span');
|
|
urlSpan.className = 'source-url';
|
|
urlSpan.textContent = mainDomain;
|
|
|
|
textWrapper.appendChild(nameSpan);
|
|
textWrapper.appendChild(urlSpan);
|
|
|
|
favicon.onerror = () => {
|
|
favicon.remove();
|
|
const fallbackIcon = document.createElement('div');
|
|
fallbackIcon.className = 'source-icon fallback';
|
|
fallbackIcon.textContent = source.name.substring(0, 1).toUpperCase();
|
|
button.insertBefore(fallbackIcon, textWrapper);
|
|
};
|
|
|
|
button.appendChild(favicon);
|
|
button.appendChild(textWrapper);
|
|
|
|
sourceList.appendChild(button);
|
|
});
|
|
|
|
if (sourceList.children.length > 0) {
|
|
const firstButton = sourceList.children[0];
|
|
firstButton.classList.add('active');
|
|
initialSource = firstButton.dataset.source;
|
|
} else {
|
|
console.warn(`No sources found for type: ${targetType}`);
|
|
}
|
|
|
|
setupCarousel(sourceList);
|
|
|
|
} else {
|
|
console.warn('No sources loaded from API.');
|
|
}
|
|
return initialSource;
|
|
}
|
|
|
|
function setupCarousel(element) {
|
|
element.addEventListener('wheel', (evt) => {
|
|
if (evt.deltaY !== 0) {
|
|
if (element.scrollWidth > element.clientWidth) {
|
|
evt.preventDefault();
|
|
element.scrollLeft += evt.deltaY;
|
|
}
|
|
}
|
|
});
|
|
|
|
let isDown = false;
|
|
let startX;
|
|
let scrollLeft;
|
|
|
|
element.addEventListener('mousedown', (e) => {
|
|
isDown = true;
|
|
element.style.cursor = 'grabbing';
|
|
startX = e.pageX - element.offsetLeft;
|
|
scrollLeft = element.scrollLeft;
|
|
});
|
|
|
|
element.addEventListener('mouseleave', () => {
|
|
isDown = false;
|
|
element.style.cursor = 'grab';
|
|
});
|
|
|
|
element.addEventListener('mouseup', () => {
|
|
isDown = false;
|
|
element.style.cursor = 'grab';
|
|
});
|
|
|
|
element.addEventListener('mousemove', (e) => {
|
|
if (!isDown) return;
|
|
e.preventDefault();
|
|
const x = e.pageX - element.offsetLeft;
|
|
const walk = (x - startX) * 2;
|
|
element.scrollLeft = scrollLeft - walk;
|
|
});
|
|
|
|
element.style.cursor = 'grab';
|
|
} |