diff --git a/forge.config.js b/forge.config.js
index 8da903b..6955da8 100644
--- a/forge.config.js
+++ b/forge.config.js
@@ -43,6 +43,10 @@ module.exports = {
name: 'main_window',
config: 'vite.renderer.config.mjs',
},
+ {
+ name: 'loading_window',
+ config: 'vite.loading.config.mjs',
+ }
],
},
},
diff --git a/index.html b/index.html
index c7b268a..d84cbef 100644
--- a/index.html
+++ b/index.html
@@ -1,13 +1,13 @@
-
-
-
-
- ZERO/ONE : Haptic Configuration Tool
-
-
-
-
-
+
+
+
+
+ ZERO/ONE Configuration Suite
+
+
+
+
+
diff --git a/loading.html b/loading.html
new file mode 100644
index 0000000..b351f92
--- /dev/null
+++ b/loading.html
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+ ZERO/ONE Starting...
+
+
+
+
+
LOADING
+
+
+
diff --git a/package-lock.json b/package-lock.json
index 0763d11..02e3556 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -54,7 +54,8 @@
"postcss": "^8.4.33",
"postcss-loader": "^8.0.0",
"prettier": "3.2.4",
- "tailwindcss": "^3.4.1"
+ "tailwindcss": "^3.4.1",
+ "vite-plugin-eslint": "^1.8.1"
}
},
"node_modules/@aashutoshrathi/word-wrap": {
@@ -2707,6 +2708,19 @@
}
}
},
+ "node_modules/@rollup/pluginutils": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz",
+ "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==",
+ "dev": true,
+ "dependencies": {
+ "estree-walker": "^2.0.1",
+ "picomatch": "^2.2.2"
+ },
+ "engines": {
+ "node": ">= 8.0.0"
+ }
+ },
"node_modules/@rollup/rollup-android-arm-eabi": {
"version": "4.9.6",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.9.6.tgz",
@@ -3163,7 +3177,6 @@
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.2.tgz",
"integrity": "sha512-uQDwm1wFHmbBbCZCqAlq6Do9LYwByNZHWzXppSnay9SuwJ+VRbjkbLABer54kcPnMSlG6Fdiy2yaFXm/z9Z5gw==",
"dev": true,
- "peer": true,
"dependencies": {
"@types/estree": "*",
"@types/json-schema": "*"
@@ -3184,8 +3197,7 @@
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
"integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==",
- "dev": true,
- "peer": true
+ "dev": true
},
"node_modules/@types/fs-extra": {
"version": "9.0.13",
@@ -3218,8 +3230,7 @@
"version": "7.0.15",
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
"integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
- "dev": true,
- "peer": true
+ "dev": true
},
"node_modules/@types/keyv": {
"version": "3.1.4",
@@ -10848,6 +10859,36 @@
}
}
},
+ "node_modules/vite-plugin-eslint": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/vite-plugin-eslint/-/vite-plugin-eslint-1.8.1.tgz",
+ "integrity": "sha512-PqdMf3Y2fLO9FsNPmMX+//2BF5SF8nEWspZdgl4kSt7UvHDRHVVfHvxsD7ULYzZrJDGRxR81Nq7TOFgwMnUang==",
+ "dev": true,
+ "dependencies": {
+ "@rollup/pluginutils": "^4.2.1",
+ "@types/eslint": "^8.4.5",
+ "rollup": "^2.77.2"
+ },
+ "peerDependencies": {
+ "eslint": ">=7",
+ "vite": ">=2"
+ }
+ },
+ "node_modules/vite-plugin-eslint/node_modules/rollup": {
+ "version": "2.79.1",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz",
+ "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==",
+ "dev": true,
+ "bin": {
+ "rollup": "dist/bin/rollup"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ }
+ },
"node_modules/vue": {
"version": "3.4.15",
"resolved": "https://registry.npmjs.org/vue/-/vue-3.4.15.tgz",
@@ -13092,6 +13133,16 @@
"@radix-ui/react-compose-refs": "1.0.1"
}
},
+ "@rollup/pluginutils": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz",
+ "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==",
+ "dev": true,
+ "requires": {
+ "estree-walker": "^2.0.1",
+ "picomatch": "^2.2.2"
+ }
+ },
"@rollup/rollup-android-arm-eabi": {
"version": "4.9.6",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.9.6.tgz",
@@ -13388,7 +13439,6 @@
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.2.tgz",
"integrity": "sha512-uQDwm1wFHmbBbCZCqAlq6Do9LYwByNZHWzXppSnay9SuwJ+VRbjkbLABer54kcPnMSlG6Fdiy2yaFXm/z9Z5gw==",
"dev": true,
- "peer": true,
"requires": {
"@types/estree": "*",
"@types/json-schema": "*"
@@ -13409,8 +13459,7 @@
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
"integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==",
- "dev": true,
- "peer": true
+ "dev": true
},
"@types/fs-extra": {
"version": "9.0.13",
@@ -13443,8 +13492,7 @@
"version": "7.0.15",
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
"integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
- "dev": true,
- "peer": true
+ "dev": true
},
"@types/keyv": {
"version": "3.1.4",
@@ -19020,6 +19068,28 @@
"rollup": "^4.2.0"
}
},
+ "vite-plugin-eslint": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/vite-plugin-eslint/-/vite-plugin-eslint-1.8.1.tgz",
+ "integrity": "sha512-PqdMf3Y2fLO9FsNPmMX+//2BF5SF8nEWspZdgl4kSt7UvHDRHVVfHvxsD7ULYzZrJDGRxR81Nq7TOFgwMnUang==",
+ "dev": true,
+ "requires": {
+ "@rollup/pluginutils": "^4.2.1",
+ "@types/eslint": "^8.4.5",
+ "rollup": "^2.77.2"
+ },
+ "dependencies": {
+ "rollup": {
+ "version": "2.79.1",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz",
+ "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==",
+ "dev": true,
+ "requires": {
+ "fsevents": "~2.3.2"
+ }
+ }
+ }
+ },
"vue": {
"version": "3.4.15",
"resolved": "https://registry.npmjs.org/vue/-/vue-3.4.15.tgz",
diff --git a/package.json b/package.json
index 3151b13..57a2489 100644
--- a/package.json
+++ b/package.json
@@ -61,7 +61,8 @@
"postcss": "^8.4.33",
"postcss-loader": "^8.0.0",
"prettier": "3.2.4",
- "tailwindcss": "^3.4.1"
+ "tailwindcss": "^3.4.1",
+ "vite-plugin-eslint": "^1.8.1"
},
"eslintConfig": {
"root": true,
@@ -113,6 +114,12 @@
]
}
]
+ },
+ "globals": {
+ "MAIN_WINDOW_VITE_DEV_SERVER_URL": "readonly",
+ "MAIN_WINDOW_VITE_NAME": "readonly",
+ "LOADING_WINDOW_VITE_DEV_SERVER_URL": "readonly",
+ "LOADING_WINDOW_VITE_NAME": "readonly"
}
},
"prettier": {
diff --git a/src/components/navbar/Navbar.vue b/src/components/navbar/Navbar.vue
index 1ca7659..095a2cc 100644
--- a/src/components/navbar/Navbar.vue
+++ b/src/components/navbar/Navbar.vue
@@ -16,7 +16,7 @@
::
diff --git a/src/main.js b/src/main.js
index bab2f02..7ddce0c 100644
--- a/src/main.js
+++ b/src/main.js
@@ -11,13 +11,16 @@ if (ess) {
app.quit()
}
+const splashTime = 6000
+
const zoomFactor = 1
const width = 1111
const height = 666
-const createWindow = () => {
+const createMainWindow = () => {
// Create the browser window.
const mainWindow = new BrowserWindow({
+ show: false,
width: width,
height: height,
titleBarStyle: 'hidden',
@@ -34,7 +37,6 @@ const createWindow = () => {
devTools: !app.isPackaged,
preload: path.join(__dirname, 'preload.js'),
zoomFactor: zoomFactor,
- enableRemoteModule: true,
},
})
@@ -54,7 +56,7 @@ const createWindow = () => {
// and load the index.html of the app.
if (MAIN_WINDOW_VITE_DEV_SERVER_URL) {
- mainWindow.loadURL(MAIN_WINDOW_VITE_DEV_SERVER_URL)
+ mainWindow.loadURL(`${MAIN_WINDOW_VITE_DEV_SERVER_URL}/index.html`)
} else {
mainWindow.loadFile(path.join(__dirname, `../renderer/${MAIN_WINDOW_VITE_NAME}/index.html`))
}
@@ -62,6 +64,46 @@ const createWindow = () => {
return mainWindow
}
+const createLoadingWindow = (mainWindow) => {
+ const loadingWindow = new BrowserWindow({
+ show: false,
+ width: 400,
+ height: 600,
+ transparent: true,
+ frame: false,
+ center: true,
+ webPreferences: {
+ devTools: !app.isPackaged,
+ },
+ })
+ const startTime = Date.now()
+ let loading = true
+ let loadingTimeout
+ loadingWindow.once('show', () => {
+ mainWindow.webContents.once('ready-to-show', () => {
+ loadingTimeout = setTimeout(() => {
+ loading = false
+ mainWindow.show()
+ loadingWindow.close()
+ }, Math.max(0, splashTime - (Date.now() - startTime)))
+ })
+ })
+ loadingWindow.once('closed', () => {
+ if (loading) {
+ clearTimeout(loadingTimeout)
+ mainWindow.close()
+ }
+ })
+ loadingWindow.once('ready-to-show', () => {
+ loadingWindow.show()
+ })
+ if (LOADING_WINDOW_VITE_DEV_SERVER_URL) {
+ loadingWindow.loadURL(`${LOADING_WINDOW_VITE_DEV_SERVER_URL}/loading.html`)
+ } else {
+ loadingWindow.loadFile(path.join(__dirname, `../renderer/${LOADING_WINDOW_VITE_NAME}/loading.html`))
+ }
+}
+
// 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.
@@ -71,7 +113,8 @@ app.whenReady().then(() => {
ipcMain.handle('nanodevices:disconnect', nanodevices.disconnect)
ipcMain.handle('nano:get', nano.get)
ipcMain.handle('nano:set', nano.set)
- const mainWindow = createWindow()
+ const mainWindow = createMainWindow()
+ createLoadingWindow(mainWindow)
ipcMain.on('electron:minimizeWindow', () => mainWindow.minimize())
ipcMain.on('electron:toggleMaximizeWindow', () => {
if (mainWindow.isMaximized()) {
@@ -109,7 +152,10 @@ app.on('activate', () => {
// On OS X it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (BrowserWindow.getAllWindows().length === 0) {
- createWindow()
+ const mainWindow = createMainWindow()
+ mainWindow.once('ready-to-show', () => {
+ mainWindow.show()
+ })
}
})
diff --git a/tailwind.config.js b/tailwind.config.js
index 98f9d2f..1e63f98 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -1,93 +1,93 @@
-const animate = require("tailwindcss-animate")
+const animate = require('tailwindcss-animate')
/** @type {import('tailwindcss').Config} */
module.exports = {
- darkMode: ["class"],
- safelist: ["dark"],
-
+ darkMode: ['class'],
+ safelist: ['dark'],
+
content: [
'./pages/**/*.{html,js,jsx,vue}',
'./components/**/*.{html,js,jsx,vue}',
'./app/**/*.{html,js,jsx,vue}',
'./src/**/*.{html,js,jsx,vue}',
- ],
-
+ ],
+
theme: {
container: {
center: true,
- padding: "2rem",
+ padding: '2rem',
screens: {
- "2xl": "1400px",
+ '2xl': '1400px',
},
},
extend: {
colors: {
- border: "hsl(var(--border))",
- input: "hsl(var(--input))",
- ring: "hsl(var(--ring))",
- background: "hsl(var(--background))",
- foreground: "hsl(var(--foreground))",
+ border: 'hsl(var(--border))',
+ input: 'hsl(var(--input))',
+ ring: 'hsl(var(--ring))',
+ background: 'hsl(var(--background))',
+ foreground: 'hsl(var(--foreground))',
primary: {
- DEFAULT: "hsl(var(--primary))",
- foreground: "hsl(var(--primary-foreground))",
+ DEFAULT: 'hsl(var(--primary))',
+ foreground: 'hsl(var(--primary-foreground))',
},
secondary: {
- DEFAULT: "hsl(var(--secondary))",
- foreground: "hsl(var(--secondary-foreground))",
+ DEFAULT: 'hsl(var(--secondary))',
+ foreground: 'hsl(var(--secondary-foreground))',
},
destructive: {
- DEFAULT: "hsl(var(--destructive))",
- foreground: "hsl(var(--destructive-foreground))",
+ DEFAULT: 'hsl(var(--destructive))',
+ foreground: 'hsl(var(--destructive-foreground))',
},
muted: {
- DEFAULT: "hsl(var(--muted))",
- foreground: "hsl(var(--muted-foreground))",
+ DEFAULT: 'hsl(var(--muted))',
+ foreground: 'hsl(var(--muted-foreground))',
},
accent: {
- DEFAULT: "hsl(var(--accent))",
- foreground: "hsl(var(--accent-foreground))",
+ DEFAULT: 'hsl(var(--accent))',
+ foreground: 'hsl(var(--accent-foreground))',
},
popover: {
- DEFAULT: "hsl(var(--popover))",
- foreground: "hsl(var(--popover-foreground))",
+ DEFAULT: 'hsl(var(--popover))',
+ foreground: 'hsl(var(--popover-foreground))',
},
card: {
- DEFAULT: "hsl(var(--card))",
- foreground: "hsl(var(--card-foreground))",
+ DEFAULT: 'hsl(var(--card))',
+ foreground: 'hsl(var(--card-foreground))',
},
},
borderRadius: {
- lg: "var(--radius)",
- md: "calc(var(--radius) - 2px)",
- sm: "calc(var(--radius) - 4px)",
+ lg: 'var(--radius)',
+ md: 'calc(var(--radius) - 2px)',
+ sm: 'calc(var(--radius) - 4px)',
},
keyframes: {
- "accordion-down": {
+ 'accordion-down': {
from: { height: 0 },
- to: { height: "var(--radix-accordion-content-height)" },
+ to: { height: 'var(--radix-accordion-content-height)' },
},
- "accordion-up": {
- from: { height: "var(--radix-accordion-content-height)" },
+ 'accordion-up': {
+ from: { height: 'var(--radix-accordion-content-height)' },
to: { height: 0 },
},
- "collapsible-down": {
+ 'collapsible-down': {
from: { height: 0 },
to: { height: 'var(--radix-collapsible-content-height)' },
},
- "collapsible-up": {
+ 'collapsible-up': {
from: { height: 'var(--radix-collapsible-content-height)' },
to: { height: 0 },
},
},
fontFamily: {
sans: ['JetbrainsMono', 'sans-serif'],
- heading: ['ProtoMono', 'sans-serif']
+ heading: ['ProtoMono', 'sans-serif'],
},
animation: {
- "accordion-down": "accordion-down 0.2s ease-out",
- "accordion-up": "accordion-up 0.2s ease-out",
- "collapsible-down": "collapsible-down 0.2s ease-in-out",
- "collapsible-up": "collapsible-up 0.2s ease-in-out",
+ 'accordion-down': 'accordion-down 0.2s ease-out',
+ 'accordion-up': 'accordion-up 0.2s ease-out',
+ 'collapsible-down': 'collapsible-down 0.2s ease-in-out',
+ 'collapsible-up': 'collapsible-up 0.2s ease-in-out',
},
},
},
diff --git a/vite.loading.config.mjs b/vite.loading.config.mjs
new file mode 100644
index 0000000..26178df
--- /dev/null
+++ b/vite.loading.config.mjs
@@ -0,0 +1,10 @@
+import { defineConfig } from 'vite'
+import { fileURLToPath, URL } from 'node:url'
+
+export default defineConfig({
+ resolve: {
+ alias: {
+ '@': fileURLToPath(new URL('./src', import.meta.url)),
+ },
+ },
+})
diff --git a/vite.main.config.mjs b/vite.main.config.mjs
index 300b63c..faf0188 100644
--- a/vite.main.config.mjs
+++ b/vite.main.config.mjs
@@ -1,4 +1,5 @@
-import { defineConfig } from 'vite';
+import { defineConfig } from 'vite'
+import eslint from 'vite-plugin-eslint'
// https://vitejs.dev/config
export default defineConfig({
@@ -8,4 +9,10 @@ export default defineConfig({
conditions: ['node'],
mainFields: ['module', 'jsnext:main', 'jsnext'],
},
-});
+ plugins: [
+ eslint({
+ cache: true,
+ failOnError: false,
+ }),
+ ],
+})
diff --git a/vite.preload.config.mjs b/vite.preload.config.mjs
index 690be5b..d00057b 100644
--- a/vite.preload.config.mjs
+++ b/vite.preload.config.mjs
@@ -1,4 +1,4 @@
-import { defineConfig } from 'vite';
+import { defineConfig } from 'vite'
// https://vitejs.dev/config
-export default defineConfig({});
+export default defineConfig({})
diff --git a/vite.renderer.config.mjs b/vite.renderer.config.mjs
index b67c611..a52797c 100644
--- a/vite.renderer.config.mjs
+++ b/vite.renderer.config.mjs
@@ -1,12 +1,12 @@
-import { defineConfig } from 'vite';
-import vue from '@vitejs/plugin-vue';
+import { defineConfig } from 'vite'
+import vue from '@vitejs/plugin-vue'
import { fileURLToPath, URL } from 'node:url'
export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
- '@': fileURLToPath(new URL('./src', import.meta.url))
- }
- }
-});
+ '@': fileURLToPath(new URL('./src', import.meta.url)),
+ },
+ },
+})