diff --git a/.vite/build/main.js b/.vite/build/main.js index 1cbb0eb..f959cc5 100644 --- a/.vite/build/main.js +++ b/.vite/build/main.js @@ -1,5 +1,5 @@ -"use strict";const w=require("electron"),M=require("path"),P=require("child_process"),T=require("tty"),z=require("util"),F=require("fs"),G=require("net");var _={exports:{}},b={exports:{}},q={exports:{}},$,S;function I(){if(S)return $;S=1;var a=1e3,e=a*60,c=e*60,f=c*24,p=f*365.25;$=function(r,n){n=n||{};var s=typeof r;if(s==="string"&&r.length>0)return g(r);if(s==="number"&&isNaN(r)===!1)return n.long?v(r):h(r);throw new Error("val is not a non-empty string or a valid number. val="+JSON.stringify(r))};function g(r){if(r=String(r),!(r.length>100)){var n=/^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(r);if(n){var s=parseFloat(n[1]),l=(n[2]||"ms").toLowerCase();switch(l){case"years":case"year":case"yrs":case"yr":case"y":return s*p;case"days":case"day":case"d":return s*f;case"hours":case"hour":case"hrs":case"hr":case"h":return s*c;case"minutes":case"minute":case"mins":case"min":case"m":return s*e;case"seconds":case"second":case"secs":case"sec":case"s":return s*a;case"milliseconds":case"millisecond":case"msecs":case"msec":case"ms":return s;default:return}}}}function h(r){return r>=f?Math.round(r/f)+"d":r>=c?Math.round(r/c)+"h":r>=e?Math.round(r/e)+"m":r>=a?Math.round(r/a)+"s":r+"ms"}function v(r){return i(r,f,"day")||i(r,c,"hour")||i(r,e,"minute")||i(r,a,"second")||r+" ms"}function i(r,n,s){if(!(r=31||typeof navigator<"u"&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)}e.formatters.j=function(i){try{return JSON.stringify(i)}catch(r){return"[UnexpectedJSONParseError]: "+r.message}};function f(i){var r=this.useColors;if(i[0]=(r?"%c":"")+this.namespace+(r?" %c":" ")+i[0]+(r?"%c ":" ")+"+"+e.humanize(this.diff),!!r){var n="color: "+this.color;i.splice(1,0,n,"color: inherit");var s=0,l=0;i[0].replace(/%[a-zA-Z%]/g,function(o){o!=="%%"&&(s++,o==="%c"&&(l=s))}),i.splice(l,0,n)}}function p(){return typeof console=="object"&&console.log&&Function.prototype.apply.call(console.log,console,arguments)}function g(i){try{i==null?e.storage.removeItem("debug"):e.storage.debug=i}catch{}}function h(){var i;try{i=e.storage.debug}catch{}return!i&&typeof process<"u"&&"env"in process&&(i=process.env.DEBUG),i}e.enable(h());function v(){try{return window.localStorage}catch{}}}(b,b.exports)),b.exports}var C={exports:{}},U;function Z(){return U||(U=1,function(a,e){var c=T,f=z;e=a.exports=W(),e.init=l,e.log=i,e.formatArgs=v,e.save=r,e.load=n,e.useColors=h,e.colors=[6,2,3,4,5,1],e.inspectOpts=Object.keys(process.env).filter(function(o){return/^debug_/i.test(o)}).reduce(function(o,t){var d=t.substring(6).toLowerCase().replace(/_([a-z])/g,function(m,y){return y.toUpperCase()}),u=process.env[t];return/^(yes|on|true|enabled)$/i.test(u)?u=!0:/^(no|off|false|disabled)$/i.test(u)?u=!1:u==="null"?u=null:u=Number(u),o[d]=u,o},{});var p=parseInt(process.env.DEBUG_FD,10)||2;p!==1&&p!==2&&f.deprecate(function(){},"except for stderr(2) and stdout(1), any other usage of DEBUG_FD is deprecated. Override debug.log if you want to use a different log function (https://git.io/debug_fd)")();var g=p===1?process.stdout:p===2?process.stderr:s(p);function h(){return"colors"in e.inspectOpts?!!e.inspectOpts.colors:c.isatty(p)}e.formatters.o=function(o){return this.inspectOpts.colors=this.useColors,f.inspect(o,this.inspectOpts).split(` -`).map(function(t){return t.trim()}).join(" ")},e.formatters.O=function(o){return this.inspectOpts.colors=this.useColors,f.inspect(o,this.inspectOpts)};function v(o){var t=this.namespace,d=this.useColors;if(d){var u=this.color,m=" \x1B[3"+u+";1m"+t+" \x1B[0m";o[0]=m+o[0].split(` +"use strict";const h=require("electron"),P=require("path"),T=require("child_process"),z=require("tty"),G=require("util"),I=require("fs"),J=require("net");function Z(s){return s&&s.__esModule&&Object.prototype.hasOwnProperty.call(s,"default")?s.default:s}var O={exports:{}},b={exports:{}},q={exports:{}},_,A;function H(){if(A)return _;A=1;var s=1e3,e=s*60,u=e*60,c=u*24,f=c*365.25;_=function(r,n){n=n||{};var o=typeof r;if(o==="string"&&r.length>0)return v(r);if(o==="number"&&isNaN(r)===!1)return n.long?m(r):g(r);throw new Error("val is not a non-empty string or a valid number. val="+JSON.stringify(r))};function v(r){if(r=String(r),!(r.length>100)){var n=/^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(r);if(n){var o=parseFloat(n[1]),d=(n[2]||"ms").toLowerCase();switch(d){case"years":case"year":case"yrs":case"yr":case"y":return o*f;case"days":case"day":case"d":return o*c;case"hours":case"hour":case"hrs":case"hr":case"h":return o*u;case"minutes":case"minute":case"mins":case"min":case"m":return o*e;case"seconds":case"second":case"secs":case"sec":case"s":return o*s;case"milliseconds":case"millisecond":case"msecs":case"msec":case"ms":return o;default:return}}}}function g(r){return r>=c?Math.round(r/c)+"d":r>=u?Math.round(r/u)+"h":r>=e?Math.round(r/e)+"m":r>=s?Math.round(r/s)+"s":r+"ms"}function m(r){return a(r,c,"day")||a(r,u,"hour")||a(r,e,"minute")||a(r,s,"second")||r+" ms"}function a(r,n,o){if(!(r=31||typeof navigator<"u"&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)}e.formatters.j=function(a){try{return JSON.stringify(a)}catch(r){return"[UnexpectedJSONParseError]: "+r.message}};function c(a){var r=this.useColors;if(a[0]=(r?"%c":"")+this.namespace+(r?" %c":" ")+a[0]+(r?"%c ":" ")+"+"+e.humanize(this.diff),!!r){var n="color: "+this.color;a.splice(1,0,n,"color: inherit");var o=0,d=0;a[0].replace(/%[a-zA-Z%]/g,function(i){i!=="%%"&&(o++,i==="%c"&&(d=o))}),a.splice(d,0,n)}}function f(){return typeof console=="object"&&console.log&&Function.prototype.apply.call(console.log,console,arguments)}function v(a){try{a==null?e.storage.removeItem("debug"):e.storage.debug=a}catch{}}function g(){var a;try{a=e.storage.debug}catch{}return!a&&typeof process<"u"&&"env"in process&&(a=process.env.DEBUG),a}e.enable(g());function m(){try{return window.localStorage}catch{}}}(b,b.exports)),b.exports}var C={exports:{}},U;function Y(){return U||(U=1,function(s,e){var u=z,c=G;e=s.exports=R(),e.init=d,e.log=a,e.formatArgs=m,e.save=r,e.load=n,e.useColors=g,e.colors=[6,2,3,4,5,1],e.inspectOpts=Object.keys(process.env).filter(function(i){return/^debug_/i.test(i)}).reduce(function(i,t){var p=t.substring(6).toLowerCase().replace(/_([a-z])/g,function(w,y){return y.toUpperCase()}),l=process.env[t];return/^(yes|on|true|enabled)$/i.test(l)?l=!0:/^(no|off|false|disabled)$/i.test(l)?l=!1:l==="null"?l=null:l=Number(l),i[p]=l,i},{});var f=parseInt(process.env.DEBUG_FD,10)||2;f!==1&&f!==2&&c.deprecate(function(){},"except for stderr(2) and stdout(1), any other usage of DEBUG_FD is deprecated. Override debug.log if you want to use a different log function (https://git.io/debug_fd)")();var v=f===1?process.stdout:f===2?process.stderr:o(f);function g(){return"colors"in e.inspectOpts?!!e.inspectOpts.colors:u.isatty(f)}e.formatters.o=function(i){return this.inspectOpts.colors=this.useColors,c.inspect(i,this.inspectOpts).split(` +`).map(function(t){return t.trim()}).join(" ")},e.formatters.O=function(i){return this.inspectOpts.colors=this.useColors,c.inspect(i,this.inspectOpts)};function m(i){var t=this.namespace,p=this.useColors;if(p){var l=this.color,w=" \x1B[3"+l+";1m"+t+" \x1B[0m";i[0]=w+i[0].split(` `).join(` -`+m),o.push("\x1B[3"+u+"m+"+e.humanize(this.diff)+"\x1B[0m")}else o[0]=new Date().toUTCString()+" "+t+" "+o[0]}function i(){return g.write(f.format.apply(f,arguments)+` -`)}function r(o){o==null?delete process.env.DEBUG:process.env.DEBUG=o}function n(){return process.env.DEBUG}function s(o){var t,d=process.binding("tty_wrap");switch(d.guessHandleType(o)){case"TTY":t=new c.WriteStream(o),t._type="tty",t._handle&&t._handle.unref&&t._handle.unref();break;case"FILE":var u=F;t=new u.SyncWriteStream(o,{autoClose:!1}),t._type="fs";break;case"PIPE":case"TCP":var m=G;t=new m.Socket({fd:o,readable:!1,writable:!0}),t.readable=!1,t.read=null,t._type="pipe",t._handle&&t._handle.unref&&t._handle.unref();break;default:throw new Error("Implement me. Unknown stream file type!")}return t.fd=o,t._isStdio=!0,t}function l(o){o.inspectOpts={};for(var t=Object.keys(e.inspectOpts),d=0;d{const a=new w.BrowserWindow({width:800,height:600,webPreferences:{preload:M.join(__dirname,"preload.js")}});a.loadURL("http://localhost:5173"),a.webContents.openDevTools()};w.app.on("ready",R);w.app.on("window-all-closed",()=>{process.platform!=="darwin"&&w.app.quit()});w.app.on("activate",()=>{w.BrowserWindow.getAllWindows().length===0&&R()}); +`+w),i.push("\x1B[3"+l+"m+"+e.humanize(this.diff)+"\x1B[0m")}else i[0]=new Date().toUTCString()+" "+t+" "+i[0]}function a(){return v.write(c.format.apply(c,arguments)+` +`)}function r(i){i==null?delete process.env.DEBUG:process.env.DEBUG=i}function n(){return process.env.DEBUG}function o(i){var t,p=process.binding("tty_wrap");switch(p.guessHandleType(i)){case"TTY":t=new u.WriteStream(i),t._type="tty",t._handle&&t._handle.unref&&t._handle.unref();break;case"FILE":var l=I;t=new l.SyncWriteStream(i,{autoClose:!1}),t._type="fs";break;case"PIPE":case"TCP":var w=J;t=new w.Socket({fd:i,readable:!1,writable:!0}),t.readable=!1,t.read=null,t._type="pipe",t._handle&&t._handle.unref&&t._handle.unref();break;default:throw new Error("Implement me. Unknown stream file type!")}return t.fd=i,t._isStdio=!0,t}function d(i){i.inspectOpts={};for(var t=Object.keys(e.inspectOpts),p=0;p{c({pid:s,tid:e,vid:u,value:0})})},set(s,e,u,c){return new Promise((f,v)=>{f({pid:s,tid:e,vid:u,value:c})})},onValueReceived(s){}};ee&&h.app.quit();const N=()=>{const s=new h.BrowserWindow({width:1100,height:912,webPreferences:{preload:P.join(__dirname,"preload.js")}});return s.loadURL("http://localhost:5173"),s.webContents.openDevTools(),s};h.app.whenReady().then(()=>{h.ipcMain.handle("nanodevices:list",E.list),h.ipcMain.handle("nanodevices:connect",E.connect),h.ipcMain.handle("nanodevices:disconnect",E.disconnect),h.ipcMain.handle("nano:get",B.get),h.ipcMain.handle("nano:set",B.set),N()});h.app.on("window-all-closed",()=>{process.platform!=="darwin"&&h.app.quit()});h.app.on("activate",()=>{h.BrowserWindow.getAllWindows().length===0&&N()}); diff --git a/.vite/build/preload.js b/.vite/build/preload.js index 3918c74..5be10d7 100644 --- a/.vite/build/preload.js +++ b/.vite/build/preload.js @@ -1 +1 @@ -"use strict"; +"use strict";const{contextBridge:i,ipcRenderer:o}=require("electron");i.exposeInMainWorld("nanodevices",{list(){o.invoke("nanodevices:list")},connect(e){o.invoke("nanodevices:connect",e)},disconnect(){o.invoke("nanodevices:disconnect")},on_device_attached(e){o.on("nanodevice-attached",(c,n)=>e(n))},on_device_detached(e){o.on("nanodevice-detached",(c,n)=>e(n))}});i.exposeInMainWorld("nanodevice",{get_value(e,c,n){o.invoke("nano:get",e,c,n)},set_value(e,c,n,t){o.invoke("nano:set",e,c,n,t)},on_value(e){o.on("nano-onvalue",(c,n)=>e(n))}}); diff --git a/src/backend/nano.js b/src/backend/nano.js new file mode 100644 index 0000000..a7dc0a4 --- /dev/null +++ b/src/backend/nano.js @@ -0,0 +1,19 @@ + +const nano = { + get(pid, tid, vid) { + return new Promise((resolve, reject) => { + resolve({ pid: pid, tid: tid, vid: vid, value: 0.0 }); + }); + }, + + set(pid, tid, vid, value) { + return new Promise((resolve, reject) => { + resolve({ pid: pid, tid: tid, vid: vid, value: value }); + }); + }, + + onValueReceived(listener) { + } +}; + +export default nano; \ No newline at end of file diff --git a/src/backend/nanodevices.js b/src/backend/nanodevices.js new file mode 100644 index 0000000..f1266a2 --- /dev/null +++ b/src/backend/nanodevices.js @@ -0,0 +1,23 @@ + + +const nanodevices = { + list() { + return []; + }, + + async connect(devicename) { + return true; + }, + + async disconnect() { + return true; + }, + + onAttach(listener) { + }, + + onDetach(listener) { + } +}; + +export default nanodevices; diff --git a/src/main.js b/src/main.js index 56ed0fb..5e12109 100644 --- a/src/main.js +++ b/src/main.js @@ -1,17 +1,21 @@ import { app, BrowserWindow } from 'electron'; import path from 'path'; -import 'electron-squirrel-startup'; +import ess from 'electron-squirrel-startup'; +import { ipcMain } from 'electron'; +import nanodevices from './backend/nanodevices.js'; +import nano from './backend/nano.js'; -// TODO Handle creating/removing shortcuts on Windows when installing/uninstalling. -//if (require('electron-squirrel-startup')) { -// app.quit(); -//} + +// Handle creating/removing shortcuts on Windows when installing/uninstalling. +if (ess) { + app.quit(); +} const createWindow = () => { // Create the browser window. const mainWindow = new BrowserWindow({ - width: 800, - height: 600, + width: 1100, + height: 912, webPreferences: { preload: path.join(__dirname, 'preload.js'), }, @@ -26,12 +30,33 @@ const createWindow = () => { // Open the DevTools. mainWindow.webContents.openDevTools(); + + return mainWindow; }; // This method will be called when Electron has finished // initialization and is ready to create browser windows. // Some APIs can only be used after this event occurs. -app.on('ready', createWindow); +app.whenReady().then(() => { + ipcMain.handle('nanodevices:list', nanodevices.list); + ipcMain.handle('nanodevices:connect', nanodevices.connect); + ipcMain.handle('nanodevices:disconnect', nanodevices.disconnect); + ipcMain.handle('nano:get', nano.get); + ipcMain.handle('nano:set', nano.set); + const mainWindow = createWindow(); + nanodevices.onAttach((device) => { + console.log("Attached device", device); + mainWindow.webContents.send('nanodevice-attached', device); + }); + nanodevices.onDetach((device) => { + console.log("Detached device", device); + mainWindow.webContents.send('nanodevice-detached', device); + }); + nano.onValueReceived((value) => { + console.log("Value received", value); + mainWindow.webContents.send('nano-onvalue', value); + }); +}); // Quit when all windows are closed, except on macOS. There, it's common // for applications and their menu bar to stay active until the user quits diff --git a/src/preload.js b/src/preload.js index 5e9d369..a1566f8 100644 --- a/src/preload.js +++ b/src/preload.js @@ -1,2 +1,22 @@ // See the Electron documentation for details on how to use preload scripts: // https://www.electronjs.org/docs/latest/tutorial/process-model#preload-scripts + +const { contextBridge, ipcRenderer } = require('electron') + + +// expose an API to choose available devices +contextBridge.exposeInMainWorld('nanodevices', { + list() { ipcRenderer.invoke('nanodevices:list'); }, + connect(devicename) { ipcRenderer.invoke('nanodevices:connect', devicename); }, + disconnect() { ipcRenderer.invoke('nanodevices:disconnect'); }, + on_device_attached(listener) { ipcRenderer.on('nanodevice-attached', (_event, value) => listener(value)); }, + on_device_detached(listener) { ipcRenderer.on('nanodevice-detached', (_event, value) => listener(value)); }, +}); + + +// expose an API to communicate with the nano device +contextBridge.exposeInMainWorld('nanodevice', { + get_value(pid, tid, vid){ ipcRenderer.invoke('nano:get', pid, tid, vid); }, + set_value(pid, tid, vid, value){ ipcRenderer.invoke('nano:set', pid, tid, vid, value); }, + on_value(listener){ ipcRenderer.on('nano-onvalue', (_event, value) => listener(value)); } +});