feat: rewrite frontend in haxe

This commit is contained in:
LordMZTE 2023-02-04 21:32:19 +01:00
parent 6f73a3a698
commit cea7a26aeb
Signed by: LordMZTE
GPG key ID: B64802DC33A64FF6
10 changed files with 212 additions and 71 deletions

View file

@ -1,6 +0,0 @@
// Formatter configuration for the KubeJS scripts.
{
tabWidth: 4,
trailingComma: "all",
}

3
build.hxml Normal file
View file

@ -0,0 +1,3 @@
# This only exists for haxe_language_server. It is not used for building!
-cp frontend
--js .js

View file

@ -1,6 +1,6 @@
const std = @import("std"); const std = @import("std");
pub fn build(b: *std.build.Builder) void { pub fn build(b: *std.build.Builder) !void {
// Standard target options allows the person running `zig build` to choose // Standard target options allows the person running `zig build` to choose
// what target to build for. Here we do not override the defaults, which // what target to build for. Here we do not override the defaults, which
// means any target is allowed, and the default is native. Other options // means any target is allowed, and the default is native. Other options
@ -11,6 +11,8 @@ pub fn build(b: *std.build.Builder) void {
// between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall.
const mode = b.standardReleaseOptions(); const mode = b.standardReleaseOptions();
const opts = b.addOptions();
const exe = b.addExecutable("vidzig", "src/main.zig"); const exe = b.addExecutable("vidzig", "src/main.zig");
exe.setTarget(target); exe.setTarget(target);
exe.setBuildMode(mode); exe.setBuildMode(mode);
@ -19,6 +21,11 @@ pub fn build(b: *std.build.Builder) void {
deps(exe); deps(exe);
const frontend_step = try BuildFrontendStep.init(b, opts);
exe.step.dependOn(&frontend_step.step);
exe.addOptions("opts", opts);
exe.install(); exe.install();
const run_cmd = exe.run(); const run_cmd = exe.run();
@ -29,14 +36,6 @@ pub fn build(b: *std.build.Builder) void {
const run_step = b.step("run", "Run the app"); const run_step = b.step("run", "Run the app");
run_step.dependOn(&run_cmd.step); run_step.dependOn(&run_cmd.step);
const exe_tests = b.addTest("src/main.zig");
exe_tests.setTarget(target);
exe_tests.setBuildMode(mode);
deps(exe_tests);
const test_step = b.step("test", "Run unit tests");
test_step.dependOn(&exe_tests.step);
} }
fn deps(exe: *std.build.LibExeObjStep) void { fn deps(exe: *std.build.LibExeObjStep) void {
@ -76,3 +75,61 @@ const onion_sources = [_][]const u8{
"deps/onion/src/onion/version.c", "deps/onion/src/onion/version.c",
"deps/onion/src/onion/websocket.c", "deps/onion/src/onion/websocket.c",
}; };
const BuildFrontendStep = struct {
step: std.build.Step,
opts: *std.build.OptionsStep,
b: *std.build.Builder,
pub fn init(b: *std.build.Builder, opts: *std.build.OptionsStep) !*BuildFrontendStep {
const self = try b.allocator.create(BuildFrontendStep);
self.* = .{
.step = std.build.Step.init(.custom, "build_frontend", b.allocator, make),
.opts = opts,
.b = b,
};
return self;
}
pub fn make(step: *std.build.Step) anyerror!void {
const self = @fieldParentPtr(BuildFrontendStep, "step", step);
const outpath = try std.fs.path.join(
self.b.allocator,
&.{ self.b.cache_root, "options", "index.js" },
);
const argv = [_][]const u8{
"haxe",
"-cp",
"frontend",
"-main",
"Index",
"-D",
"dce=full",
"-D",
"js_es=6",
"-D",
"js_classic",
"--js",
outpath,
};
var child = std.ChildProcess.init(&argv, self.b.allocator);
const term = try child.spawnAndWait();
if (!std.meta.eql(term, .{ .Exited = 0 }))
return error.UnexpectedExitCode;
try self.opts.contents.writer().writeAll(
\\pub const index_js = @embedFile("index.js");
\\
);
}
};

21
frontend/EnqueueTask.hx Normal file
View file

@ -0,0 +1,21 @@
import haxe.Json;
import js.html.XMLHttpRequest;
class EnqueueTask {
var url:String;
var outname:Null<String>;
var prepend:Bool;
public function new(url:String, outname:Null<String>, prepend:Bool) {
this.url = url;
this.outname = outname;
this.prepend = prepend;
}
public function send():Void {
var xhr = new XMLHttpRequest();
xhr.open("POST", Util.resolveUrl("vids/"));
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send(Json.stringify(this));
}
}

40
frontend/Index.hx Normal file
View file

@ -0,0 +1,40 @@
import js.html.AnchorElement;
import js.html.XMLHttpRequest;
import js.html.InputElement;
import js.Browser;
function main():Void {
Browser.document.getElementById("enqueue_form").addEventListener("submit", onEnqSubmit);
for (del_btn in Browser.document.getElementsByClassName("vid_del_btn")) {
del_btn.onclick = () -> {
var href = cast(del_btn.parentElement.getElementsByTagName("a")[0], AnchorElement).href;
var xhr = new XMLHttpRequest();
xhr.open("DELETE", href);
xhr.send();
del_btn.parentElement.remove();
};
}
Browser.document.getElementById("pause_btn").onclick = PauseButton.onClick;
PauseButton.updateDisplay();
}
function onEnqSubmit(e:Dynamic):Void {
e.preventDefault();
var url_inp = cast(Browser.document.getElementById("url_inp"), InputElement);
var outname = cast(Browser.document.getElementById("outname_inp"), InputElement).value;
new EnqueueTask(
url_inp.value,
outname.length == 0 ? null : outname,
cast(Browser.document.getElementById("prepend_switch"), InputElement).checked
).send();
url_inp.value = "";
}

17
frontend/PauseButton.hx Normal file
View file

@ -0,0 +1,17 @@
import js.html.XMLHttpRequest;
import js.Browser;
function onClick() {
Util.paused = !Util.paused;
var xhr = new XMLHttpRequest();
xhr.open("POST", Util.resolveUrl("set_paused"));
xhr.send(Std.string(Util.paused));
updateDisplay();
}
function updateDisplay() {
var btn = Browser.document.getElementById("pause_btn");
btn.innerHTML = Util.paused ? "Unpause" : "Pause";
}

13
frontend/Util.hx Normal file
View file

@ -0,0 +1,13 @@
import js.Browser;
@:native("paused")
extern var paused: Bool;
/**
Resolves a relative URL like that used in hrefs to a normal, full URL.
*/
function resolveUrl(s:String):String {
var a = Browser.document.createAnchorElement();
a.href = s;
return a.href;
}

51
hxformat.json Normal file
View file

@ -0,0 +1,51 @@
{
"wrapping": {
"arrayWrap": {
"defaultWrap": "onePerLine",
"rules": [
{
"conditions": [
{
"cond": "totalItemLength <= n",
"value": 50
}
],
"type": "noWrap"
}
]
},
"methodChain": {
"rules": [
{
"conditions": [
{
"cond": "itemCount >= n",
"value": 3
}
],
"type": "onePerLine"
}
]
},
"callParameter": {
"rules": [
{
"conditions": [
{
"cond": "itemCount >= n",
"value": 3
},
{
"cond": "totalItemLength >= n",
"value": 50
}
],
"type": "onePerLine"
}
]
}
},
"indentation": {
"character": " "
}
}

View file

@ -1,55 +0,0 @@
function resolveUrl(s) {
let a = document.createElement("a");
a.href = s;
return a.href;
}
document
.getElementById("enqueue_form")
.addEventListener("submit", function (e) {
e.preventDefault();
const outname = document.getElementById("outname_inp").value;
const data = {
url: document.getElementById("url_inp").value,
outname: outname.length == 0 ? null : outname,
prepend: document.getElementById("prepend_switch").checked,
};
let xhr = new XMLHttpRequest();
xhr.open("POST", resolveUrl("vids/"));
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send(JSON.stringify(data));
document.getElementById("url_inp").value = "";
});
for (let del_btn of document.getElementsByClassName("vid_del_btn")) {
del_btn.onclick = function () {
let xhr = new XMLHttpRequest();
xhr.open(
"DELETE",
del_btn.parentElement.getElementsByTagName("a")[0].href,
);
xhr.send();
del_btn.parentElement.remove();
};
}
function updatePauseButtonDisplay() {
const btn = document.getElementById("pause_btn");
btn.innerHTML = paused ? "Unpause" : "Pause";
}
document.getElementById("pause_btn").onclick = function () {
paused = !paused;
let xhr = new XMLHttpRequest();
xhr.open("POST", resolveUrl("set_paused"));
xhr.send(paused ? "true" : false);
updatePauseButtonDisplay();
};
updatePauseButtonDisplay();

View file

@ -87,7 +87,7 @@ pub fn main() !void {
_ = c.onion_url_add( _ = c.onion_url_add(
urls, urls,
"static/index.js", "static/index.js",
routes.comptimeStatic(@embedFile("assets/index.js"), "application/javascript"), routes.comptimeStatic(@import("opts").index_js, "application/javascript"),
); );
_ = c.onion_url_add( _ = c.onion_url_add(
urls, urls,