feat: rewrite frontend in haxe
This commit is contained in:
parent
6f73a3a698
commit
cea7a26aeb
|
@ -1,6 +0,0 @@
|
|||
// Formatter configuration for the KubeJS scripts.
|
||||
{
|
||||
tabWidth: 4,
|
||||
trailingComma: "all",
|
||||
}
|
||||
|
3
build.hxml
Normal file
3
build.hxml
Normal file
|
@ -0,0 +1,3 @@
|
|||
# This only exists for haxe_language_server. It is not used for building!
|
||||
-cp frontend
|
||||
--js .js
|
75
build.zig
75
build.zig
|
@ -1,6 +1,6 @@
|
|||
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
|
||||
// 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
|
||||
|
@ -11,6 +11,8 @@ pub fn build(b: *std.build.Builder) void {
|
|||
// between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall.
|
||||
const mode = b.standardReleaseOptions();
|
||||
|
||||
const opts = b.addOptions();
|
||||
|
||||
const exe = b.addExecutable("vidzig", "src/main.zig");
|
||||
exe.setTarget(target);
|
||||
exe.setBuildMode(mode);
|
||||
|
@ -19,6 +21,11 @@ pub fn build(b: *std.build.Builder) void {
|
|||
|
||||
deps(exe);
|
||||
|
||||
const frontend_step = try BuildFrontendStep.init(b, opts);
|
||||
exe.step.dependOn(&frontend_step.step);
|
||||
|
||||
exe.addOptions("opts", opts);
|
||||
|
||||
exe.install();
|
||||
|
||||
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");
|
||||
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 {
|
||||
|
@ -76,3 +75,61 @@ const onion_sources = [_][]const u8{
|
|||
"deps/onion/src/onion/version.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
21
frontend/EnqueueTask.hx
Normal 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
40
frontend/Index.hx
Normal 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
17
frontend/PauseButton.hx
Normal 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
13
frontend/Util.hx
Normal 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
51
hxformat.json
Normal 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": " "
|
||||
}
|
||||
}
|
|
@ -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();
|
|
@ -87,7 +87,7 @@ pub fn main() !void {
|
|||
_ = c.onion_url_add(
|
||||
urls,
|
||||
"static/index.js",
|
||||
routes.comptimeStatic(@embedFile("assets/index.js"), "application/javascript"),
|
||||
routes.comptimeStatic(@import("opts").index_js, "application/javascript"),
|
||||
);
|
||||
_ = c.onion_url_add(
|
||||
urls,
|
||||
|
|
Loading…
Reference in a new issue