diff --git a/.dist/icon.png b/.dist/icon.png
new file mode 100644
index 0000000..be5e131
Binary files /dev/null and b/.dist/icon.png differ
diff --git a/.dist/module.json b/.dist/module.json
new file mode 100644
index 0000000..57521bc
--- /dev/null
+++ b/.dist/module.json
@@ -0,0 +1,65 @@
+{
+ "name": "GetiyoSimpleVisual",
+ "type": "normal",
+ "author": "marco",
+ "category": "AIFx",
+ "default_reference_properties": {
+ "amplitude": {
+ "type": "slider",
+ "title": "Amplitude",
+ "description": "Controls the height of the sine wave",
+ "value": 50,
+ "min": 5,
+ "max": 100,
+ "step": 1
+ },
+ "frequency": {
+ "type": "slider",
+ "title": "Frequency",
+ "description": "Controls how many waves are displayed",
+ "value": 1,
+ "min": 0.1,
+ "max": 5,
+ "step": 0.1
+ },
+ "speed": {
+ "type": "slider",
+ "title": "Speed",
+ "description": "Controls how fast the wave animates",
+ "value": 1,
+ "min": 0,
+ "max": 5,
+ "step": 0.1
+ },
+ "color": {
+ "type": "color",
+ "title": "Color",
+ "description": "The color of the sine wave",
+ "value": "#4287f5"
+ },
+ "lineWidth": {
+ "type": "slider",
+ "title": "Line Width",
+ "description": "Thickness of the sine wave line",
+ "value": 3,
+ "min": 1,
+ "max": 10,
+ "step": 1
+ }
+ },
+ "default_module_properties": {},
+ "triggers": {},
+ "conditions": {
+ "server": {},
+ "client": {}
+ },
+ "default_size": {
+ "width": 300,
+ "height": 300
+ },
+ "default_location": {
+ "x": 100,
+ "y": 100
+ },
+ "build": "0001"
+}
\ No newline at end of file
diff --git a/.dist/server.js b/.dist/server.js
new file mode 100644
index 0000000..8a200fe
--- /dev/null
+++ b/.dist/server.js
@@ -0,0 +1 @@
+module.exports = (api) => {api.onClientConnects(function(n){console.log("Client connected: "+n.getClientID())}),api.onClientDisconnects(function(n){console.log("Client disconnected: "+n.getClientID())}),api.onNewClient(function(n){console.log("Client connected via legacy handler: "+n.getClientID())});};
\ No newline at end of file
diff --git a/.dist/user.html b/.dist/user.html
new file mode 100644
index 0000000..e3ec870
--- /dev/null
+++ b/.dist/user.html
@@ -0,0 +1 @@
+
Sine Wave Visualization
\ No newline at end of file
diff --git a/.dist/user.js b/.dist/user.js
new file mode 100644
index 0000000..0624442
--- /dev/null
+++ b/.dist/user.js
@@ -0,0 +1,95 @@
+(()=>{var api = new ModuleApi();
+// Configuration with default values
+var config = {
+ amplitude: 50,
+ frequency: 1,
+ speed: 1,
+ color: '#4287f5',
+ lineWidth: 3
+};
+// Get DOM elements
+var container = api.dom();
+var canvas = container.querySelector('#sineCanvas');
+var ctx = canvas.getContext('2d');
+// Animation variables
+var animationId;
+var startTime = Date.now();
+// Initialize the canvas
+function initCanvas() {
+ var rect = container.getBoundingClientRect();
+ canvas.width = rect.width;
+ canvas.height = rect.height;
+}
+// Draw the sine wave
+function drawSineWave() {
+ if (!ctx)
+ return;
+ // Clear canvas
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
+ // Set line style
+ ctx.strokeStyle = config.color;
+ ctx.lineWidth = config.lineWidth;
+ ctx.lineCap = 'round';
+ ctx.lineJoin = 'round';
+ // Draw the wave
+ var now = Date.now();
+ var elapsed = (now - startTime) / 1000;
+ var timeOffset = elapsed * config.speed;
+ ctx.beginPath();
+ // Start from the left side of the canvas
+ var centerY = canvas.height / 2;
+ for (var x = 0; x <= canvas.width; x++) {
+ // Calculate the y position for each x point along the sine wave
+ var xValue = (x / canvas.width) * Math.PI * 2 * config.frequency;
+ var sineValue = Math.sin(xValue + timeOffset);
+ var y = centerY + sineValue * config.amplitude;
+ if (x === 0) {
+ ctx.moveTo(x, y);
+ }
+ else {
+ ctx.lineTo(x, y);
+ }
+ }
+ ctx.stroke();
+ // Request the next frame
+ animationId = requestAnimationFrame(drawSineWave);
+}
+// Start the animation
+function startAnimation() {
+ if (animationId) {
+ cancelAnimationFrame(animationId);
+ }
+ startTime = Date.now();
+ animationId = requestAnimationFrame(drawSineWave);
+}
+// Handle window resize
+function handleResize() {
+ initCanvas();
+ drawSineWave();
+}
+// Setup property listeners
+api.onPropertyUpdate('amplitude', function (value) {
+ config.amplitude = value;
+});
+api.onPropertyUpdate('frequency', function (value) {
+ config.frequency = value;
+});
+api.onPropertyUpdate('speed', function (value) {
+ config.speed = value;
+});
+api.onPropertyUpdate('color', function (value) {
+ config.color = value;
+});
+api.onPropertyUpdate('lineWidth', function (value) {
+ config.lineWidth = value;
+});
+// Handle resize events
+api.onResize(function () {
+ handleResize();
+});
+// Initialize
+window.addEventListener('load', function () {
+ initCanvas();
+ startAnimation();
+});
+})();
\ No newline at end of file
diff --git a/module.json b/module.json
index 7942ebe..ab25231 100644
--- a/module.json
+++ b/module.json
@@ -1,21 +1,65 @@
{
- "name": "GetiyoSimpleVisual",
- "type": "normal",
- "author": "marco",
- "category": "AIFx",
- "default_reference_properties": {},
- "default_module_properties": {},
- "triggers": {},
- "conditions": {
- "server": {},
- "client": {}
- },
- "default_size": {
- "width": 300,
- "height": 300
- },
- "default_location": {
- "x": 100,
- "y": 100
- }
-}
\ No newline at end of file
+ "name": "GetiyoSimpleVisual",
+ "type": "normal",
+ "author": "marco",
+ "category": "AIFx",
+ "default_reference_properties": {
+ "amplitude": {
+ "type": "slider",
+ "title": "Amplitude",
+ "description": "Controls the height of the sine wave",
+ "value": 50,
+ "min": 5,
+ "max": 100,
+ "step": 1
+ },
+ "frequency": {
+ "type": "slider",
+ "title": "Frequency",
+ "description": "Controls how many waves are displayed",
+ "value": 1,
+ "min": 0.1,
+ "max": 5,
+ "step": 0.1
+ },
+ "speed": {
+ "type": "slider",
+ "title": "Speed",
+ "description": "Controls how fast the wave animates",
+ "value": 1,
+ "min": 0,
+ "max": 5,
+ "step": 0.1
+ },
+ "color": {
+ "type": "color",
+ "title": "Color",
+ "description": "The color of the sine wave",
+ "value": "#4287f5"
+ },
+ "lineWidth": {
+ "type": "slider",
+ "title": "Line Width",
+ "description": "Thickness of the sine wave line",
+ "value": 3,
+ "min": 1,
+ "max": 10,
+ "step": 1
+ }
+ },
+ "default_module_properties": {},
+ "triggers": {},
+ "conditions": {
+ "server": {},
+ "client": {}
+ },
+ "default_size": {
+ "width": 300,
+ "height": 300
+ },
+ "default_location": {
+ "x": 100,
+ "y": 100
+ },
+ "build": "0001"
+}
diff --git a/server/server.ts b/server/server.ts
index f1514ae..52daec5 100644
--- a/server/server.ts
+++ b/server/server.ts
@@ -1,2 +1,17 @@
declare const api: ModuleServerApi;
-api.onNewClient((client) => {});
+
+// Handle new client connections
+api.onClientConnects((client) => {
+ console.log(`Client connected: ${client.getClientID()}`);
+});
+
+// Handle client disconnections
+api.onClientDisconnects((client) => {
+ console.log(`Client disconnected: ${client.getClientID()}`);
+});
+
+// For backward compatibility
+api.onNewClient((client) => {
+ // This is the older API but kept for backward compatibility
+ console.log(`Client connected via legacy handler: ${client.getClientID()}`);
+});
diff --git a/user/index.html b/user/index.html
index e69de29..102c93f 100644
--- a/user/index.html
+++ b/user/index.html
@@ -0,0 +1,12 @@
+
+
+
+
+ Sine Wave Visualization
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/user/scss/layout.scss b/user/scss/layout.scss
index e69de29..eef8733 100644
--- a/user/scss/layout.scss
+++ b/user/scss/layout.scss
@@ -0,0 +1,13 @@
+.sine-container {
+ width: 100%;
+ height: 100%;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+
+ #sineCanvas {
+ width: 100%;
+ height: 100%;
+ background: transparent;
+ }
+}
\ No newline at end of file
diff --git a/user/ts/user.ts b/user/ts/user.ts
index 8940dd6..8486479 100644
--- a/user/ts/user.ts
+++ b/user/ts/user.ts
@@ -1 +1,115 @@
const api: ModuleClientApi = new ModuleApi();
+
+// Configuration with default values
+const config = {
+ amplitude: 50,
+ frequency: 1,
+ speed: 1,
+ color: '#4287f5',
+ lineWidth: 3
+};
+
+// Get DOM elements
+const container = api.dom();
+const canvas = container.querySelector('#sineCanvas') as HTMLCanvasElement;
+const ctx = canvas.getContext('2d');
+
+// Animation variables
+let animationId: number;
+let startTime = Date.now();
+
+// Initialize the canvas
+function initCanvas() {
+ const rect = container.getBoundingClientRect();
+ canvas.width = rect.width;
+ canvas.height = rect.height;
+}
+
+// Draw the sine wave
+function drawSineWave() {
+ if (!ctx) return;
+
+ // Clear canvas
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
+
+ // Set line style
+ ctx.strokeStyle = config.color;
+ ctx.lineWidth = config.lineWidth;
+ ctx.lineCap = 'round';
+ ctx.lineJoin = 'round';
+
+ // Draw the wave
+ const now = Date.now();
+ const elapsed = (now - startTime) / 1000;
+ const timeOffset = elapsed * config.speed;
+
+ ctx.beginPath();
+
+ // Start from the left side of the canvas
+ const centerY = canvas.height / 2;
+
+ for (let x = 0; x <= canvas.width; x++) {
+ // Calculate the y position for each x point along the sine wave
+ const xValue = x / canvas.width * Math.PI * 2 * config.frequency;
+ const sineValue = Math.sin(xValue + timeOffset);
+ const y = centerY + sineValue * config.amplitude;
+
+ if (x === 0) {
+ ctx.moveTo(x, y);
+ } else {
+ ctx.lineTo(x, y);
+ }
+ }
+
+ ctx.stroke();
+
+ // Request the next frame
+ animationId = requestAnimationFrame(drawSineWave);
+}
+
+// Start the animation
+function startAnimation() {
+ if (animationId) {
+ cancelAnimationFrame(animationId);
+ }
+ startTime = Date.now();
+ animationId = requestAnimationFrame(drawSineWave);
+}
+
+// Handle window resize
+function handleResize() {
+ initCanvas();
+ drawSineWave();
+}
+
+// Setup property listeners
+api.onPropertyUpdate('amplitude', (value) => {
+ config.amplitude = value;
+});
+
+api.onPropertyUpdate('frequency', (value) => {
+ config.frequency = value;
+});
+
+api.onPropertyUpdate('speed', (value) => {
+ config.speed = value;
+});
+
+api.onPropertyUpdate('color', (value) => {
+ config.color = value;
+});
+
+api.onPropertyUpdate('lineWidth', (value) => {
+ config.lineWidth = value;
+});
+
+// Handle resize events
+api.onResize(() => {
+ handleResize();
+});
+
+// Initialize
+window.addEventListener('load', () => {
+ initCanvas();
+ startAnimation();
+});