Feat : STRCHA Stream status

This commit is contained in:
jeanotx32
2026-08-11 00:52:33 +02:00
parent 6f11b72cbb
commit b529417940
13 changed files with 1038 additions and 14 deletions

View File

@@ -1,5 +1,5 @@
import { useState } from 'react';
import type { AgentAction, AgentView } from '@stream-control/shared';
import type { AgentAction, AgentView, WatchSettings } from '@stream-control/shared';
import { api } from '../api';
interface Props {
@@ -19,6 +19,15 @@ export function AgentSettings({ agent, onClose, onCommand, notify }: Props) {
const [directory, setDirectory] = useState(agent.status.recordDirectory ?? '');
const [token, setToken] = useState<string | null>(null);
const [busy, setBusy] = useState(false);
const [watch, setWatch] = useState<WatchSettings>(agent.watch);
function patchWatch(patch: Partial<WatchSettings>) {
setWatch((current) => ({ ...current, ...patch }));
}
function patchFullscreen(patch: Partial<WatchSettings['fullscreen']>) {
setWatch((current) => ({ ...current, fullscreen: { ...current.fullscreen, ...patch } }));
}
async function save() {
setBusy(true);
@@ -28,6 +37,7 @@ export function AgentSettings({ agent, onClose, onCommand, notify }: Props) {
notes,
autoConnectObs: autoConnect,
obs: { host, port: Number(port), password },
watch,
} as Partial<AgentView>);
notify('Configuration enregistrée');
onClose();
@@ -129,6 +139,127 @@ export function AgentSettings({ agent, onClose, onCommand, notify }: Props) {
</button>
</div>
<fieldset className="group">
<legend>Surveillance du stream</legend>
<label className="checkbox">
<input
type="checkbox"
checked={watch.enabled}
onChange={(event) => patchWatch({ enabled: event.target.checked })}
/>
<span>Mettre l'enregistrement en pause pendant les shows privés</span>
</label>
<div className="row">
<label className="field small-field">
<span>Plateforme</span>
<select
value={watch.provider}
onChange={(event) =>
patchWatch({ provider: event.target.value as WatchSettings['provider'] })
}
>
<option value="stripchat">Stripchat</option>
</select>
</label>
<label className="field grow">
<span>Pseudo du streamer</span>
<input
value={watch.username}
onChange={(event) => patchWatch({ username: event.target.value })}
placeholder="tel qu'il apparaît dans l'URL"
/>
</label>
</div>
<div className="row">
<label className="field grow">
<span>Intervalle de sonde (s)</span>
<input
value={String(Math.round(watch.pollIntervalMs / 1000))}
onChange={(event) =>
patchWatch({ pollIntervalMs: (Number(event.target.value) || 10) * 1000 })
}
inputMode="numeric"
/>
</label>
<label className="field grow">
<span>Lectures avant pause</span>
<input
value={String(watch.confirmations)}
onChange={(event) => patchWatch({ confirmations: Number(event.target.value) || 1 })}
inputMode="numeric"
/>
</label>
</div>
<label className="field">
<span>Statuts considérés comme « privé »</span>
<input
value={watch.privateStatuses.join(', ')}
onChange={(event) =>
patchWatch({
privateStatuses: event.target.value
.split(',')
.map((entry) => entry.trim())
.filter(Boolean),
})
}
/>
<span className="muted small">
Statuts renvoyés par Stripchat : public, private, p2p, groupShow, idle. Retire
groupShow si tu veux continuer à enregistrer les shows de groupe.
</span>
</label>
<label className="checkbox">
<input
type="checkbox"
checked={watch.fullscreen.enabled}
onChange={(event) => patchFullscreen({ enabled: event.target.checked })}
/>
<span>Rappeler le plein écran à la fin du show privé</span>
</label>
<div className="row">
<label className="field small-field">
<span>Touche</span>
<input
value={watch.fullscreen.key}
onChange={(event) => patchFullscreen({ key: event.target.value })}
/>
</label>
<label className="field grow">
<span>Titre de la fenêtre du lecteur</span>
<input
value={watch.fullscreen.windowMatch}
onChange={(event) => patchFullscreen({ windowMatch: event.target.value })}
placeholder="fragment du titre, ex. Stripchat"
/>
</label>
<label className="field small-field">
<span>Délai (s)</span>
<input
value={String(Math.round(watch.fullscreen.delayMs / 1000))}
onChange={(event) =>
patchFullscreen({ delayMs: (Number(event.target.value) || 0) * 1000 })
}
inputMode="numeric"
/>
</label>
</div>
<div className="row">
<button className="ghost" onClick={() => void onCommand(agent.id, 'watch.check')}>
Sonder maintenant
</button>
<button className="ghost" onClick={() => void onCommand(agent.id, 'hotkey.fullscreen')}>
Tester le plein écran
</button>
</div>
</fieldset>
<div className="danger-zone">
<div>
<strong>Jeton d'agent</strong>