From 89404882ab7a9a100eec09837dffdc98dd4bccc1 Mon Sep 17 00:00:00 2001
From: Nik Ivanov <2centnik@gmail.com>
Date: Sun, 12 Apr 2026 23:13:10 +0000
Subject: [PATCH 01/38] progress so far
---
.gitignore | 4 +-
build.py | 7 +-
data/www/client.js | 38 -
data/www/dpad.less | 253 ---
data/www/index.html | 224 +-
data/www/main.css | 17 -
data/www/main.js | 559 -----
data/www/svgControl.js | 265 ---
ui/index.html | 12 +
ui/package-lock.json | 2737 +++++++++++++++++++++++
ui/package.json | 27 +
ui/postcss.config.js | 6 +
ui/src/App.tsx | 148 ++
ui/src/api.ts | 117 +
ui/src/components/AlertModal.tsx | 50 +
ui/src/components/Button.tsx | 33 +
ui/src/components/Card.tsx | 22 +
ui/src/components/DPad.tsx | 77 +
ui/src/components/ProgressBar.tsx | 27 +
ui/src/components/Slider.tsx | 33 +
ui/src/components/Toggle.tsx | 29 +
ui/src/components/ToolsModal.tsx | 115 +
ui/src/hooks/useWorkerRenderer.ts | 59 +
ui/src/index.css | 11 +
ui/src/main.tsx | 10 +
ui/src/renderers/index.ts | 77 +
ui/src/renderers/pathTracing.ts | 41 +
ui/src/renderers/vectorRasterVector.ts | 70 +
ui/src/screens/BeginDrawingScreen.tsx | 40 +
ui/src/screens/ChooseRendererScreen.tsx | 32 +
ui/src/screens/DrawingBeganScreen.tsx | 12 +
ui/src/screens/DrawingPreviewScreen.tsx | 161 ++
ui/src/screens/ExtendToHomeScreen.tsx | 73 +
ui/src/screens/LoadingScreen.tsx | 8 +
ui/src/screens/PenCalibrationScreen.tsx | 89 +
ui/src/screens/RetractBeltsScreen.tsx | 49 +
ui/src/screens/SetTopDistanceScreen.tsx | 59 +
ui/src/screens/SvgUploadScreen.tsx | 91 +
ui/src/screens/UploadProgressScreen.tsx | 84 +
ui/src/svgControl.ts | 225 ++
ui/src/types.ts | 40 +
ui/tailwind.config.js | 8 +
ui/tsconfig.json | 18 +
ui/tsconfig.tsbuildinfo | 1 +
ui/vite.config.ts | 11 +
45 files changed, 4721 insertions(+), 1348 deletions(-)
delete mode 100644 data/www/client.js
delete mode 100644 data/www/dpad.less
delete mode 100644 data/www/main.css
delete mode 100644 data/www/main.js
delete mode 100644 data/www/svgControl.js
create mode 100644 ui/index.html
create mode 100644 ui/package-lock.json
create mode 100644 ui/package.json
create mode 100644 ui/postcss.config.js
create mode 100644 ui/src/App.tsx
create mode 100644 ui/src/api.ts
create mode 100644 ui/src/components/AlertModal.tsx
create mode 100644 ui/src/components/Button.tsx
create mode 100644 ui/src/components/Card.tsx
create mode 100644 ui/src/components/DPad.tsx
create mode 100644 ui/src/components/ProgressBar.tsx
create mode 100644 ui/src/components/Slider.tsx
create mode 100644 ui/src/components/Toggle.tsx
create mode 100644 ui/src/components/ToolsModal.tsx
create mode 100644 ui/src/hooks/useWorkerRenderer.ts
create mode 100644 ui/src/index.css
create mode 100644 ui/src/main.tsx
create mode 100644 ui/src/renderers/index.ts
create mode 100644 ui/src/renderers/pathTracing.ts
create mode 100644 ui/src/renderers/vectorRasterVector.ts
create mode 100644 ui/src/screens/BeginDrawingScreen.tsx
create mode 100644 ui/src/screens/ChooseRendererScreen.tsx
create mode 100644 ui/src/screens/DrawingBeganScreen.tsx
create mode 100644 ui/src/screens/DrawingPreviewScreen.tsx
create mode 100644 ui/src/screens/ExtendToHomeScreen.tsx
create mode 100644 ui/src/screens/LoadingScreen.tsx
create mode 100644 ui/src/screens/PenCalibrationScreen.tsx
create mode 100644 ui/src/screens/RetractBeltsScreen.tsx
create mode 100644 ui/src/screens/SetTopDistanceScreen.tsx
create mode 100644 ui/src/screens/SvgUploadScreen.tsx
create mode 100644 ui/src/screens/UploadProgressScreen.tsx
create mode 100644 ui/src/svgControl.ts
create mode 100644 ui/src/types.ts
create mode 100644 ui/tailwind.config.js
create mode 100644 ui/tsconfig.json
create mode 100644 ui/tsconfig.tsbuildinfo
create mode 100644 ui/vite.config.ts
diff --git a/.gitignore b/.gitignore
index 3f9c08ea..8fc6b9f9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,6 @@
.pio
-data/www/worker/*
-tsc/node_modules
+data/www/*
+node_modules
tsc/package-lock.json
tsc/dist
tsc/dist_packed
diff --git a/build.py b/build.py
index ec94192c..f9c1e1cf 100644
--- a/build.py
+++ b/build.py
@@ -1,7 +1,7 @@
import os
Import("env")
-print("Transpiling TS code")
+print("Transpiling TS worker code")
env.Execute("rm data/www/worker/* || true")
currentPath = os.getcwd()
@@ -10,4 +10,9 @@
if not os.path.exists("../data/www/worker/"):
os.makedirs("../data/www/worker/")
env.Execute("cp dist_packed/main.js ../data/www/worker/worker.js")
+os.chdir(currentPath)
+
+print("Building React UI")
+os.chdir('./ui')
+env.Execute("npm run build")
os.chdir(currentPath)
\ No newline at end of file
diff --git a/data/www/client.js b/data/www/client.js
deleted file mode 100644
index 6767c7e9..00000000
--- a/data/www/client.js
+++ /dev/null
@@ -1,38 +0,0 @@
-export async function leftRetractDown() {
- await postCommand("l-ret");
-}
-
-export async function leftExtendDown() {
- await postCommand("l-ext");
-}
-
-export async function rightRetractDown() {
- await postCommand("r-ret");
-}
-
-export async function rightExtendDown() {
- await postCommand("r-ext");
-}
-
-export async function leftRetractUp() {
- await postCommand("l-0");
-}
-
-export async function leftExtendUp() {
- await postCommand("l-0");
-}
-
-export async function rightRetractUp() {
- await postCommand("r-0");
-}
-
-export async function rightExtendUp() {
- await postCommand("r-0");
-}
-
-async function postCommand(command) {
- $.post("/command", {command}).fail(function() {
- alert("Command failed");
- location.reload();
- });
-}
\ No newline at end of file
diff --git a/data/www/dpad.less b/data/www/dpad.less
deleted file mode 100644
index 11225dc2..00000000
--- a/data/www/dpad.less
+++ /dev/null
@@ -1,253 +0,0 @@
-.set {
- overflow: hidden;
- text-align: center;
- .d-pad { margin-right: 40px; }
- .d-pad, .o-pad {
- display: inline-block;
- // transform: scale(.7);
- }
- }
- .set.setbg { background: #222; }
- .set.setbg2 { background: #5f9837; }
-
-
- @dpad-radius: 17%;
- @dpad-radius-in: 20%;
- @dpad-fg: #ddd;
- @dpad-fg-hover: #eee;
- @dpad-bg: #fff;
- @arrowcolor: #aaa;
- @tri-sml-a: 13px;
- @tri-sml-b: 19px;
- @tri-lrg-a: 13px;
- @tri-lrg-b: 19px;
- @dpad-arrow-shift: 5px;
- @dpad-arrow-move: 35%;
- .d-pad {
- position: relative;
- width: 200px;
- height: 200px;
- border-radius: 48%;
- overflow: hidden;
- &:before {
- content: '';
- position: absolute;
- top: 50%;
- left: 50%;
- border-radius: 5%;
- transform: translate(-50%, -50%);
- width: 66.6%;
- height: 66.6%;
- background: @dpad-fg;
- }
- &:after {
- content: '';
- position: absolute;
- display: none;
- z-index:2;
- width: 20%;
- height: 20%;
- top: 50%;
- left: 50%;
- background: @dpad-fg;
- border-radius: 50%;
- transform: translate(-50%, -50%);
- transition: all .25s;
- cursor: pointer;
- }
- &:hover:after {
- width: 30%;
- height: 30%;
- }
- a {
- display:block;
- position: absolute;
- -webkit-tap-highlight-color: rgba(255, 255, 255, 0);
- width: 33.3%;
- height: 43%;
- line-height: 40%;
- color: #fff;
- background: @dpad-fg;
- text-align: center;
- &:hover {
- background: @dpad-fg-hover;
- }
- &:before {
- content: '';
- position: absolute;
- width: 0;
- height: 0;
- border-radius: 5px;
- border-style: solid;
- transition: all .25s;
- }
- &:after {
- content: '';
- position: absolute;
- width: 102%;
- height: 78%;
- background: @dpad-bg;
- border-radius: @dpad-radius-in;
- }
- }
- a.left, a.right {
- width: 43%;
- height: 33%;
- &:after {
- width: 78%;
- height: 102%;
- }
- }
-
- a.up {
- top: 0;
- left: 50%;
- transform: translate(-50%, 0);
- border-radius: @dpad-radius @dpad-radius 50% 50%;
- &:hover {
- background: linear-gradient(0deg, @dpad-fg 0%, @dpad-fg-hover 50%);
- }
- &:after {
- left: 0;
- top: 0;
- transform: translate(-100%, 0);
- border-top-left-radius: 50%;
- pointer-events: none;
- }
- &:before {
- top: 40%;
- left: 50%;
- transform: translate(-50%, -50%);
- border-width: 0 @tri-sml-a @tri-sml-b @tri-sml-a;
- border-color: transparent transparent @arrowcolor transparent;
- }
- &:active:before {
- border-bottom-color: #333;
- }
- }
- a.up:hover:before { top: @dpad-arrow-move; }
-
- a.down {
- bottom: 0;
- left: 50%;
- transform: translate(-50%, 0);
- border-radius: 50% 50% @dpad-radius @dpad-radius;
- &:hover {
- background: linear-gradient(180deg, @dpad-fg 0%, @dpad-fg-hover 50%);
- }
- &:after {
- right: 0;
- bottom: 0;
- transform: translate(100%, 0);
- border-bottom-right-radius: 50%;
- pointer-events: none;
- }
- &:before {
- bottom: 40%;
- left: 50%;
- transform: translate(-50%, 50%);
- border-width: @tri-sml-b @tri-sml-a 0px @tri-sml-a;
- border-color: @arrowcolor transparent transparent transparent;
- }
- &:active:before {
- border-top-color: #333;
- }
- }
- a.down:hover:before { bottom: @dpad-arrow-move; }
-
- a.left {
- top: 50%;
- left: 0;
- transform: translate(0, -50%);
- border-radius: @dpad-radius 50% 50% @dpad-radius;
- &:hover {
- background: linear-gradient(-90deg, @dpad-fg 0%, @dpad-fg-hover 50%);
- }
- &:after {
- left: 0;
- bottom: 0;
- transform: translate(0, 100%);
- border-bottom-left-radius: 50%;
- pointer-events: none;
- }
- &:before {
- left: 40%;
- top: 50%;
- transform: translate(-50%, -50%);
- border-width: @tri-sml-a @tri-sml-b @tri-sml-a 0;
- border-color: transparent @arrowcolor transparent transparent;
- }
- &:active:before {
- border-right-color: #333;
- }
- }
- a.left:hover:before { left: @dpad-arrow-move; }
-
- a.right {
- top: 50%;
- right: 0;
- transform: translate(0, -50%);
- border-radius: 50% @dpad-radius @dpad-radius 50%;
- &:hover {
- background: linear-gradient(90deg, @dpad-fg 0%, @dpad-fg-hover 50%);
- }
- &:after {
- right: 0;
- top: 0;
- transform: translate(0, -100%);
- border-top-right-radius: 50%;
- pointer-events: none;
- }
- &:before {
- right: 40%;
- top: 50%;
- transform: translate(50%, -50%);
- border-width: @tri-sml-a 0 @tri-sml-a @tri-sml-b;
- border-color: transparent transparent transparent @arrowcolor;
- }
- &:active:before {
- border-left-color: #333;
- }
- }
- a.right:hover:before { right: @dpad-arrow-move; }
- }
- .d-pad.up a.up:before { border-bottom-color: #333; }
- .d-pad.down a.down:before { border-top-color: #333; }
- .d-pad.left a.left:before { border-right-color: #333; }
- .d-pad.right a.right:before { border-left-color: #333; }
-
- .blue {
- @c: #1843ca;
- @c-h: #143cb9;
- @c-t: #ccc;
- @c-t-a: rgba(255,255,255,1);
- .d-pad {
- &:before, a { background: @c; }
- &:after { display: block; background: @c-t; }
- a:after { border-radius: 10%; }
- a.up:hover { background: linear-gradient(0deg, @c 0%, @c-h 50%); }
- a.right:hover { background: linear-gradient(90deg, @c 0%, @c-h 50%); }
- a.down:hover { background: linear-gradient(180deg, @c 0%, @c-h 50%); }
- a.left:hover { background: linear-gradient(-90deg, @c 0%, @c-h 50%); }
- a.up:before { border-bottom-color: @c-t; }
- a.right:before { border-left-color: @c-t; }
- a.down:before { border-top-color: @c-t; }
- a.left:before { border-right-color: @c-t; }
- a.up:active:before { border-bottom-color: @c-t-a; }
- a.right:active:before { border-left-color: @c-t-a; }
- a.down:active:before { border-top-color: @c-t-a; }
- a.left:active:before { border-right-color: @c-t-a; }
- }
- }
-
- // set direction active state
-
- .d-pad.up a.up:before { border-bottom-color: #333; }
- .d-pad.down a.down:before { border-top-color: #333; }
- .d-pad.left a.left:before { border-right-color: #333; }
- .d-pad.right a.right:before { border-left-color: #333; }
-
- .o-pad.up a.up:after { border-bottom-color: #333; }
- .o-pad.down a.down:after { border-top-color: #333; }
- .o-pad.left a.left:after { border-right-color: #333; }
- .o-pad.right a.right:after { border-left-color: #333; }
\ No newline at end of file
diff --git a/data/www/index.html b/data/www/index.html
index 31959a2d..0ea9e176 100644
--- a/data/www/index.html
+++ b/data/www/index.html
@@ -1,215 +1,13 @@
-
-
-
-
- Mural
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Retract belts
-
Place the belt loops on the homing screws and retract the belts until the motors stall. Don't let the motors stall for too long.
-
-
-
-
-
-
-
-
-
-
-
-
-
Extend belts
-
The belts will extend to their home position. Make sure the belts are unobstructed and the motors do not skip, or the drawing accuracy may be affected
-
-
-
-
-
Pen calibration
-
Insert the pen so it's close to, but not touching the wall and secure it with a bolt. Then, adjust the pen position so the pen is touching the wall
-
-
-
-
-
-
Select SVG Image
-
Use black and white line art SVGs for now
-
![]()
-
-
-
-
-
-
Choose render type
-
-
-
-
-
-
Drawing preview
-
![]()
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Mural is ready!
-
-
-
-
-
Drawing Started
- Mural will not be accessible via your browser while the drawing is in progress. Please refresh the page once the drawing is finished.
-
-
-
-
-
-
-
-
\ No newline at end of file
+
+
+
+ Mural
+
+
+
+
+
+
+