Munka 9489d6cc58 Las pestañas ocupan la fila del título también en Windows
En Windows la ventana conservaba la barra de título del sistema y la barra de
pestañas iba DEBAJO: una fila entera gastada en repetir el nombre de la app. En
macOS ya no pasaba (TitleBarStyle::Overlay desde la v1.4.2). Ahora las dos se
comportan igual, y como Chrome: la barra de pestañas ES la fila del título.

- Ventana sin decoración en Windows (decorations(false)). resizable(true) conserva
  WS_THICKFRAME, así que los bordes siguen redimensionando y Aero Snap (arrastrar a
  un borde, Win+flechas) sigue vivo.
- La barra dibuja sus propios botones minimizar/maximizar/cerrar con las medidas y
  colores del sistema (46 px de ancho, alto completo de la barra, esquinas rectas,
  rojo #c42b1c al posarse en el aspa) y los glifos de Segoe Fluent Icons. Actúan
  por el evento nuevo ls-window; cerrar sigue pasando por CloseRequested, o sea que
  oculta a la bandeja igual que antes.
- El icono del medio alterna maximizar/restaurar según el estado. El repintado se
  dispara solo cuando ese estado CAMBIA, no en cada píxel del redimensionado.
- La geometría maximizada ya no se guarda entre sesiones: sin decoración, al
  reabrir volvería como ventana normal del tamaño de la pantalla y taparía la barra
  de tareas. Se conserva la última geometría restaurada.
- Doble clic en el hueco libre de la barra ahora maximiza/restaura (lo gobierna
  data-tauri-drag-region), como la barra de título del sistema y como Chrome. Antes
  abría una pestaña nueva; para eso quedan el botón + y Cmd/Ctrl+T.

NO incluye los Snap Layouts de Windows 11 (el menú que asoma al posar el cursor
sobre maximizar). Requieren que la ventana conteste WM_NCHITTEST con HTMAXBUTTON, y
aquí ese botón lo tapa el webview hijo de la barra, que se queda con los mensajes
del ratón: la ventana principal nunca los ve. Es la misma razón por la que Electron
necesita botones NATIVOS (titleBarOverlay) para poder ofrecerlo. El resto de Aero
Snap no se ve afectado.

Se añade .github/workflows/check.yml: cargo check en Windows y macOS al empujar una
rama, sin publicar nada. Hasta ahora solo existía el workflow de publicar (etiquetas
v*), así que no había forma de comprobar que algo compilaba sin sacar un release.

Verificado: sintaxis del script de la barra con node --check; medidas, clases y
estados de los botones comprobados en el navegador (46 px, pegados al borde, ocultos
en macOS, icono y rótulo correctos al maximizar, y el arrastre solo en el hueco
libre, nunca en los botones). La compilación la verifica el workflow nuevo.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 12:35:10 -05:00

Labstream OS — App de escritorio (Windows + macOS)

Cliente de escritorio para Labstream OS, hecho con Tauri 2. Desde la v1.1.0 no es un envoltorio de una sola vista: es un shell con pestañas (multiwebview) sobre el servidor del NAS (https://os.labstreamsas.com).

No contiene la app: el backend, la base de datos, OnlyOffice, etc. siguen en el NAS. Esto le da al equipo un cliente nativo de verdad en Windows y Mac:

  • Pestañas como en un navegador: los enlaces internos con target="_blank" (documentos, entregables, exportaciones, OnlyOffice…) abren pestaña dentro de la app — antes morían en silencio. También ⌘/Ctrl+clic y clic central. Atajos: ⌘/Ctrl+T nueva, ⌘/Ctrl+W cerrar, Ctrl+Tab rotar, ⌘/Ctrl+1…9 ir a la n. La sesión (pestañas abiertas, activa) se restaura al reabrir.
  • Zoom de interfaz: ⌘/Ctrl + / − / 0 y Ctrl+rueda, con indicador en la barra y persistencia entre sesiones (50%–250%).
  • Documentos dentro de la app: los visores/editores del propio servidor (OnlyOffice, PDFs, reproductor de revisión) abren en pestañas; solo lo de OTRO origen (Drive…) sale al navegador del sistema. El login por Authentik sigue funcionando dentro.
  • Notas de voz / cámara: pide permiso de micrófono y cámara (entitlements de macOS).
  • Descargas (entregables, exportaciones) con el diálogo nativo de guardado.
  • Bandeja del sistema: cerrar la ventana la oculta; la app sigue notificando. En macOS, el clic en el Dock también reabre la ventana, y hay menú nativo en español (Edición/Vista/Archivo) con los atajos.
  • Arranque automático al iniciar sesión y sesión persistente (no re-loguea).
  • Una sola instancia (release): abrirla de nuevo enfoca la ventana existente.
  • Menú de opciones ⋮ (v1.2.0) en la barra — también con clic derecho sobre ella: pestañas, zoom, recargar, abrir la página en el navegador, Iniciar con el sistema (elección recordada) y Buscar actualización… con aviso del resultado. Es un popup nativo del sistema, igual en Windows y macOS, y vive solo en el shell (la web app no se toca).

La barra de pestañas vive en dist/index.html (webview local «chrome»); las pestañas son webviews hijos tab-*. Shell ↔ Rust se hablan por eventos ls-*.

El servidor objetivo se configura en src-tauri/src/lib.rs → constante SERVER_URL.

Salidas:

  • Windows → instalador .exe (NSIS).
  • macOS → .dmg universal (funciona en Intel y Apple Silicon).

Prerrequisitos (solo para construir)

Quien instala no necesita nada (en Windows, WebView2 ya viene en Win 10/11; en Mac, el WebView del sistema). Para construir hacen falta:

  • Node.js 20+
  • Rust (incluye cargo)
  • En Windows: "Visual Studio Build Tools" con el componente de C++.
  • En Mac: Xcode Command Line Tools (xcode-select --install).

⚠️ Cada sistema se construye en su sistema: el .exe se compila en Windows y el .dmg en Mac. Tauri no compila de forma cruzada de manera fiable. Por eso lo normal es dejar que GitHub Actions construya ambos (ver abajo). Como excepción cómoda: si trabajas en Mac, el .dmg sí lo puedes hacer en local.


Construir los instaladores con GitHub Actions (recomendado)

Genera ambos instaladores sin tener las dos máquinas a mano:

  1. Sube este proyecto a su propio repositorio (ej. Labstream2026/labstream-desktop).
  2. Cambia la versión en dos sitios (deben coincidir):
    • src-tauri/tauri.conf.json → "version"
    • src-tauri/Cargo.toml → version
    • (opcional) package.json → "version"
  3. Crea y publica la etiqueta de versión:
    git commit -am "Versión 1.1.0"
    git tag v1.1.0
    git push origin main --tags
    
  4. GitHub Actions construye el .exe (Windows) y el .dmg (macOS) en paralelo y los publica juntos en Releases: https://github.com/Labstream2026/labstream-desktop/releases.

También puedes lanzarlo a mano sin etiqueta desde Actions → Build instaladores → Run workflow (los instaladores quedan como artifacts).


Construir en local

En Mac (tu máquina) → genera el .dmg

npm install
npm run icons
npm run tauri build -- --bundles dmg

El .dmg queda en:

src-tauri/target/release/bundle/dmg/Labstream OS_<versión>_<arch>.dmg

Para un .dmg universal (Intel + Apple Silicon) en local:

rustup target add aarch64-apple-darwin x86_64-apple-darwin
npm run tauri build -- --target universal-apple-darwin --bundles dmg

En una PC Windows → genera el .exe

npm install
npm run tauri build -- --bundles nsis

Queda en src-tauri/target/release/bundle/nsis/Labstream OS_<versión>_x64-setup.exe.

Para desarrollo con recarga en caliente (en cualquier sistema): npm run dev.


Versiones (SemVer)

Se usa MAYOR.MENOR.PARCHE:

Cambio Ejemplo
Corrección / arreglo 1.0.0 → 1.0.1
Función nueva compatible 1.0.1 → 1.1.0
Cambio grande / incompatible 1.1.0 → 2.0.0

La versión del envoltorio es independiente de la de la app web (labstream-os). Una sola etiqueta de versión genera el instalador de Windows y el de Mac a la vez, así ambas plataformas van siempre sincronizadas.


Actualización automática (opcional, recomendable a futuro)

Hoy, para actualizar, el equipo descarga el nuevo instalador del Release y lo reinstala encima. Para que las apps ya instaladas se actualicen solas, Tauri trae un updater (funciona igual en Windows y Mac). Para activarlo (paso futuro):

  1. Genera el par de claves de firma:
    npm run tauri signer generate -- -w ~/.tauri/labstream.key
    
  2. Añade el plugin-updater y la clave pública en tauri.conf.json, y guarda la clave privada como secret en GitHub (TAURI_SIGNING_PRIVATE_KEY).
  3. Apunta el updater al latest.json que publica el Release.

Se deja sin activar a propósito para que la primera versión compile sin configuración extra.


Avisos de seguridad del sistema (instalación interna sin firmar)

Como los instaladores no están firmados con certificado de pago, la primera vez cada sistema muestra una advertencia. Es normal para apps internas:

  • Windows (SmartScreen): pantalla azul "Windows protegió su PC" → Más información → Ejecutar de todos modos.
  • macOS (Gatekeeper): "no se puede abrir porque proviene de un desarrollador no identificado" → clic derecho sobre la app → Abrir → Abrir. (Si insiste, ejecutar una vez: xattr -cr "/Applications/Labstream OS.app".)

Si en el futuro se distribuye a clientes externos, conviene firmar: code signing en Windows (~150–400 USD/año) y un Apple Developer ID + notarizado en Mac (99 USD/año) para quitar estos avisos.


Estructura

labstream-desktop/
├── app-icon.png                 fuente del ícono (1024×1024)
├── dist/index.html              pantalla de respaldo (requerida por Tauri)
├── package.json                 scripts de build
├── src-tauri/
│   ├── tauri.conf.json          nombre, versión, iconos, instaladores, entitlements
│   ├── Cargo.toml               dependencias Rust + versión
│   ├── Info.plist               textos de permiso (micrófono/cámara) en macOS
│   ├── Entitlements.plist       entitlements de macOS (audio-input, cámara, red)
│   ├── build.rs
│   ├── capabilities/default.json
│   ├── icons/                   se generan desde app-icon.png
│   └── src/{main.rs,lib.rs}     lib.rs crea la ventana + SERVER_URL + tray
└── .github/workflows/build.yml  build automático de .exe (Windows) y .dmg (macOS)
Descripción
App de escritorio de Labstream OS (Tauri 2, Windows y macOS)
Readme 378 KiB
Languages
Rust 96.5%
JavaScript 3.5%