This commit is contained in:
2026-10-17 20:16:24 +07:00
parent f5dc9c1e5b
commit 40456eebf1
16 changed files with 2122 additions and 54 deletions
+44 -6
View File
@@ -1,10 +1,12 @@
import { app, BrowserWindow, ipcMain, protocol, screen, session } from 'electron'
import { app, BrowserWindow, ipcMain, protocol, screen, session, safeStorage } from 'electron'
import { createReadStream } from 'node:fs'
import { stat } from 'node:fs/promises'
import { join } from 'node:path'
import { Readable } from 'node:stream'
import { Controller, parseCommand } from './controller.js'
import { parseRange } from './range.js'
import { Online } from './online.js'
import type { OnlineState } from '../src/types/online.js'
import { PackageStore } from './package-store.js'
import { packageMediaResponse } from './package-media.js'
import type { HostInfo } from '../src/types/screen.js'
@@ -21,6 +23,7 @@ protocol.registerSchemesAsPrivileged([
let control: BrowserWindow | null = null
let output: BrowserWindow | null = null
let selectedDisplay: number | null = null
let online: Online | null = null
const controller = new Controller((state) => {
for (const window of [control, output])
if (window && !window.isDestroyed()) window.webContents.send('state', state)
@@ -62,6 +65,7 @@ function requireControl(event: Electron.IpcMainInvokeEvent) {
throw new Error('Недоступно')
}
function show(displayId: number) {
if (online?.blocksOutput) throw new Error('Подождите завершения подготовки материалов')
const display = screen.getAllDisplays().find((d) => d.id === displayId)
if (!display || display.id === screen.getPrimaryDisplay().id)
throw new Error('Выберите внешний дисплей; включите расширенный рабочий стол')
@@ -98,9 +102,23 @@ app
.then(async () => {
const packages = new PackageStore(join(app.getPath('userData'), 'packages'))
await packages.initialize()
online = new Online(join(app.getPath('userData'), 'connection'), packages, controller, {
available: () =>
safeStorage.isEncryptionAvailable() &&
(process.platform !== 'linux' ||
!['basic_text', 'unknown'].includes(safeStorage.getSelectedStorageBackend())),
encrypt: (value) => safeStorage.encryptString(value),
decrypt: (value) => safeStorage.decryptString(value),
})
await online.initialize()
const onlineTick = setInterval(() => {
void online?.poll()
}, 1000)
const timerTick = setInterval(() => controller.tick(), 250)
app.on('before-quit', () => {
clearInterval(timerTick)
clearInterval(onlineTick)
online?.close()
packages.cancel()
})
session.defaultSession.setPermissionRequestHandler((_contents, _permission, callback) =>
@@ -182,12 +200,26 @@ app
throw new Error('Недоступно')
return controller.state
})
ipcMain.handle('online-state', (event): OnlineState => {
requireControl(event)
return online!.snapshot()
})
ipcMain.handle('online-action', async (event, intent: unknown) => {
requireControl(event)
if (selectingPackage) throw new Error('Подождите проверки пакета')
return online!.act(intent)
})
ipcMain.handle('close-output', (event) => {
requireControl(event)
output?.close()
})
ipcMain.handle('host', (event) => {
requireControl(event)
return host()
})
ipcMain.handle('show', (event, id: unknown) => {
requireControl(event)
if (selectingPackage) throw new Error('Подождите проверки пакета')
if (typeof id !== 'number') throw new Error('Некорректный дисплей')
show(id)
})
@@ -204,15 +236,14 @@ app
if (key !== null && typeof key !== 'string') throw new Error('Некорректный пакет')
selectingPackage = true
try {
controller.selectPackage(key === null ? null : await packages.verify(key))
await online!.select(key)
return controller.state
} catch (error) {
if (key === controller.state.catalog.key) controller.selectPackage(null)
throw error
} finally {
selectingPackage = false
}
})
let localSession = ''
let localSequence = 0
ipcMain.handle('command', (event, command: unknown) => {
requireControl(event)
if (selectingPackage) throw new Error('Подождите проверки пакета')
@@ -222,7 +253,14 @@ app
['play', 'pause', 'resume', 'stop', 'replay', 'seek', 'next'].includes(parsed.action)
)
throw new Error('Сначала откройте окно показа')
controller.command(parsed)
if (parsed.session !== controller.state.session) return
if (localSession !== parsed.session) {
localSession = parsed.session
localSequence = 0
}
if (parsed.sequence <= localSequence) return
controller.command({ ...parsed, sequence: controller.state.sequence + 1 })
localSequence = parsed.sequence
})
let capturing = false
let lastCapture = -Infinity