- Тематики: 14 курированных категорий (Зомби, Космос, Вампиры, Постапокалипсис, Шпионы и т.д.) поверх жанров TMDB. discover-tmdb принимает themeKeywords (pipe-OR по with_keywords); для musical/ superhero/martial добавлен extraGenre AND-связкой в movie-режиме. - Стриминг поиска по сайтам: search-movies переведён с invoke→return на event-emit — карточки появляются по мере ответа каждого сайта, не ждут самого медленного. Спиннер виден до первого результата. - Авто-детект логотипа сайта: поле "URL иконки" убрано из формы. Бэк IPC detect-logo пробует manifest.json → apple-touch-icon → link rel=icon ≥48px → JSON-LD → og:image → msapplication-TileImage → /favicon.ico (с проверкой content-type=image/*). Легаси-приложения без иконки догоняются тихо при открытии Settings.
61 lines
3.2 KiB
JavaScript
61 lines
3.2 KiB
JavaScript
const { contextBridge, ipcRenderer } = require('electron');
|
|
|
|
contextBridge.exposeInMainWorld('electron', {
|
|
createView: (name, url, imageUrl, zoom, useProxy) =>
|
|
ipcRenderer.send('create-view', name, url, imageUrl, zoom, useProxy),
|
|
confirm: (text, funcName) => ipcRenderer.send('confirm', text, funcName),
|
|
removeView: (name) => ipcRenderer.send('remove-view', name),
|
|
hideView: () => ipcRenderer.send('hide-view'),
|
|
showView: (name) => ipcRenderer.send('show-view', name),
|
|
adjustView: (expanded) => ipcRenderer.send('adjust-view', expanded),
|
|
on: (channel, func) => {
|
|
const listener = (_event, ...args) => func(...args);
|
|
ipcRenderer.on(channel, listener);
|
|
return () => ipcRenderer.removeListener(channel, listener);
|
|
},
|
|
handleAction: (action) => ipcRenderer.send('action', action),
|
|
setProxy: (host, port) => ipcRenderer.send('set-proxy', host, port),
|
|
expandWithHeader: () => ipcRenderer.send('expandWithHeader'),
|
|
collapseWithHeader: () => ipcRenderer.send('collapseWithHeader'),
|
|
backwardPage: () => ipcRenderer.send('backwardPage'),
|
|
forwardPage: () => ipcRenderer.send('forwardPage'),
|
|
refreshPage: () => ipcRenderer.send('refreshPage'),
|
|
getCurrentPage: () => ipcRenderer.invoke('get-current-page'),
|
|
getPageMeta: () => ipcRenderer.invoke('get-page-meta'),
|
|
installUpdate: () => ipcRenderer.invoke('install-update'),
|
|
checkUpdateNow: () => ipcRenderer.invoke('check-update-now'),
|
|
readConfig: () => ipcRenderer.invoke('read-config'),
|
|
writeConfig: (data) => ipcRenderer.send('write-config', data),
|
|
// Streaming: возвращает unsubscribe(). onResult({ source, results }) вызывается по мере прихода
|
|
// ответов от каждого сайта; onDone() — когда все сайты ответили.
|
|
// Слушатели снимаются автоматически после onDone (или вручную через возвращённую функцию).
|
|
searchMoviesStream: (query, sites, onResult, onDone) => {
|
|
const searchId = `s_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
let active = true;
|
|
const cleanup = () => {
|
|
if (!active) return;
|
|
active = false;
|
|
ipcRenderer.removeListener('search-movies-result', resultListener);
|
|
ipcRenderer.removeListener('search-movies-done', doneListener);
|
|
};
|
|
const resultListener = (_event, payload) => {
|
|
if (active && payload.searchId === searchId) onResult({ source: payload.source, results: payload.results });
|
|
};
|
|
const doneListener = (_event, payload) => {
|
|
if (active && payload.searchId === searchId) {
|
|
try { onDone(); } finally { cleanup(); }
|
|
}
|
|
};
|
|
ipcRenderer.on('search-movies-result', resultListener);
|
|
ipcRenderer.on('search-movies-done', doneListener);
|
|
ipcRenderer.send('search-movies-start', searchId, query, sites);
|
|
return cleanup;
|
|
},
|
|
searchTmdb: (query, apiKey) => ipcRenderer.invoke('search-tmdb', query, apiKey),
|
|
discoverTmdb: (params) => ipcRenderer.invoke('discover-tmdb', params),
|
|
detectLogo: (siteUrl) => ipcRenderer.invoke('detect-logo', siteUrl),
|
|
toggleKiosk: () => ipcRenderer.invoke('toggle-kiosk'),
|
|
isKiosk: () => ipcRenderer.invoke('is-kiosk'),
|
|
|
|
});
|