mirror of
https://github.com/Boof2015/prism.git
synced 2026-08-12 05:10:51 +02:00
114 lines
3.4 KiB
TypeScript
114 lines
3.4 KiB
TypeScript
import { mkdir, readFile, writeFile } from 'node:fs/promises'
|
|
import { dirname } from 'node:path'
|
|
import { createEmptyWindowLocalState, normalizeWindowLocalState } from '../shared/windowState'
|
|
import type { WindowBounds } from '../types/popout'
|
|
import type { ScopeKind } from '../types/scope'
|
|
import type { PrismWindowLocalStateV1, WindowBackgroundState } from '../types/windowState'
|
|
|
|
export class FileBackedWindowStateStore {
|
|
private state: PrismWindowLocalStateV1 = createEmptyWindowLocalState()
|
|
private initialized = false
|
|
private writeChain: Promise<void> = Promise.resolve()
|
|
|
|
constructor(private readonly localStatePath: string) {}
|
|
|
|
async initialize(): Promise<void> {
|
|
if (this.initialized) return
|
|
this.state = await this.readLocalState()
|
|
this.initialized = true
|
|
}
|
|
|
|
getMainAlwaysOnTop(): boolean {
|
|
return this.state.mainAlwaysOnTop
|
|
}
|
|
|
|
getPopoutAlwaysOnTop(kind: ScopeKind): boolean {
|
|
return this.state.popoutAlwaysOnTop[kind] === true
|
|
}
|
|
|
|
getWindowBackground(): WindowBackgroundState {
|
|
return { ...this.state.windowBackground }
|
|
}
|
|
|
|
getNowPlayingConfigWindowBounds(): WindowBounds | undefined {
|
|
return this.state.nowPlayingConfigWindowBounds
|
|
? { ...this.state.nowPlayingConfigWindowBounds }
|
|
: undefined
|
|
}
|
|
|
|
async setMainAlwaysOnTop(alwaysOnTop: boolean): Promise<void> {
|
|
await this.ensureInitialized()
|
|
this.state = normalizeWindowLocalState({
|
|
...this.state,
|
|
mainAlwaysOnTop: alwaysOnTop,
|
|
popoutAlwaysOnTop: { ...this.state.popoutAlwaysOnTop },
|
|
})
|
|
await this.persistState()
|
|
}
|
|
|
|
async setPopoutAlwaysOnTop(kind: ScopeKind, alwaysOnTop: boolean): Promise<void> {
|
|
await this.ensureInitialized()
|
|
|
|
const popoutAlwaysOnTop = { ...this.state.popoutAlwaysOnTop }
|
|
if (alwaysOnTop) {
|
|
popoutAlwaysOnTop[kind] = true
|
|
} else {
|
|
delete popoutAlwaysOnTop[kind]
|
|
}
|
|
|
|
this.state = normalizeWindowLocalState({
|
|
...this.state,
|
|
popoutAlwaysOnTop,
|
|
})
|
|
await this.persistState()
|
|
}
|
|
|
|
async setWindowBackground(background: WindowBackgroundState): Promise<void> {
|
|
await this.ensureInitialized()
|
|
this.state = normalizeWindowLocalState({
|
|
...this.state,
|
|
windowBackground: background,
|
|
popoutAlwaysOnTop: { ...this.state.popoutAlwaysOnTop },
|
|
})
|
|
await this.persistState()
|
|
}
|
|
|
|
async setNowPlayingConfigWindowBounds(bounds?: WindowBounds): Promise<void> {
|
|
await this.ensureInitialized()
|
|
this.state = normalizeWindowLocalState({
|
|
...this.state,
|
|
nowPlayingConfigWindowBounds: bounds,
|
|
})
|
|
await this.persistState()
|
|
}
|
|
|
|
private async ensureInitialized(): Promise<void> {
|
|
if (!this.initialized) {
|
|
await this.initialize()
|
|
}
|
|
}
|
|
|
|
private async readLocalState(): Promise<PrismWindowLocalStateV1> {
|
|
try {
|
|
const raw = await readFile(this.localStatePath, 'utf8')
|
|
return normalizeWindowLocalState(JSON.parse(raw) as unknown)
|
|
} catch {
|
|
return createEmptyWindowLocalState()
|
|
}
|
|
}
|
|
|
|
private async persistState(): Promise<void> {
|
|
const state = normalizeWindowLocalState(this.state)
|
|
const payload = `${JSON.stringify(state, null, 2)}\n`
|
|
|
|
this.writeChain = this.writeChain
|
|
.catch(() => {})
|
|
.then(async () => {
|
|
await mkdir(dirname(this.localStatePath), { recursive: true })
|
|
await writeFile(this.localStatePath, payload, 'utf8')
|
|
})
|
|
|
|
await this.writeChain
|
|
}
|
|
}
|