@glassnote/client 2.4.16 → 2.4.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/INSTALACION.md +73 -14
- package/autoStart.js +1 -1
- package/bin/glassnote.js +11 -4
- package/main.js +59 -10
- package/npmUpdate.js +3 -1
- package/package.json +2 -2
package/INSTALACION.md
CHANGED
|
@@ -63,19 +63,19 @@ donde la app los busca, y el cliente arranca ya conectado.
|
|
|
63
63
|
```sh
|
|
64
64
|
# Linux / macOS — ojo con el `-s --`, es lo que hace que sh le pase las banderas al script
|
|
65
65
|
curl -fsSL https://glassnote.intermark.ec/install.sh | sh -s -- \
|
|
66
|
-
--org-id
|
|
66
|
+
--org-id <id> --api-key <clave> --device-name "Caja 01" --user-name "Santiago"
|
|
67
67
|
```
|
|
68
68
|
|
|
69
69
|
```powershell
|
|
70
70
|
# Windows — con parámetros: `[scriptblock]` es lo que deja pasárselos al script bajado
|
|
71
71
|
& ([scriptblock]::Create((irm https://glassnote.intermark.ec/install.ps1))) `
|
|
72
|
-
-OrgId
|
|
72
|
+
-OrgId <id> -ApiKey <clave> -DeviceName 'Caja 01' -UserName 'Santiago'
|
|
73
73
|
```
|
|
74
74
|
|
|
75
75
|
```powershell
|
|
76
76
|
# Windows — con variables de entorno: `irm | iex` no deja pasar parámetros, pero el
|
|
77
77
|
# cliente lee las variables (quedan puestas en esa ventana de PowerShell)
|
|
78
|
-
$env:GLASSNOTE_ORG_ID='
|
|
78
|
+
$env:GLASSNOTE_ORG_ID='<id>'; $env:GLASSNOTE_API_KEY='<clave>'; $env:GLASSNOTE_DEVICE_NAME='Caja 01'; $env:GLASSNOTE_USER_NAME='Santiago'
|
|
79
79
|
irm https://glassnote.intermark.ec/install.ps1 | iex
|
|
80
80
|
```
|
|
81
81
|
|
|
@@ -98,6 +98,60 @@ Es el diseño: en GlassNote un dispositivo es un usuario en un equipo. Dos usuar
|
|
|
98
98
|
misma máquina son dos dispositivos en el tablero, cada uno con su `device-id`, y cada
|
|
99
99
|
cliente corre mientras su usuario tiene la sesión abierta.
|
|
100
100
|
|
|
101
|
+
Para SCCM/Microsoft Configuration Manager en producción hay dos formas, con el mismo
|
|
102
|
+
paquete offline adentro:
|
|
103
|
+
|
|
104
|
+
| Forma | Cuándo |
|
|
105
|
+
|---|---|
|
|
106
|
+
| **MSI** `glassnote-client-offline.msi` | La recomendada para Configuration Manager e Intune. Se importa como aplicación *Windows Installer*. Lleva el paquete adentro: el equipo no descarga nada. La detección hay que cambiarla a la marca del registro (ver la guía de SCCM). |
|
|
107
|
+
| Bootstrap `install-glassnote-sccm.ps1` | Cuando no se quiere poner 145 MB en el punto de distribución: el script baja el ZIP desde `glassnote.intermark.ec` en cada equipo. |
|
|
108
|
+
|
|
109
|
+
### El MSI
|
|
110
|
+
|
|
111
|
+
```text
|
|
112
|
+
https://glassnote.intermark.ec/glassnote-client-offline.msi
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Instalar y desinstalar:
|
|
116
|
+
|
|
117
|
+
```text
|
|
118
|
+
msiexec /i glassnote-client-offline.msi GLASSNOTE_ORG_ID=<id> GLASSNOTE_API_KEY=<clave> /qn
|
|
119
|
+
msiexec /x {ProductCode} /qn
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
El ProductCode cambia con cada paquete, así que no se escribe a mano: para desinstalar,
|
|
123
|
+
búsquelo en `HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall` por el nombre
|
|
124
|
+
`GlassNote Client (offline)`. Propiedades: `GLASSNOTE_ORG_ID` y `GLASSNOTE_API_KEY`
|
|
125
|
+
(obligatorias), `GLASSNOTE_API_URL`, `GLASSNOTE_WS_URL`, `GLASSNOTE_DEVICE_NAME`,
|
|
126
|
+
`GLASSNOTE_USER_NAME`. Sin el alta la instalación falla con 1603 y no deja nada.
|
|
127
|
+
|
|
128
|
+
Un paquete nuevo reemplaza al anterior aunque sea la misma versión del cliente, y volver
|
|
129
|
+
a lanzar el mismo paquete repara un equipo donde el producto figura instalado pero el
|
|
130
|
+
cliente no está.
|
|
131
|
+
|
|
132
|
+
El MSI se instala por equipo, pero el cliente es por usuario: la instalación corre como
|
|
133
|
+
SYSTEM, busca al usuario con sesión iniciada e instala en su sesión, espera y devuelve su
|
|
134
|
+
código de salida. **Sin nadie con sesión iniciada no instala** y msiexec devuelve error.
|
|
135
|
+
Desinstalar quita el cliente del usuario, el autoarranque y los archivos del paquete;
|
|
136
|
+
**no toca `%APPDATA%\glassnote`**, así que reinstalar deja el mismo dispositivo.
|
|
137
|
+
|
|
138
|
+
### El bootstrap
|
|
139
|
+
|
|
140
|
+
```text
|
|
141
|
+
https://glassnote.intermark.ec/install-glassnote-sccm.ps1
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Ese bootstrap descarga:
|
|
145
|
+
|
|
146
|
+
```text
|
|
147
|
+
https://glassnote.intermark.ec/glassnote-sccm-offline-runtime.zip
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
El ZIP lo genera GitHub Actions durante el deploy de `glassnote-next` e incluye Node.js
|
|
151
|
+
portable, Electron, cache npm y `glassnote-client-2.4.17.tgz`. Así la instalación inicial
|
|
152
|
+
no depende de `nodejs.org`, GitHub ni `registry.npmjs.org`. El `install.ps1` genérico queda
|
|
153
|
+
para instalaciones manuales, Intune/GPO simples o equipos con salida normal a internet.
|
|
154
|
+
|
|
101
155
|
Estas herramientas suelen correr los scripts como **SYSTEM**, y un cliente instalado así
|
|
102
156
|
quedaría en el perfil de SYSTEM, donde nadie lo ve.
|
|
103
157
|
|
|
@@ -112,7 +166,8 @@ quedaría en el perfil de SYSTEM, donde nadie lo ve.
|
|
|
112
166
|
| GPO | script de inicio de sesión en *User Configuration*, no de arranque en *Computer Configuration* |
|
|
113
167
|
|
|
114
168
|
**Cuando no se puede** —*Run Scripts* de SCCM corre siempre como SYSTEM, igual que una
|
|
115
|
-
Application con *Install for system
|
|
169
|
+
Application con *Install for system*, y un MSI siempre se instala con permisos de
|
|
170
|
+
administrador— el instalador lo detecta y no instala en SYSTEM:
|
|
116
171
|
|
|
117
172
|
1. busca al usuario con sesión iniciada (el dueño de `explorer.exe`);
|
|
118
173
|
2. deja el instalador en el `%TEMP%` de ese usuario y lo corre con una tarea programada de
|
|
@@ -120,9 +175,10 @@ Application con *Install for system*— el instalador lo detecta y no instala en
|
|
|
120
175
|
3. espera a que termine, muestra su salida y sale con su código;
|
|
121
176
|
4. borra la tarea y la carpeta.
|
|
122
177
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
comandos, y el script que la
|
|
178
|
+
Lo hacen los tres: `install.ps1`, el paquete offline y el MSI. El comando es el mismo en
|
|
179
|
+
los dos casos. Las variables de entorno y los parámetros llegan a la sesión del usuario; la
|
|
180
|
+
API key viaja como variable de entorno, nunca en una línea de comandos, y el script que la
|
|
181
|
+
lleva se borra al arrancar.
|
|
126
182
|
|
|
127
183
|
```powershell
|
|
128
184
|
# el mismo script para todo el parque
|
|
@@ -141,9 +197,10 @@ Límites del camino por SYSTEM:
|
|
|
141
197
|
*Only when a user is logged on*.
|
|
142
198
|
- **Instala para el usuario con sesión**, el primero que encuentra. Otro usuario del mismo
|
|
143
199
|
equipo es otro dispositivo y necesita su propia instalación.
|
|
144
|
-
- ***Run Scripts* corta por timeout** (60 s por defecto)
|
|
145
|
-
|
|
146
|
-
|
|
200
|
+
- ***Run Scripts* corta por timeout** (60 s por defecto). Para SCCM offline suba el
|
|
201
|
+
timeout a unos 1800 s porque baja y extrae un ZIP de alrededor de 150 MB. Si corta,
|
|
202
|
+
revise `C:\ProgramData\GlassNote\install-sccm-bootstrap.log` y
|
|
203
|
+
`C:\ProgramData\GlassNote\install-sccm.log`.
|
|
147
204
|
- El `out.log` de la instalación queda tomado por el cliente, que hereda esa salida, hasta
|
|
148
205
|
que se cierra. La carpeta `glassnote-install-*` se limpia en la siguiente instalación.
|
|
149
206
|
|
|
@@ -187,9 +244,11 @@ instalación la haya lanzado SYSTEM.
|
|
|
187
244
|
- **Renderer**: a los 10 s de arrancar y después cada hora mira `version_renderer.txt` en el
|
|
188
245
|
bucket de S3 y baja el zip a `%APPDATA%\glassnote\renderer`. No toca el binario.
|
|
189
246
|
|
|
190
|
-
Salidas a internet que necesita el equipo: `registry.npmjs.org`
|
|
191
|
-
`glassnote.s3.us-east-1.amazonaws.com` (renderer), `nodejs.org`
|
|
192
|
-
la API.
|
|
247
|
+
Salidas a internet que necesita el equipo con el instalador genérico: `registry.npmjs.org`
|
|
248
|
+
(instalar y actualizar), `glassnote.s3.us-east-1.amazonaws.com` (renderer), `nodejs.org`
|
|
249
|
+
(solo si no hay Node) y la API. Con el instalador SCCM offline, la instalación inicial
|
|
250
|
+
usa `glassnote.intermark.ec` para descargar el ZIP y la API para registrar el dispositivo;
|
|
251
|
+
`registry.npmjs.org` queda para actualizaciones posteriores del cliente.
|
|
193
252
|
|
|
194
253
|
Sin probar, pero a revisar con el área de sistemas del cliente:
|
|
195
254
|
|
|
@@ -240,7 +299,7 @@ días, lo que acota lo que se puede hacer con una que se filtre.
|
|
|
240
299
|
Un equipo ya instalado se empareja sin reinstalar:
|
|
241
300
|
|
|
242
301
|
```sh
|
|
243
|
-
glassnote pair --org-id
|
|
302
|
+
glassnote pair --org-id <id> --api-key <clave> --device-name "Caja 01"
|
|
244
303
|
```
|
|
245
304
|
|
|
246
305
|
Si el alta falla, el comando **sale con código distinto de cero** y dice por qué (la
|
package/autoStart.js
CHANGED
package/bin/glassnote.js
CHANGED
|
@@ -72,7 +72,7 @@ function npmInvocation(args) {
|
|
|
72
72
|
|
|
73
73
|
function runNpm(args, opts) {
|
|
74
74
|
const { file, args: argv, shell } = npmInvocation(args);
|
|
75
|
-
return spawnSync(file, argv, Object.assign({ stdio: 'inherit', shell, env: npmEnv() }, opts || {}));
|
|
75
|
+
return spawnSync(file, argv, Object.assign({ stdio: 'inherit', shell, env: npmEnv(), windowsHide: true }, opts || {}));
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
// userData tira de `uuid`, y este CLI corre también donde el árbol de dependencias no
|
|
@@ -113,6 +113,7 @@ function clienteEnMarcha() {
|
|
|
113
113
|
env: Object.assign({}, process.env, { ELECTRON_RUN_AS_NODE: '1' }),
|
|
114
114
|
stdio: 'ignore',
|
|
115
115
|
timeout: 4000,
|
|
116
|
+
windowsHide: true,
|
|
116
117
|
});
|
|
117
118
|
return res.status === 0;
|
|
118
119
|
}
|
|
@@ -193,7 +194,7 @@ function cerrarClienteWindows() {
|
|
|
193
194
|
const res = spawnSync(
|
|
194
195
|
'powershell.exe',
|
|
195
196
|
['-NoProfile', '-NonInteractive', '-Command', guionCerrarCliente(rutaDelClienteInstalado(), process.pid)],
|
|
196
|
-
{ encoding: 'utf8', timeout: 20000 }
|
|
197
|
+
{ encoding: 'utf8', timeout: 20000, windowsHide: true }
|
|
197
198
|
);
|
|
198
199
|
|
|
199
200
|
// Si PowerShell no está o falló, no se sigue a ciegas: se mira si el cliente
|
|
@@ -272,12 +273,12 @@ function launch({ detach = false, extra = [] } = {}) {
|
|
|
272
273
|
}
|
|
273
274
|
|
|
274
275
|
if (detach) {
|
|
275
|
-
const child = spawn(binary, args, { detached: true, stdio: 'ignore', env });
|
|
276
|
+
const child = spawn(binary, args, { detached: true, stdio: 'ignore', env, windowsHide: true });
|
|
276
277
|
child.unref();
|
|
277
278
|
return 0;
|
|
278
279
|
}
|
|
279
280
|
|
|
280
|
-
const child = spawnSync(binary, args, { stdio: 'inherit', env });
|
|
281
|
+
const child = spawnSync(binary, args, { stdio: 'inherit', env, windowsHide: true });
|
|
281
282
|
if (child.error) fail(`no se pudo arrancar el cliente: ${child.error.message}`);
|
|
282
283
|
if (child.status !== 0 && process.platform === 'linux') {
|
|
283
284
|
console.error(
|
|
@@ -328,6 +329,7 @@ function addToPathWindows(dir = mode.BIN_DIR) {
|
|
|
328
329
|
].join('; ');
|
|
329
330
|
const res = spawnSync('powershell', ['-NoProfile', '-NonInteractive', '-Command', ps], {
|
|
330
331
|
encoding: 'utf8',
|
|
332
|
+
windowsHide: true,
|
|
331
333
|
});
|
|
332
334
|
const added = res.status === 0 && String(res.stdout).includes('added');
|
|
333
335
|
return { touched: added ? ['PATH de usuario (sin administrador)'] : [], line: dir };
|
|
@@ -389,6 +391,7 @@ function removeFromPathWindows() {
|
|
|
389
391
|
].join('; ');
|
|
390
392
|
const res = spawnSync('powershell', ['-NoProfile', '-NonInteractive', '-Command', ps], {
|
|
391
393
|
encoding: 'utf8',
|
|
394
|
+
windowsHide: true,
|
|
392
395
|
});
|
|
393
396
|
return res.status === 0 && String(res.stdout).includes('removed');
|
|
394
397
|
}
|
|
@@ -633,10 +636,14 @@ async function cmdInstall(args) {
|
|
|
633
636
|
// Al arrancar, la app se registra sola en el autoarranque del usuario.
|
|
634
637
|
step('arrancando el cliente en segundo plano (queda en la bandeja del sistema)');
|
|
635
638
|
const binary = path.join(mode.INSTALLED_PACKAGE_DIR, 'bin', 'glassnote.js');
|
|
639
|
+
// windowsHide: en Windows un proceso desprendido abre su propia consola, y la gente la
|
|
640
|
+
// cierra. Lo mismo vale para cada spawn de este archivo: el ayudante de actualización
|
|
641
|
+
// corre sin consola, y ahí cualquier hijo de consola sin windowsHide abriría una.
|
|
636
642
|
const child = spawn(process.execPath, [binary, 'start', '--detach'], {
|
|
637
643
|
detached: true,
|
|
638
644
|
stdio: 'ignore',
|
|
639
645
|
env: process.env,
|
|
646
|
+
windowsHide: true,
|
|
640
647
|
});
|
|
641
648
|
child.unref();
|
|
642
649
|
log('Listo. Ícono en la bandeja; se abrirá solo en los próximos arranques.');
|
package/main.js
CHANGED
|
@@ -6,6 +6,7 @@ const {
|
|
|
6
6
|
Menu,
|
|
7
7
|
nativeImage,
|
|
8
8
|
screen,
|
|
9
|
+
session,
|
|
9
10
|
} = require('electron');
|
|
10
11
|
const packageJson = require('./package.json');
|
|
11
12
|
const LocalServer = require('./localserver');
|
|
@@ -231,6 +232,8 @@ setInterval(cleanupOldLogs, LIMPIEZA_LOGS_MS).unref();
|
|
|
231
232
|
createTailUtility(logsDir);
|
|
232
233
|
|
|
233
234
|
app.whenReady().then(() => {
|
|
235
|
+
allowYoutubeEmbeds();
|
|
236
|
+
|
|
234
237
|
// macOS: esto es una app de bandeja, se maneja desde la barra de menu. Instalada por
|
|
235
238
|
// npm no hay .app propio, asi que el Dock mostraba el icono por defecto de Electron y
|
|
236
239
|
// una entrada que no sirve para nada. Se saca del Dock, pero antes se le pone el icono
|
|
@@ -865,23 +868,34 @@ function iniciarSondeoCursor() {
|
|
|
865
868
|
}
|
|
866
869
|
if (!dentro) return;
|
|
867
870
|
|
|
868
|
-
//
|
|
869
|
-
//
|
|
870
|
-
//
|
|
871
|
-
//
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
//
|
|
875
|
-
//
|
|
876
|
-
|
|
871
|
+
// En Linux se inyecta mientras el overlay ignora el mouse: ahi no llega nada, y con
|
|
872
|
+
// la ventana clickeable los eventos reales llegan solos.
|
|
873
|
+
//
|
|
874
|
+
// En Windows es AL REVES. Mientras ignora, el `forward: true` de setIgnoreMouseEvents
|
|
875
|
+
// ya entrega los movimientos reales —medido: el boton recibe mouseover y se puede
|
|
876
|
+
// clickear—. Pero con la ventana clickeable Windows NO le manda todos: el clic que
|
|
877
|
+
// activa el overlay (desde 2.4.12 se muestra sin foco, asi que el primer clic sobre
|
|
878
|
+
// un formulario lo activa) le devuelve el WS_EX_LAYERED a los ~30 ms, y una ventana
|
|
879
|
+
// layered deja pasar el mouse por sus pixeles transparentes a la ventana de abajo.
|
|
880
|
+
// El cursor sale del formulario, el renderer no recibe un solo movimiento, se queda
|
|
881
|
+
// con la ultima posicion —encima del formulario— y nunca devuelve el passthrough: el
|
|
882
|
+
// overlay queda clickeable y se come los clics sobre todo lo que dibuja. Medido en
|
|
883
|
+
// la VM de Windows 11 con el estilo de la ventana (0x80008 en vez de 0x80028) y con
|
|
884
|
+
// el estado del renderer; en 2.4.11, con la ventana ya activa, no pasaba.
|
|
885
|
+
// Se le cuenta la posicion desde aca y el renderer se pone al dia solo.
|
|
886
|
+
// En macOS no se midio nada de esto: queda como estaba.
|
|
887
|
+
if (process.platform === 'darwin') return;
|
|
888
|
+
if (enLinux ? !ignorandoMouse : ignorandoMouse) return;
|
|
877
889
|
|
|
878
890
|
// Repetir el mismo punto en cada tick es ruido, pero callarse del todo mientras el
|
|
879
891
|
// cursor esta quieto rompe el otro caso: el menu se abre DEBAJO de un cursor que no
|
|
880
892
|
// se movio, no hay mousemove que lo cuente, y ese boton nace muerto. Se reemite cada
|
|
881
893
|
// tanto para que la UI que aparece sola se entere igual.
|
|
894
|
+
// En Windows solo cuando el cursor se mueve: el menu que aparece bajo un cursor
|
|
895
|
+
// quieto ya lo cubre el forward, y repetir el punto no le cuenta nada nuevo.
|
|
882
896
|
const ahora = Date.now();
|
|
883
897
|
const mismoPunto = x === ultimoPuntoEnviado.x && y === ultimoPuntoEnviado.y;
|
|
884
|
-
if (mismoPunto && ahora - ultimoEnvioMs < REEMISION_QUIETO_MS) return;
|
|
898
|
+
if (mismoPunto && (!enLinux || ahora - ultimoEnvioMs < REEMISION_QUIETO_MS)) return;
|
|
885
899
|
ultimoPuntoEnviado = { x, y };
|
|
886
900
|
ultimoEnvioMs = ahora;
|
|
887
901
|
mainWindow.webContents.sendInputEvent({ type: 'mouseMove', x, y });
|
|
@@ -1057,6 +1071,41 @@ process.on('unhandledRejection', (reason, promise) => {
|
|
|
1057
1071
|
|
|
1058
1072
|
|
|
1059
1073
|
|
|
1074
|
+
/**
|
|
1075
|
+
* YouTube rechaza el reproductor embebido que llega sin Referer: muestra "Video player
|
|
1076
|
+
* configuration error" (el error 153) en vez del video. El renderer se carga desde file://
|
|
1077
|
+
* y de ahi Chromium no manda Referer a ningun sitio https, asi que un glass con un video
|
|
1078
|
+
* nunca lo reproduciria. Medido sobre Electron 29 con el mismo video: sin esto se queda en
|
|
1079
|
+
* 0 s con el error; con esto reproduce, con sonido.
|
|
1080
|
+
*
|
|
1081
|
+
* Solo toca el pedido del reproductor (/embed/) y solo si no trae Referer: la
|
|
1082
|
+
* previsualizacion web, que va por https, manda el suyo y no pasa por aca.
|
|
1083
|
+
*
|
|
1084
|
+
* OJO: Electron admite UN solo onBeforeSendHeaders por sesion. Registrar otro en cualquier
|
|
1085
|
+
* lado reemplaza a este sin avisar, y los videos vuelven a dar el 153.
|
|
1086
|
+
*/
|
|
1087
|
+
function allowYoutubeEmbeds() {
|
|
1088
|
+
try {
|
|
1089
|
+
session.defaultSession.webRequest.onBeforeSendHeaders(
|
|
1090
|
+
{
|
|
1091
|
+
urls: [
|
|
1092
|
+
'https://www.youtube.com/embed/*',
|
|
1093
|
+
'https://www.youtube-nocookie.com/embed/*',
|
|
1094
|
+
],
|
|
1095
|
+
},
|
|
1096
|
+
(details, callback) => {
|
|
1097
|
+
const headers = details.requestHeaders;
|
|
1098
|
+
if (!headers.Referer && !headers.referer) {
|
|
1099
|
+
headers.Referer = 'https://glassnote.intermark.ec/';
|
|
1100
|
+
}
|
|
1101
|
+
callback({ requestHeaders: headers });
|
|
1102
|
+
}
|
|
1103
|
+
);
|
|
1104
|
+
} catch (error) {
|
|
1105
|
+
console.error('[youtube] no se pudo preparar el Referer de los videos:', error.message);
|
|
1106
|
+
}
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1060
1109
|
/**
|
|
1061
1110
|
* Carga el HTML del renderer. Cual de las dos fuentes gana lo decide resolverRenderer()
|
|
1062
1111
|
* en rendererPaths.js, que es tambien de donde sale la version que muestra el menu.
|
package/npmUpdate.js
CHANGED
|
@@ -238,12 +238,14 @@ class NpmUpdate {
|
|
|
238
238
|
}
|
|
239
239
|
|
|
240
240
|
try {
|
|
241
|
+
// windowsHide: sin él Windows le abre una consola al ayudante, que dura todo el
|
|
242
|
+
// npm install, y si el usuario la cierra la actualización muere a medias.
|
|
241
243
|
// cwd fuera del paquete: en Windows no se puede borrar un directorio que es
|
|
242
244
|
// el cwd de un proceso vivo, y ese proceso sería justamente el actualizador.
|
|
243
245
|
const child = spawn(
|
|
244
246
|
nodeBinary || process.execPath,
|
|
245
247
|
[cli, 'update', version, '--relaunch', '--wait', '4000'],
|
|
246
|
-
{ detached: true, stdio: ['ignore', salida, salida], env, cwd: os.tmpdir() }
|
|
248
|
+
{ detached: true, stdio: ['ignore', salida, salida], env, cwd: os.tmpdir(), windowsHide: true }
|
|
247
249
|
);
|
|
248
250
|
child.unref();
|
|
249
251
|
console.warn(`[update] ayudante lanzado, pid ${child.pid}; la app se cierra en 500 ms`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@glassnote/client",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.18",
|
|
4
4
|
"description": "GlassNote — cliente de escritorio de notas superpuestas. Se instala con npx, sin instaladores nativos ni firmas.",
|
|
5
5
|
"main": "main.js",
|
|
6
6
|
"publishConfig": {
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
"url": "git+ssh://git@intermarkec/intermarkec/glassnote-electron.git"
|
|
76
76
|
},
|
|
77
77
|
"dependencies": {
|
|
78
|
-
"@glassnote/renderer": "2.2
|
|
78
|
+
"@glassnote/renderer": "2.3.2",
|
|
79
79
|
"cors": "^2.8.5",
|
|
80
80
|
"electron": "^29.4.6",
|
|
81
81
|
"express": "^4.18.2",
|