Add ad-free YouTube player built on zero-native
Desktop YouTube player with no login and no ads. Extracts direct video/audio streams with yt-dlp and plays them in a native window via zero-native (Zig + system WebView) for a tiny footprint vs Electron. - Dual-stream engine: muted video synced with separate audio track for high quality without ffmpeg muxing; progressive fallback - On-device playlists, watch history, audio-only mode - Full custom controls: seek, volume, speed, quality, fullscreen, queue - Zig bridge handlers spawn yt-dlp and return slimmed JSON to the web UI - Cinematic dark UI: Bricolage/Hanken/JetBrains Mono, vermilion accent
This commit is contained in:
56
src/main.zig
Normal file
56
src/main.zig
Normal file
@@ -0,0 +1,56 @@
|
||||
//! YT Player — zero-native app entry.
|
||||
//!
|
||||
//! This file shows how the App is wired to the runtime and how the bridge
|
||||
//! handlers in `bridge.zig` are registered. When you scaffold with
|
||||
//! `zero-native init`, a `src/main.zig` + `src/runner.zig` + `build.zig` are
|
||||
//! generated for your installed version. Merge the `bridge()` registration and
|
||||
//! the `handlers`/`policies` below into that generated App — the handler
|
||||
//! implementations themselves live in `bridge.zig` and need no changes.
|
||||
|
||||
const std = @import("std");
|
||||
const zero_native = @import("zero_native");
|
||||
const handlers_impl = @import("bridge.zig");
|
||||
|
||||
const Handler = zero_native.bridge.Handler;
|
||||
|
||||
// Commands the UI is allowed to call, matched against window.zero.invoke names.
|
||||
const policies = [_]zero_native.bridge.CommandPolicy{
|
||||
.{ .command = "yt.search" },
|
||||
.{ .command = "yt.streams" },
|
||||
.{ .command = "store.load" },
|
||||
.{ .command = "store.save" },
|
||||
};
|
||||
|
||||
pub const App = struct {
|
||||
handlers: [4]Handler = undefined,
|
||||
|
||||
pub fn app(self: *App) zero_native.App {
|
||||
return .{
|
||||
.context = self,
|
||||
.name = "YT Player",
|
||||
// Serve the packaged static UI from the zero://app origin.
|
||||
.source = zero_native.WebViewSource.packaged("frontend", "index.html"),
|
||||
.bridge = bridge(self),
|
||||
};
|
||||
}
|
||||
|
||||
fn bridge(self: *App) zero_native.BridgeDispatcher {
|
||||
self.handlers = .{
|
||||
.{ .name = "yt.search", .context = self, .invoke_fn = handlers_impl.ytSearch },
|
||||
.{ .name = "yt.streams", .context = self, .invoke_fn = handlers_impl.ytStreams },
|
||||
.{ .name = "store.load", .context = self, .invoke_fn = handlers_impl.storeLoad },
|
||||
.{ .name = "store.save", .context = self, .invoke_fn = handlers_impl.storeSave },
|
||||
};
|
||||
return .{
|
||||
.policy = .{ .enabled = true, .commands = &policies },
|
||||
.registry = .{ .handlers = &self.handlers },
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
pub fn main() !void {
|
||||
var instance: App = .{};
|
||||
var runtime = try zero_native.Runtime.init(std.heap.page_allocator);
|
||||
defer runtime.deinit();
|
||||
try runtime.run(instance.app());
|
||||
}
|
||||
Reference in New Issue
Block a user