Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 7 additions & 13 deletions app/components-react/root/StartStreamingButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,11 @@ function StartStreamingButton(p: { disabled?: boolean }) {

if (!primaryPlatform) return false;

// In unprotected mode, only a Twitch ingest url can show the Go Live window. This is for legacy reasons.
if (!StreamSettingsService.state.protectedModeEnabled) {
return isTwitchUnprotectedStream && updateStreamInfoOnLive;
Comment thread
michelinewu marked this conversation as resolved.
}

if (streamShiftStatus === 'pending') {
return true;
}
Expand All @@ -219,21 +224,10 @@ function StartStreamingButton(p: { disabled?: boolean }) {
return true;
}

// For Twitch, there are two cases to check for the ability to show the Go Live window:
// 1. In protected mode: when Twitch is the primary platform
// 2. In unprotected mode: when the ingest url is for Twitch. The unprotected mode behavior for Twitch is for legacy reasons
if (
(StreamSettingsService.state.protectedModeEnabled && primaryPlatform === 'twitch') ||
isTwitchUnprotectedStream
) {
// For Twitch, we can show the Go Live window even with protected mode off
// This is mainly for legacy reasons.
if (primaryPlatform === 'twitch') {
return isMultiplatformMode || updateStreamInfoOnLive;
} else {
return (
StreamSettingsService.state.protectedModeEnabled &&
StreamSettingsService.isSafeToModifyStreamKey()
);
return StreamSettingsService.isSafeToModifyStreamKey();
}
}, [
primaryPlatform,
Expand Down
1 change: 1 addition & 0 deletions app/services/streaming/stream-destination.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export function isCommonTwitchService(destination: IStreamDestination): boolean
export function isTwitchStreamDestination(destination: IStreamDestination): boolean {
if (destination.streamType === 'rtmp_common') return isCommonTwitchService(destination);
if (destination.streamType !== 'rtmp_custom' || !destination.server) return false;
if (destination.server.trim().toLowerCase() === 'auto') return true;

try {
// Electron's browser URL parser treats RTMP URLs as opaque and has no hostname.
Expand Down
7 changes: 2 additions & 5 deletions app/services/streaming/streaming-view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ export class StreamInfoView<T extends Object> extends ViewHandler<T> {
return (
!this.protectedModeEnabled &&
this.userView.isLoggedIn &&
this.isPrimaryPlatform('twitch') &&
this.isPlatformLinked('twitch') &&
Comment thread
michelinewu marked this conversation as resolved.
isTwitchStreamDestination(this.streamSettingsView.settings)
);
}
Expand Down Expand Up @@ -1165,9 +1165,6 @@ export class StreamInfoView<T extends Object> extends ViewHandler<T> {
}

get showFeatureToggleCards() {
if (!this.incrementalRolloutView.featureIsEnabled(EAvailableFeatures.liveOutputEditing)) {
return false;
}
return !this.isMidStreamMode;
return this.protectedModeEnabled && !this.isMidStreamMode;
Comment thread
michelinewu marked this conversation as resolved.
}
}
39 changes: 20 additions & 19 deletions test/regular/settings/streaming.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
import { showSettingsWindow } from '../../helpers/modules/settings/settings';
import { click, clickButton, waitForDisplayed } from '../../helpers/modules/core';
import { assertFormContains, fillForm, readFields } from '../../helpers/modules/forms';
import { sleep } from '../../helpers/sleep';
Comment thread
Copilot marked this conversation as resolved.
Outdated

// not a react hook
// eslint-disable-next-line react-hooks/rules-of-hooks
Expand Down Expand Up @@ -43,26 +44,41 @@ test('Populates stream settings after go live', withUser('twitch'), async t => {
);
await stopStream();

// Validate that the stream key persists when switching types and back to recommended settings
await showSettingsWindow('Stream', async () => {
// Validate that the stream key resets when switching from Streaming Services to Custom Streaming Server
await fillForm({ streamType: 'Streaming Services' });
await waitForDisplayed('label=Service');
const fields2 = (await readFields()) as Record<string, string>;
t.is(fields2.key, key, 'Stream key should persist when switching types');
t.is(
fields2.key,
'',
'Stream key should reset when switching from Streaming Services to Custom Streaming Server',
);
await fillForm({ key });

// Switch back to Custom Streaming Server type and validate that the stream key is still present
// Validate that the stream key persists when switching from Streaming Services to Custom Streaming Server
await fillForm({ streamType: 'Custom Streaming Server' });
await waitForDisplayed('label=URL');
const fields3 = (await readFields()) as Record<string, string>;
t.is(
fields3.key,
key,
'Stream key should persist when switching back to Custom Streaming Server type',
'Stream key should persist when switching from Streaming Services to Custom Streaming Server',
);

// Can switch back to recommended settings, which will restore protected mode
await clickButton('Use recommended settings');
await waitForDisplayed('a=Stream to custom ingest', {
timeout: 5000,
timeoutMsg: 'Switched back to protected mode',
});

await clickButton('Close');
});

await goLive();
await stopStream();

// TODO: Validate non-Twitch target
// await showSettingsWindow('Stream', async () => {
// await fillForm({ streamType: 'Custom Streaming Server' });
Expand All @@ -73,21 +89,6 @@ test('Populates stream settings after go live', withUser('twitch'), async t => {
// await clickGoLive();
// t.false(await chatIsVisible(), 'Chat should be collapsed when going live in unprotected mode ');
// await stopStream();

// Can switch back to protected mode
await showSettingsWindow('Stream', async () => {
// Can switch back to recommended settings
await clickButton('Use recommended settings');
await waitForDisplayed('a=Stream to custom ingest', {
timeout: 5000,
timeoutMsg: 'Recommended settings should restore protected mode',
});

await clickButton('Close');
});

await goLive();
await stopStream();
});

test('Populates stream key after go live', async t => {
Expand Down
2 changes: 1 addition & 1 deletion test/regular/streaming/twitch-stream-destination.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ const destinations = [
name: 'unresolved automatic selection',
streamType: 'rtmp_custom',
server: 'auto',
twitch: false,
twitch: true,
enhanced: false,
},
{ name: 'empty server', streamType: 'rtmp_custom', server: '', twitch: false, enhanced: false },
Expand Down
7 changes: 5 additions & 2 deletions test/regular/streaming/twitch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,11 +116,14 @@ test('Migrate the twitch account to the protected mode', async t => {
});
// TODO: Add validation that the destination switchers in the go live window are hidden (requires multistream test account)
// TODO: Add validation that the Twitch edit stream form in the go live window is the only form (requires multistream test account)
await waitForStreamStop();
await stopStream();

// check that settings have been switched to the Custom Ingest mode
await showSettingsWindow('Stream');
t.true(await isDisplayed('button=Use recommended settings'), 'Protected mode should be disabled');
t.false(
await isDisplayed('button=Use recommended settings'),
'Protected mode should be disabled',
);
});

// TODO: Re-enable after reauthing userpool
Expand Down
Loading