Make video a per-server toggle instead of an env-wide setting
VIDEO_ENABLED is now permission rather than behaviour: it decides whether the feature exists at all, while turning it on for a server is a toggle in the panel or !video in chat, off by default. Video costs real CPU for every playing channel, so that should be a deliberate choice rather than something a config flag switches on everywhere. With the env flag off the panel renders no toggle at all and !video says so, and the switch applies from the next track — swapping tracks mid-play would cut the current one. The loop button no longer reads "выкл" either: it sat next to the video button showing the same word, so the two states were indistinguishable. Both now name what they do and rely on highlighting for state. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
e06c42f60c
commit
a9b680c418
@@ -183,6 +183,7 @@ export function App() {
|
||||
voiceChannels={voiceChannels}
|
||||
yourVoiceChannel={yourVoiceChannel}
|
||||
requireListener={me.features.requireListener}
|
||||
videoAvailable={me.features.video}
|
||||
onAction={(action, payload) => void runAction(action, payload)}
|
||||
onSeek={(seconds) => void runAction("seek", { position: seconds })}
|
||||
onJoin={(channelId) => {
|
||||
|
||||
@@ -9,6 +9,8 @@ interface Props {
|
||||
voiceChannels: VoiceChannel[];
|
||||
yourVoiceChannel: VoiceChannel | null;
|
||||
requireListener: boolean;
|
||||
/** Hidden entirely when the bot was built without video support. */
|
||||
videoAvailable: boolean;
|
||||
onAction(action: string, payload?: Record<string, unknown>): void;
|
||||
onSeek(seconds: number): void;
|
||||
onJoin(channelId: string | null): void;
|
||||
@@ -23,7 +25,7 @@ const STATUS_LABEL: Record<PlayerState["status"], string> = {
|
||||
};
|
||||
|
||||
const LOOP_LABEL: Record<LoopMode, string> = {
|
||||
off: "🔁 выкл",
|
||||
off: "🔁 повтор",
|
||||
track: "🔂 трек",
|
||||
queue: "🔁 очередь",
|
||||
};
|
||||
@@ -35,6 +37,7 @@ export function NowPlaying({
|
||||
voiceChannels,
|
||||
yourVoiceChannel,
|
||||
requireListener,
|
||||
videoAvailable,
|
||||
onAction,
|
||||
onSeek,
|
||||
onJoin,
|
||||
@@ -141,6 +144,21 @@ export function NowPlaying({
|
||||
{LOOP_LABEL[state.loop]}
|
||||
</button>
|
||||
|
||||
{videoAvailable && (
|
||||
<button
|
||||
className={state.videoEnabled ? "active" : ""}
|
||||
onClick={() => onAction("video", { enabled: !state.videoEnabled })}
|
||||
disabled={!canControl}
|
||||
title={
|
||||
state.videoEnabled
|
||||
? "Клип показывается как демонстрация экрана — нажмите, чтобы выключить"
|
||||
: "Показывать клип как демонстрацию экрана (со следующего трека)"
|
||||
}
|
||||
>
|
||||
📺 видео
|
||||
</button>
|
||||
)}
|
||||
|
||||
<div className="volume">
|
||||
<span title="Громкость">🔊</span>
|
||||
<input
|
||||
|
||||
+2
-1
@@ -26,6 +26,7 @@ export interface PlayerState {
|
||||
history: Track[];
|
||||
volume: number;
|
||||
loop: LoopMode;
|
||||
videoEnabled: boolean;
|
||||
updatedAt: number;
|
||||
}
|
||||
|
||||
@@ -43,7 +44,7 @@ export interface ServerRef {
|
||||
export interface Me {
|
||||
user: { id: string; username: string };
|
||||
servers: ServerRef[];
|
||||
features: { localLibrary: boolean; requireListener: boolean };
|
||||
features: { localLibrary: boolean; requireListener: boolean; video: boolean };
|
||||
}
|
||||
|
||||
export interface ServerStateResponse {
|
||||
|
||||
Reference in New Issue
Block a user