Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7fc42b32d4 |
@@ -50,14 +50,6 @@ type FlatClip = {
|
||||
* A management toggle reveals the pack editors (personal + this room, if
|
||||
* permitted). Space-wide packs are managed from Space settings.
|
||||
*/
|
||||
/** [EC#13, EC#47] Why the fork refused to play a clip, for the user. */
|
||||
export const soundboardRefusalText = (reason: string | undefined): string => {
|
||||
if (reason === 'muted') return 'Unmute your microphone to play a soundboard clip.';
|
||||
if (reason === 'not_permitted')
|
||||
return "The soundboard isn't available in this voice channel (only microphone audio is allowed here).";
|
||||
return 'Could not play that clip.';
|
||||
};
|
||||
|
||||
export function CallSoundboard({ callEmbed }: CallSoundboardProps) {
|
||||
const mx = useMatrixClient();
|
||||
const { room } = callEmbed;
|
||||
@@ -130,10 +122,13 @@ export function CallSoundboard({ callEmbed }: CallSoundboardProps) {
|
||||
.catch(() => undefined);
|
||||
const result = await callEmbed.control.injectAudio(url, vol, clipBytes);
|
||||
if (!result.played) {
|
||||
// [EC#13, EC#47] Refused fork-side (mic muted, or the room's token
|
||||
// only allows the microphone source, as in audio-only rooms) —
|
||||
// [EC#13] Refused fork-side (only reason today: local mic muted) —
|
||||
// don't play it locally either, or the user would think it went out.
|
||||
setError(soundboardRefusalText(result.reason));
|
||||
setError(
|
||||
result.reason === 'muted'
|
||||
? 'Unmute your microphone to play a soundboard clip.'
|
||||
: 'Could not play that clip.',
|
||||
);
|
||||
done();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
import { test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { shouldShowScreenshareNotice } from './useScreenshareNotices';
|
||||
|
||||
test('shouldShowScreenshareNotice: no "window was closed" when an admin turned sharing off (#297)', () => {
|
||||
assert.equal(shouldShowScreenshareNotice('ended', false), false);
|
||||
assert.equal(shouldShowScreenshareNotice('ended', true), true);
|
||||
assert.equal(shouldShowScreenshareNotice('no-frames', false), true);
|
||||
assert.equal(shouldShowScreenshareNotice('alone', true), true);
|
||||
});
|
||||
@@ -1,8 +1,9 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { useSetAtom } from 'jotai';
|
||||
import { Icons } from 'folds';
|
||||
import { CallEmbed } from '../plugins/call';
|
||||
import { toastQueueAtom } from '../state/toast';
|
||||
import { useRoomCallPolicy } from './useRoomCallPolicy';
|
||||
|
||||
export type ScreenshareNoticeKind = 'ended' | 'no-frames' | 'alone';
|
||||
|
||||
@@ -19,18 +20,32 @@ export const describeScreenshareNotice = (kind: ScreenshareNoticeKind): string |
|
||||
}
|
||||
};
|
||||
|
||||
/** Pure: a policy-forced stop is explained by its own toast (#297). */
|
||||
export const shouldShowScreenshareNotice = (
|
||||
kind: ScreenshareNoticeKind,
|
||||
allowScreenshare: boolean,
|
||||
): boolean => !(kind === 'ended' && !allowScreenshare);
|
||||
|
||||
/**
|
||||
* [Gitea EC#39] Toast the fork's io.lotus.screenshare_notice: shared window
|
||||
* closed, no frames for a while, or a long share with nobody watching.
|
||||
*/
|
||||
export function useScreenshareNotices(embed: CallEmbed): void {
|
||||
const setToast = useSetAtom(toastQueueAtom);
|
||||
// [Gitea #297] When a room admin turns screen sharing off, the share ends
|
||||
// and the fork reports `ended` ("the shared window was closed"), which is
|
||||
// wrong; useCallPolicyRevokedToast already says what happened.
|
||||
const { allowScreenshare } = useRoomCallPolicy(embed.room);
|
||||
const allowRef = useRef(allowScreenshare);
|
||||
allowRef.current = allowScreenshare;
|
||||
useEffect(
|
||||
() =>
|
||||
embed.listenAction<{ data?: { kind?: ScreenshareNoticeKind } }>(
|
||||
'io.lotus.screenshare_notice',
|
||||
(evt) => {
|
||||
const body = describeScreenshareNotice(evt.detail?.data?.kind as ScreenshareNoticeKind);
|
||||
const kind = evt.detail?.data?.kind as ScreenshareNoticeKind;
|
||||
if (!shouldShowScreenshareNotice(kind, allowRef.current)) return;
|
||||
const body = describeScreenshareNotice(kind);
|
||||
if (!body) return;
|
||||
setToast({
|
||||
id: `screenshare-${evt.detail?.data?.kind}-${Date.now()}`,
|
||||
|
||||
Reference in New Issue
Block a user