Updated UI style to be more modern

Updated headless browser to get images, videos and gifs!
This commit is contained in:
2025-11-20 14:25:23 -05:00
parent 6ddc45b989
commit aa5ac304bd
8 changed files with 850 additions and 327 deletions

View File

@@ -7,14 +7,12 @@ export async function populateSources(sourceList) {
if (sources && sources.length > 0) {
sources.forEach((source) => {
const button = document.createElement('button');
button.className =
'source-button w-12 h-12 flex items-center justify-center rounded-xl text-gray-400 hover:bg-gray-700 hover:text-white transition-all duration-200';
button.className = 'source-button hover:bg-gray-700 hover:text-white transition-all duration-200';
button.dataset.source = source.name;
button.title = source.name;
const favicon = document.createElement('img');
favicon.className = 'w-8 h-8 rounded';
let mainDomain = source.url;
try {
const hostname = new URL(source.url).hostname;
@@ -25,32 +23,94 @@ export async function populateSources(sourceList) {
mainDomain = hostname;
}
} catch (e) {
console.warn(`Could not parse domain from ${source.url}:`, 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 = () => {
button.innerHTML = `<span class="font-bold text-sm">${source.name.substring(
0,
2
)}</span>`;
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);
});
console.log('Sources populated:', sources);
if (sourceList.children.length > 0) {
const firstButton = sourceList.children[0];
firstButton.classList.add('active');
initialSource = firstButton.dataset.source;
}
setupCarousel(sourceList);
} else {
console.warn('No sources were loaded from the main process.');
console.warn('No sources loaded.');
}
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';
}

View File

@@ -18,8 +18,7 @@ export function showPage(pageId, domRefs, callbacks, state) {
});
document.querySelectorAll('.nav-button').forEach((tab) => {
tab.classList.remove('bg-indigo-600', 'text-white');
tab.classList.add('text-gray-400', 'hover:bg-gray-700');
tab.classList.remove('active');
});
const activePage = document.getElementById(pageId);
@@ -46,7 +45,6 @@ export function showPage(pageId, domRefs, callbacks, state) {
}
if (activeTab) {
activeTab.classList.add('bg-indigo-600', 'text-white');
activeTab.classList.remove('text-gray-400', 'hover:bg-gray-700');
activeTab.classList.add('active');
}
}

View File

@@ -1,6 +1,6 @@
const GITHUB_OWNER = 'ItsSkaiya';
const GITHUB_REPO = 'WaifuBoard';
const CURRENT_VERSION = 'v1.3.1';
const CURRENT_VERSION = 'v1.4.0';
const UPDATE_CHECK_INTERVAL = 5 * 60 * 1000;
let currentVersionDisplay;

View File

@@ -6,14 +6,15 @@ class HeadlessBrowser {
const win = new BrowserWindow({
show: false,
width: 800,
height: 600,
width: 1920,
height: 1080,
webPreferences: {
offscreen: true,
contextIsolation: false,
nodeIntegration: false,
images: true,
images: false,
webgl: false,
backgroundThrottling: false,
},
});
@@ -21,6 +22,26 @@ class HeadlessBrowser {
const userAgent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36';
win.webContents.setUserAgent(userAgent);
const session = win.webContents.session;
const filter = { urls: ['*://*/*'] };
session.webRequest.onBeforeRequest(filter, (details, callback) => {
const url = details.url.toLowerCase();
const blockExtensions = [
'.css', '.woff', '.woff2', '.ttf', '.svg', '.eot',
'google-analytics', 'doubleclick', 'facebook', 'twitter', 'adsystem'
];
const isBlocked = blockExtensions.some(ext => url.includes(ext));
if (isBlocked) {
return callback({ cancel: true });
}
return callback({ cancel: false });
});
await win.loadURL(url, { userAgent });
if (waitSelector) {
@@ -53,8 +74,7 @@ class HeadlessBrowser {
clearTimeout(timer);
resolve(true);
} else {
// FIX: Use setTimeout because requestAnimationFrame stops in hidden windows
setTimeout(check, 100);
setTimeout(check, 50);
}
};
check();