aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEddy Pedroni <epedroni@pm.me>2025-02-21 06:55:30 +0100
committerEddy Pedroni <epedroni@pm.me>2025-02-21 06:55:30 +0100
commit2404f7b5507393bf2f8dcb60ba6886f3cda799aa (patch)
tree8a8f8f070665efe70902befa334a61c59542b7bf
parent655f5b87c43f4ac5cfaef6be482d652c532edc23 (diff)
Add wireframe of web interface, mock implementation in nicegui
-rw-r--r--doc/diagram.drawio210
-rw-r--r--requirements.txt1
-rw-r--r--web-project/pyproject.toml24
-rw-r--r--web-project/src/solo_tool_web.py49
4 files changed, 216 insertions, 68 deletions
diff --git a/doc/diagram.drawio b/doc/diagram.drawio
index f900292..13123d6 100644
--- a/doc/diagram.drawio
+++ b/doc/diagram.drawio
@@ -1,6 +1,6 @@
-<mxfile host="Electron" modified="2024-11-10T11:22:07.508Z" agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/22.1.2 Chrome/114.0.5735.289 Electron/25.9.4 Safari/537.36" etag="iuxE9_e737GxBbJf21Ic" version="22.1.2" type="device" pages="3">
+<mxfile host="Electron" modified="2025-02-20T18:01:24.888Z" agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/22.1.2 Chrome/114.0.5735.289 Electron/25.9.4 Safari/537.36" etag="rIT3cVqIH2baaT9wWlVp" version="22.1.2" type="device" pages="4">
<diagram id="g-wcGVps3MkI6_XAwNEs" name="Core">
- <mxGraphModel dx="1561" dy="946" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1169" pageHeight="827" math="0" shadow="0">
+ <mxGraphModel dx="2840" dy="1751" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1169" pageHeight="827" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
@@ -216,7 +216,7 @@
</mxGraphModel>
</diagram>
<diagram id="yK3rgzEW7m2RTtpwjvJ6" name="MIDI">
- <mxGraphModel dx="2015" dy="395" grid="0" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1169" pageHeight="827" math="0" shadow="0">
+ <mxGraphModel dx="2731" dy="963" grid="0" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1169" pageHeight="827" math="0" shadow="0">
<root>
<mxCell id="OKDEixDBbmxQMGRGU1jO-0" />
<mxCell id="OKDEixDBbmxQMGRGU1jO-1" parent="OKDEixDBbmxQMGRGU1jO-0" />
@@ -369,201 +369,275 @@
</mxGraphModel>
</diagram>
<diagram id="PyNSc7ezSt42GBdjTBvd" name="Launchpad">
- <mxGraphModel dx="1561" dy="946" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
+ <mxGraphModel dx="1562" dy="947" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1169" pageHeight="827" math="0" shadow="0">
<root>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-0" />
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-1" parent="ZtjfeE3uwfRsFhnWfLYL-0" />
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-39" value="0&lt;br&gt;volume&lt;br&gt;50%" style="rounded=1;whiteSpace=wrap;html=1;container=0;fillColor=#d5e8d4;strokeColor=#82b366;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="40" y="80" width="80" height="80" as="geometry" />
+ <mxGeometry x="40" y="40" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-40" value="16&lt;br&gt;speed&lt;br&gt;50%" style="rounded=1;whiteSpace=wrap;html=1;container=0;fillColor=#ffe6cc;strokeColor=#d79b00;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="40" y="167" width="80" height="80" as="geometry" />
+ <mxGeometry x="40" y="127" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-41" value="32" style="rounded=1;whiteSpace=wrap;html=1;container=0;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="40" y="255" width="80" height="80" as="geometry" />
+ <mxGeometry x="40" y="215" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-42" value="48&lt;br&gt;previous&lt;br&gt;song" style="rounded=1;whiteSpace=wrap;html=1;container=0;fillColor=#f8cecc;strokeColor=#b85450;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="40" y="342" width="80" height="80" as="geometry" />
+ <mxGeometry x="40" y="302" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-43" value="64" style="rounded=1;whiteSpace=wrap;html=1;container=0;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="40" y="429" width="80" height="80" as="geometry" />
+ <mxGeometry x="40" y="389" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-44" value="80" style="rounded=1;whiteSpace=wrap;html=1;container=0;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="40" y="516" width="80" height="80" as="geometry" />
+ <mxGeometry x="40" y="476" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-45" value="96&lt;br&gt;stop" style="rounded=1;whiteSpace=wrap;html=1;container=0;fillColor=#f8cecc;strokeColor=#b85450;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="40" y="604" width="80" height="80" as="geometry" />
+ <mxGeometry x="40" y="564" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-46" value="112&lt;br&gt;play/&lt;br&gt;pause" style="rounded=1;whiteSpace=wrap;html=1;container=0;fillColor=#ffe6cc;strokeColor=#d79b00;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="40" y="691" width="80" height="80" as="geometry" />
+ <mxGeometry x="40" y="651" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-84" value="1&lt;br&gt;volume&lt;br&gt;60%" style="rounded=1;whiteSpace=wrap;html=1;container=0;fillColor=#d5e8d4;strokeColor=#82b366;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="130" y="80" width="80" height="80" as="geometry" />
+ <mxGeometry x="130" y="40" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-85" value="17&lt;br&gt;speed&lt;br&gt;60%" style="rounded=1;whiteSpace=wrap;html=1;container=0;fillColor=#ffe6cc;strokeColor=#d79b00;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="130" y="167" width="80" height="80" as="geometry" />
+ <mxGeometry x="130" y="127" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-86" value="33" style="rounded=1;whiteSpace=wrap;html=1;container=0;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="130" y="255" width="80" height="80" as="geometry" />
+ <mxGeometry x="130" y="215" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-87" value="49&lt;br&gt;-25%" style="rounded=1;whiteSpace=wrap;html=1;container=0;fillColor=#f8cecc;strokeColor=#b85450;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="130" y="342" width="80" height="80" as="geometry" />
+ <mxGeometry x="130" y="302" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-88" value="65" style="rounded=1;whiteSpace=wrap;html=1;container=0;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="130" y="429" width="80" height="80" as="geometry" />
+ <mxGeometry x="130" y="389" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-89" value="81" style="rounded=1;whiteSpace=wrap;html=1;container=0;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="130" y="516" width="80" height="80" as="geometry" />
+ <mxGeometry x="130" y="476" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-90" value="97" style="rounded=1;whiteSpace=wrap;html=1;container=0;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="130" y="604" width="80" height="80" as="geometry" />
+ <mxGeometry x="130" y="564" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-91" value="113" style="rounded=1;whiteSpace=wrap;html=1;container=0;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="130" y="691" width="80" height="80" as="geometry" />
+ <mxGeometry x="130" y="651" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-93" value="2&lt;br&gt;volume&lt;br&gt;70%" style="rounded=1;whiteSpace=wrap;html=1;container=0;fillColor=#d5e8d4;strokeColor=#82b366;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="220" y="80" width="80" height="80" as="geometry" />
+ <mxGeometry x="220" y="40" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-94" value="18&lt;br&gt;speed&lt;br&gt;70%" style="rounded=1;whiteSpace=wrap;html=1;container=0;fillColor=#ffe6cc;strokeColor=#d79b00;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="220" y="167" width="80" height="80" as="geometry" />
+ <mxGeometry x="220" y="127" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-95" value="34" style="rounded=1;whiteSpace=wrap;html=1;container=0;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="220" y="255" width="80" height="80" as="geometry" />
+ <mxGeometry x="220" y="215" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-96" value="50&lt;br&gt;-5%" style="rounded=1;whiteSpace=wrap;html=1;container=0;fillColor=#f8cecc;strokeColor=#b85450;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="220" y="342" width="80" height="80" as="geometry" />
+ <mxGeometry x="220" y="302" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-97" value="66" style="rounded=1;whiteSpace=wrap;html=1;container=0;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="220" y="429" width="80" height="80" as="geometry" />
+ <mxGeometry x="220" y="389" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-98" value="82" style="rounded=1;whiteSpace=wrap;html=1;container=0;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="220" y="516" width="80" height="80" as="geometry" />
+ <mxGeometry x="220" y="476" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-99" value="98&lt;br&gt;toggle AB" style="rounded=1;whiteSpace=wrap;html=1;container=0;fillColor=#d5e8d4;strokeColor=#82b366;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="220" y="604" width="80" height="80" as="geometry" />
+ <mxGeometry x="220" y="564" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-100" value="114&lt;br&gt;jump to A" style="rounded=1;whiteSpace=wrap;html=1;container=0;fillColor=#ffe6cc;strokeColor=#d79b00;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="220" y="691" width="80" height="80" as="geometry" />
+ <mxGeometry x="220" y="651" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-102" value="3&lt;br&gt;volume&lt;br&gt;80%" style="rounded=1;whiteSpace=wrap;html=1;container=0;fillColor=#d5e8d4;strokeColor=#82b366;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="310" y="80" width="80" height="80" as="geometry" />
+ <mxGeometry x="310" y="40" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-103" value="19&lt;br&gt;speed&lt;br&gt;80%" style="rounded=1;whiteSpace=wrap;html=1;container=0;fillColor=#ffe6cc;strokeColor=#d79b00;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="310" y="167" width="80" height="80" as="geometry" />
+ <mxGeometry x="310" y="127" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-104" value="35" style="rounded=1;whiteSpace=wrap;html=1;container=0;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="310" y="255" width="80" height="80" as="geometry" />
+ <mxGeometry x="310" y="215" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-105" value="51&lt;br&gt;-1%" style="rounded=1;whiteSpace=wrap;html=1;container=0;fillColor=#f8cecc;strokeColor=#b85450;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="310" y="342" width="80" height="80" as="geometry" />
+ <mxGeometry x="310" y="302" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-106" value="67" style="rounded=1;whiteSpace=wrap;html=1;container=0;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="310" y="429" width="80" height="80" as="geometry" />
+ <mxGeometry x="310" y="389" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-107" value="83" style="rounded=1;whiteSpace=wrap;html=1;container=0;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="310" y="516" width="80" height="80" as="geometry" />
+ <mxGeometry x="310" y="476" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-108" value="&lt;div&gt;99&lt;/div&gt;" style="rounded=1;whiteSpace=wrap;html=1;container=0;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="310" y="604" width="80" height="80" as="geometry" />
+ <mxGeometry x="310" y="564" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-109" value="115" style="rounded=1;whiteSpace=wrap;html=1;container=0;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="310" y="691" width="80" height="80" as="geometry" />
+ <mxGeometry x="310" y="651" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-111" value="4&lt;br&gt;volume&lt;br&gt;90%" style="rounded=1;whiteSpace=wrap;html=1;container=0;fillColor=#d5e8d4;strokeColor=#82b366;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="400" y="80" width="80" height="80" as="geometry" />
+ <mxGeometry x="400" y="40" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-112" value="20&lt;br&gt;speed&lt;br&gt;90%" style="rounded=1;whiteSpace=wrap;html=1;container=0;fillColor=#ffe6cc;strokeColor=#d79b00;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="400" y="167" width="80" height="80" as="geometry" />
+ <mxGeometry x="400" y="127" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-113" value="36" style="rounded=1;whiteSpace=wrap;html=1;container=0;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="400" y="255" width="80" height="80" as="geometry" />
+ <mxGeometry x="400" y="215" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-114" value="52&lt;br&gt;+1%" style="rounded=1;whiteSpace=wrap;html=1;container=0;fillColor=#d5e8d4;strokeColor=#82b366;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="400" y="342" width="80" height="80" as="geometry" />
+ <mxGeometry x="400" y="302" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-115" value="68" style="rounded=1;whiteSpace=wrap;html=1;container=0;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="400" y="429" width="80" height="80" as="geometry" />
+ <mxGeometry x="400" y="389" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-116" value="84" style="rounded=1;whiteSpace=wrap;html=1;container=0;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="400" y="516" width="80" height="80" as="geometry" />
+ <mxGeometry x="400" y="476" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-117" value="100" style="rounded=1;whiteSpace=wrap;html=1;container=0;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="400" y="604" width="80" height="80" as="geometry" />
+ <mxGeometry x="400" y="564" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-118" value="116&lt;br&gt;set A" style="rounded=1;whiteSpace=wrap;html=1;container=0;fillColor=#ffe6cc;strokeColor=#d79b00;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="400" y="691" width="80" height="80" as="geometry" />
+ <mxGeometry x="400" y="651" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-120" value="5&lt;br&gt;volume&lt;br&gt;100%" style="rounded=1;whiteSpace=wrap;html=1;container=0;fillColor=#d5e8d4;strokeColor=#82b366;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="490" y="80" width="80" height="80" as="geometry" />
+ <mxGeometry x="490" y="40" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-121" value="21&lt;br&gt;speed&lt;br&gt;100%" style="rounded=1;whiteSpace=wrap;html=1;container=0;fillColor=#ffe6cc;strokeColor=#d79b00;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="490" y="167" width="80" height="80" as="geometry" />
+ <mxGeometry x="490" y="127" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-122" value="37" style="rounded=1;whiteSpace=wrap;html=1;container=0;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="490" y="255" width="80" height="80" as="geometry" />
+ <mxGeometry x="490" y="215" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-123" value="53&lt;br&gt;+5%" style="rounded=1;whiteSpace=wrap;html=1;container=0;fillColor=#d5e8d4;strokeColor=#82b366;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="490" y="342" width="80" height="80" as="geometry" />
+ <mxGeometry x="490" y="302" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-124" value="69" style="rounded=1;whiteSpace=wrap;html=1;container=0;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="490" y="429" width="80" height="80" as="geometry" />
+ <mxGeometry x="490" y="389" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-125" value="85" style="rounded=1;whiteSpace=wrap;html=1;container=0;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="490" y="516" width="80" height="80" as="geometry" />
+ <mxGeometry x="490" y="476" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-126" value="&lt;div&gt;101&lt;/div&gt;" style="rounded=1;whiteSpace=wrap;html=1;container=0;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="490" y="604" width="80" height="80" as="geometry" />
+ <mxGeometry x="490" y="564" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-127" value="117&lt;br&gt;set B" style="rounded=1;whiteSpace=wrap;html=1;container=0;fillColor=#ffe6cc;strokeColor=#d79b00;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="490" y="691" width="80" height="80" as="geometry" />
+ <mxGeometry x="490" y="651" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-129" value="6&lt;br&gt;volume&lt;br&gt;110%" style="rounded=1;whiteSpace=wrap;html=1;container=0;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="580" y="80" width="80" height="80" as="geometry" />
+ <mxGeometry x="580" y="40" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-130" value="22&lt;br&gt;speed&lt;br&gt;110%" style="rounded=1;whiteSpace=wrap;html=1;container=0;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="580" y="167" width="80" height="80" as="geometry" />
+ <mxGeometry x="580" y="127" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-131" value="38" style="rounded=1;whiteSpace=wrap;html=1;container=0;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="580" y="255" width="80" height="80" as="geometry" />
+ <mxGeometry x="580" y="215" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-132" value="54&lt;br&gt;+25%" style="rounded=1;whiteSpace=wrap;html=1;container=0;fillColor=#d5e8d4;strokeColor=#82b366;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="580" y="342" width="80" height="80" as="geometry" />
+ <mxGeometry x="580" y="302" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-133" value="70" style="rounded=1;whiteSpace=wrap;html=1;container=0;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="580" y="429" width="80" height="80" as="geometry" />
+ <mxGeometry x="580" y="389" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-134" value="86" style="rounded=1;whiteSpace=wrap;html=1;container=0;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="580" y="516" width="80" height="80" as="geometry" />
+ <mxGeometry x="580" y="476" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-135" value="102" style="rounded=1;whiteSpace=wrap;html=1;container=0;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="580" y="604" width="80" height="80" as="geometry" />
+ <mxGeometry x="580" y="564" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-136" value="118&lt;br&gt;previous AB" style="rounded=1;whiteSpace=wrap;html=1;container=0;fillColor=#f8cecc;strokeColor=#b85450;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="580" y="691" width="80" height="80" as="geometry" />
+ <mxGeometry x="580" y="651" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-138" value="7&lt;br&gt;volume&lt;br&gt;120%" style="rounded=1;whiteSpace=wrap;html=1;container=0;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="670" y="80" width="80" height="80" as="geometry" />
+ <mxGeometry x="670" y="40" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-139" value="23&lt;br&gt;speed&lt;br&gt;120%" style="rounded=1;whiteSpace=wrap;html=1;container=0;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="670" y="167" width="80" height="80" as="geometry" />
+ <mxGeometry x="670" y="127" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-140" value="39" style="rounded=1;whiteSpace=wrap;html=1;container=0;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="670" y="255" width="80" height="80" as="geometry" />
+ <mxGeometry x="670" y="215" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-141" value="55&lt;br&gt;next song" style="rounded=1;whiteSpace=wrap;html=1;container=0;fillColor=#d5e8d4;strokeColor=#82b366;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="670" y="342" width="80" height="80" as="geometry" />
+ <mxGeometry x="670" y="302" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-142" value="71" style="rounded=1;whiteSpace=wrap;html=1;container=0;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="670" y="429" width="80" height="80" as="geometry" />
+ <mxGeometry x="670" y="389" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-143" value="87" style="rounded=1;whiteSpace=wrap;html=1;container=0;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="670" y="516" width="80" height="80" as="geometry" />
+ <mxGeometry x="670" y="476" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-144" value="103" style="rounded=1;whiteSpace=wrap;html=1;container=0;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="670" y="604" width="80" height="80" as="geometry" />
+ <mxGeometry x="670" y="564" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="ZtjfeE3uwfRsFhnWfLYL-145" value="119&lt;br&gt;next AB" style="rounded=1;whiteSpace=wrap;html=1;container=0;fillColor=#d5e8d4;strokeColor=#82b366;" parent="ZtjfeE3uwfRsFhnWfLYL-1" vertex="1">
- <mxGeometry x="670" y="691" width="80" height="80" as="geometry" />
+ <mxGeometry x="670" y="651" width="80" height="80" as="geometry" />
+ </mxCell>
+ </root>
+ </mxGraphModel>
+ </diagram>
+ <diagram id="R-0UAU87gWX4lK6NCzNs" name="Web wireframe">
+ <mxGraphModel dx="1562" dy="947" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1169" pageHeight="827" math="0" shadow="0">
+ <root>
+ <mxCell id="0" />
+ <mxCell id="1" parent="0" />
+ <mxCell id="0goJ5iq8U8227kam6OUo-1" value="Song list" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+ <mxGeometry x="80" y="80" width="240" height="440" as="geometry" />
+ </mxCell>
+ <mxCell id="0goJ5iq8U8227kam6OUo-2" value="Volume slider" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+ <mxGeometry x="320" y="80" width="440" height="40" as="geometry" />
+ </mxCell>
+ <mxCell id="0goJ5iq8U8227kam6OUo-3" value="Speed slider" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+ <mxGeometry x="360" y="160" width="360" height="40" as="geometry" />
+ </mxCell>
+ <mxCell id="0goJ5iq8U8227kam6OUo-4" value="Speed +5" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+ <mxGeometry x="720" y="160" width="40" height="40" as="geometry" />
+ </mxCell>
+ <mxCell id="0goJ5iq8U8227kam6OUo-5" value="Speed -5" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+ <mxGeometry x="320" y="160" width="40" height="40" as="geometry" />
+ </mxCell>
+ <mxCell id="E9TFIlIWBKXALOEyTYeL-1" value="Seek slider" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+ <mxGeometry x="320" y="240" width="440" height="40" as="geometry" />
+ </mxCell>
+ <mxCell id="E9TFIlIWBKXALOEyTYeL-2" value="Prev song" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+ <mxGeometry x="320" y="320" width="70" height="40" as="geometry" />
+ </mxCell>
+ <mxCell id="e6dzTLVl2QyovQL1D1hT-1" value="Seek&lt;br&gt;-25%" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+ <mxGeometry x="390" y="320" width="50" height="40" as="geometry" />
+ </mxCell>
+ <mxCell id="e6dzTLVl2QyovQL1D1hT-2" value="Seek&lt;br&gt;-5%" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+ <mxGeometry x="440" y="320" width="50" height="40" as="geometry" />
+ </mxCell>
+ <mxCell id="e6dzTLVl2QyovQL1D1hT-3" value="Seek&lt;br&gt;-1%" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+ <mxGeometry x="490" y="320" width="50" height="40" as="geometry" />
+ </mxCell>
+ <mxCell id="e6dzTLVl2QyovQL1D1hT-5" value="Seek&lt;br&gt;+1%" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+ <mxGeometry x="540" y="320" width="50" height="40" as="geometry" />
+ </mxCell>
+ <mxCell id="e6dzTLVl2QyovQL1D1hT-6" value="Seek&lt;br&gt;+5%" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+ <mxGeometry x="590" y="320" width="50" height="40" as="geometry" />
+ </mxCell>
+ <mxCell id="e6dzTLVl2QyovQL1D1hT-9" value="Seek&lt;br&gt;+25%" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+ <mxGeometry x="640" y="320" width="50" height="40" as="geometry" />
+ </mxCell>
+ <mxCell id="e6dzTLVl2QyovQL1D1hT-10" value="Next song" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+ <mxGeometry x="690" y="320" width="70" height="40" as="geometry" />
+ </mxCell>
+ <mxCell id="2VOf0fCjGpZdvwMfuWx9-1" value="Set A" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+ <mxGeometry x="320" y="400" width="120" height="40" as="geometry" />
+ </mxCell>
+ <mxCell id="2VOf0fCjGpZdvwMfuWx9-2" value="Set B" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+ <mxGeometry x="440" y="400" width="120" height="40" as="geometry" />
+ </mxCell>
+ <mxCell id="eBDQebIGrGTMiAxLC66R-1" value="Previous AB" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+ <mxGeometry x="560" y="400" width="100" height="40" as="geometry" />
+ </mxCell>
+ <mxCell id="eBDQebIGrGTMiAxLC66R-2" value="Next AB" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+ <mxGeometry x="660" y="400" width="100" height="40" as="geometry" />
+ </mxCell>
+ <mxCell id="e5je7AeTKV-z7aj2oazw-1" value="Toggle AB" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+ <mxGeometry x="320" y="480" width="80" height="40" as="geometry" />
+ </mxCell>
+ <mxCell id="e5je7AeTKV-z7aj2oazw-2" value="Stop" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+ <mxGeometry x="400" y="480" width="80" height="40" as="geometry" />
+ </mxCell>
+ <mxCell id="e5je7AeTKV-z7aj2oazw-3" value="Start" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+ <mxGeometry x="480" y="480" width="80" height="40" as="geometry" />
+ </mxCell>
+ <mxCell id="e5je7AeTKV-z7aj2oazw-4" value="Jump to A" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+ <mxGeometry x="560" y="480" width="200" height="40" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
diff --git a/requirements.txt b/requirements.txt
index 20ce1da..7c19832 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,4 +1,5 @@
-e solo-tool-project[dev]
-e cli-project[dev]
-e gui-project[dev]
+-e web-project[dev]
diff --git a/web-project/pyproject.toml b/web-project/pyproject.toml
new file mode 100644
index 0000000..440812e
--- /dev/null
+++ b/web-project/pyproject.toml
@@ -0,0 +1,24 @@
+[build-system]
+requires = ["setuptools"]
+build-backend = "setuptools.build_meta"
+
+[project]
+name = "solo_tool_web"
+authors = [
+ { name = "Eddy Pedroni", email = "epedroni@pm.me" },
+]
+description = "A NiceGUI-based web frontend for the solo_tool library"
+requires-python = ">=3.12"
+dependencies = [
+ "nicegui==2.11.1",
+ "solo_tool"
+]
+dynamic = ["version"]
+
+[project.optional-dependencies]
+dev = [
+]
+
+[project.gui-scripts]
+solo-tool-web = "solo_tool_web:main"
+
diff --git a/web-project/src/solo_tool_web.py b/web-project/src/solo_tool_web.py
new file mode 100644
index 0000000..859dba2
--- /dev/null
+++ b/web-project/src/solo_tool_web.py
@@ -0,0 +1,49 @@
+from nicegui import ui
+
+def main():
+ with ui.splitter(value=30) as splitter:
+ splitter.style('width: 100%; height: 100%;')
+ with splitter.before:
+ with ui.list().props('dense separator'):
+ ui.item('Sweet Child o\' Mine')
+ ui.item('Elembivos')
+ ui.item('Tears of the Dragon')
+ ui.item('Victory Song')
+ with splitter.after:
+ with ui.column() as column:
+ column.style('width: 100%;')
+
+ ui.slider(min=0, max=120, value=100)
+
+ with ui.row():
+ ui.button('-5')
+ ui.slider(min=50, max=120, step=5, value=100)
+ ui.button('+5')
+
+ ui.slider(min=0, max=100, value=0)
+
+ with ui.row():
+ ui.button('Prev')
+ ui.button('-25%')
+ ui.button('-5%')
+ ui.button('-1%')
+ ui.button('+1%')
+ ui.button('+5%')
+ ui.button('+25%')
+ ui.button('Next')
+
+ with ui.row():
+ ui.button('Set A')
+ ui.button('Set B')
+ ui.button('Previous AB')
+ ui.button('Next AB')
+
+ with ui.row():
+ ui.button('Toggle AB')
+ ui.button('Stop')
+ ui.button('Start')
+ ui.button('Jump to A')
+ ui.run()
+
+if __name__ in {'__main__', '__mp_main__'}:
+ main()