Add Windows support via a Tauri (WebView2) shell
zero-native has no Windows target yet, so add a parallel Tauri shell for Windows that reuses the same frontend: - src-tauri/: Rust commands (yt_search, yt_streams, store_load, store_save) mirroring the Zig bridge; spawns bundled yt-dlp.exe with CREATE_NO_WINDOW; data stored in app_data_dir - frontend bridge now auto-detects window.__TAURI__ vs window.zero and routes accordingly; CSP updated for Tauri IPC - tauri.conf.json bundles yt-dlp.exe as a resource and builds nsis/msi - scripts/make-icon.js generates appicon.png for 'tauri icon' - README: native Windows build steps + WSLg fallback note
This commit is contained in:
@@ -9,19 +9,25 @@
|
||||
* ========================================================================== */
|
||||
|
||||
// ---------- Native bridge adapter ----------
|
||||
async function invoke(command, payload = {}) {
|
||||
if (window.zero && typeof window.zero.invoke === 'function') {
|
||||
return await window.zero.invoke(command, payload);
|
||||
}
|
||||
throw new Error('Native bridge unavailable — run this inside zero-native (zig build run).');
|
||||
// Works against two shells from the same frontend:
|
||||
// • Tauri (Windows / WebView2): window.__TAURI__.core.invoke, snake_case commands
|
||||
// • zero-native (Linux / macOS): window.zero.invoke, dotted commands
|
||||
const TAURI = window.__TAURI__ && window.__TAURI__.core ? window.__TAURI__.core : null;
|
||||
const ZERO = window.zero && typeof window.zero.invoke === 'function' ? window.zero : null;
|
||||
|
||||
// call(zeroName, tauriName, payload) — routes to whichever shell is present.
|
||||
async function call(zeroName, tauriName, payload = {}) {
|
||||
if (TAURI) return await TAURI.invoke(tauriName, payload);
|
||||
if (ZERO) return await ZERO.invoke(zeroName, payload);
|
||||
throw new Error('No native bridge available — run inside the YT Player app.');
|
||||
}
|
||||
|
||||
const API = {
|
||||
search: (query) => invoke('yt.search', { query }),
|
||||
getStreams: (videoId) => invoke('yt.streams', { videoId }),
|
||||
loadData: () => invoke('store.load', {}),
|
||||
search: (query) => call('yt.search', 'yt_search', { query }),
|
||||
getStreams: (videoId) => call('yt.streams', 'yt_streams', { videoId }),
|
||||
loadData: () => call('store.load', 'store_load', {}),
|
||||
// data is sent pre-stringified so the native side can write it verbatim.
|
||||
saveData: (data) => invoke('store.save', { data: JSON.stringify(data) }),
|
||||
saveData: (data) => call('store.save', 'store_save', { data: JSON.stringify(data) }),
|
||||
};
|
||||
|
||||
// ---------- State ----------
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta
|
||||
http-equiv="Content-Security-Policy"
|
||||
content="default-src 'self'; img-src 'self' https: data:; media-src https: blob:; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src https://fonts.gstatic.com data:; script-src 'self'; connect-src 'self' https:;"
|
||||
content="default-src 'self'; img-src 'self' https: data: asset: http://asset.localhost; media-src 'self' https: blob:; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src https://fonts.gstatic.com data:; script-src 'self'; connect-src 'self' https: ipc: http://ipc.localhost;"
|
||||
/>
|
||||
<title>YT Player</title>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
|
||||
Reference in New Issue
Block a user