Skip to content
Permalink

Comparing changes

This is a direct comparison between two commits made in this repository or its related repositories. View the default comparison for this range or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: stream-labs/desktop
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: f0c03eedd58b24e219d8b53e6a69d7ef1bdb3afd
Choose a base ref
..
head repository: stream-labs/desktop
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: dec57e7ffd21a03dc5d9faa2435762a9e074e97d
Choose a head ref
Showing with 1,433 additions and 265 deletions.
  1. +30 −18 .vscode/launch.json
  2. +1 −1 app/components-react/pages/PlatformMerge.tsx
  3. +2 −2 app/components-react/pages/onboarding/Connect.tsx
  4. +3 −2 app/components-react/shared/Message.tsx
  5. +50 −104 app/components-react/widgets/GameWidget.tsx
  6. +111 −0 app/components-react/widgets/games/ChatWord.tsx
  7. +104 −0 app/components-react/widgets/games/TicTacToe.tsx
  8. +9 −0 app/components-react/widgets/games/index.tsx
  9. +142 −19 app/components-react/windows/GuestCamProperties.tsx
  10. +14 −0 app/components-react/windows/go-live/platforms/TwitchEditStreamInfo.tsx
  11. +1 −7 app/components-react/windows/go-live/useGoLiveSettings.ts
  12. +49 −12 app/components-react/windows/source-showcase/SourceGrid.tsx
  13. +14 −8 app/components-react/windows/source-showcase/SourceShowcase.m.less
  14. +2 −0 app/components-react/windows/source-showcase/SourceTag.tsx
  15. +1 −1 app/components/windows/settings/Settings.vue.ts
  16. +2 −3 app/i18n/ar-SA/grow.json
  17. +27 −1 app/i18n/ar-SA/settings.json
  18. +27 −1 app/i18n/cs-CZ/settings.json
  19. +27 −1 app/i18n/da-DK/settings.json
  20. +27 −1 app/i18n/de-DE/settings.json
  21. +8 −1 app/i18n/en-US/guest-cam.json
  22. +2 −1 app/i18n/en-US/twitch.json
  23. +35 −14 app/i18n/en-US/widget-game.json
  24. +27 −1 app/i18n/es-ES/settings.json
  25. +27 −1 app/i18n/fr-FR/settings.json
  26. +27 −1 app/i18n/hu-HU/settings.json
  27. +27 −1 app/i18n/id-ID/settings.json
  28. +27 −1 app/i18n/it-IT/settings.json
  29. +27 −1 app/i18n/ja-JP/settings.json
  30. +27 −1 app/i18n/ko-KR/settings.json
  31. +27 −1 app/i18n/mk-MK/settings.json
  32. +27 −1 app/i18n/nl-NL/settings.json
  33. +27 −1 app/i18n/pl-PL/settings.json
  34. +27 −1 app/i18n/pt-BR/settings.json
  35. +27 −1 app/i18n/pt-PT/settings.json
  36. +27 −1 app/i18n/ru-RU/settings.json
  37. +27 −1 app/i18n/sk-SK/settings.json
  38. +27 −1 app/i18n/sl-SI/settings.json
  39. +27 −1 app/i18n/sv-SE/settings.json
  40. +27 −1 app/i18n/th-TH/settings.json
  41. +27 −1 app/i18n/tr-TR/settings.json
  42. +27 −1 app/i18n/vi-VN/settings.json
  43. +27 −1 app/i18n/zh-CN/settings.json
  44. +27 −1 app/i18n/zh-TW/settings.json
  45. +1 −0 app/services/dismissables.ts
  46. +107 −16 app/services/guest-cam/index.ts
  47. +6 −1 app/services/guest-cam/producer.ts
  48. +1 −0 app/services/i18n/i18n.ts
  49. +23 −1 app/services/incremental-rollout.ts
  50. +5 −3 app/services/platforms/twitch.ts
  51. +11 −0 app/services/settings/settings.ts
  52. +1 −1 app/services/sources/sources-data.ts
  53. +4 −4 app/services/sources/sources.ts
  54. +2 −1 app/services/usage-statistics.ts
  55. +1 −1 app/services/widgets/widgets-config.ts
  56. +2 −2 package.json
  57. +1 −1 scripts/repositories.json
  58. +8 −11 test/regular/settings/audio.ts
  59. +5 −5 yarn.lock
48 changes: 30 additions & 18 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -1,20 +1,32 @@
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch",
"protocol": "inspector",
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron.cmd",
"osx": {
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron",
},
"runtimeArgs": [
"."
],
"cwd": "${workspaceRoot}",
"outputCapture": "std"
}
]
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch",
"protocol": "inspector",
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron.cmd",
"osx": {
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron"
},
"runtimeArgs": [".", "--remote-debugging-port=9222"],
"cwd": "${workspaceRoot}"
},
{
"type": "chrome",
"request": "attach",
"name": "Attach to Chrome",
"port": 9222,
"webRoot": "${workspaceRoot}",
"sourceMaps": true
}
],
"compounds": [
{
"name": "Electron All",
"configurations": ["Launch", "Attach to Chrome"],
"stopAll": true
}
]
}
2 changes: 1 addition & 1 deletion app/components-react/pages/PlatformMerge.tsx
Original file line number Diff line number Diff line change
@@ -36,7 +36,7 @@ export default function PlatformMerge(p: IPlatformMergeProps) {

async function mergePlatform() {
if (!platform) return;
const mode = platform === 'youtube' ? 'external' : 'internal';
const mode = ['youtube', 'twitch'].includes(platform) ? 'external' : 'internal';
await UserService.actions.return.startAuth(platform, mode, true);

if (p.params.highlighter) {
4 changes: 2 additions & 2 deletions app/components-react/pages/onboarding/Connect.tsx
Original file line number Diff line number Diff line change
@@ -156,7 +156,7 @@ export class LoginModule {
this.UsageStatisticsService.recordAnalyticsEvent('PlatformLogin', platform);
const result = await this.UserService.startAuth(
platform,
platform === 'youtube' ? 'external' : 'internal',
['youtube', 'twitch'].includes(platform) ? 'external' : 'internal',
);

if (result === EPlatformCallResult.TwitchTwoFactor) {
@@ -165,7 +165,7 @@ export class LoginModule {
type: 'error',
message: $t(
'Twitch requires two factor authentication to be enabled on your account in order to stream to Twitch. ' +
'Please enable two factor authentication and try again.',
'Please enable two factor authentication and try again.',
),
title: $t('Twitch Authentication Error'),
buttons: [$t('Enable Two Factor Authentication'), $t('Dismiss')],
5 changes: 3 additions & 2 deletions app/components-react/shared/Message.tsx
Original file line number Diff line number Diff line change
@@ -2,13 +2,14 @@ import React, { HTMLAttributes } from 'react';
import ExclamationCircleOutlined from '@ant-design/icons';

// TODO: add more types
type MessageType = 'warning' | 'info';

export default function Message(p: { type: 'warning' } & HTMLAttributes<unknown>) {
export default function Message(p: { type: MessageType } & HTMLAttributes<unknown>) {
const type = p.type;
const classProp = `ant-message-custom-content ant-message-${type}`;
return (
<div className={classProp}>
<ExclamationCircleOutlined color="orange" /> {p.children}
{type === 'warning' && <ExclamationCircleOutlined color="orange" />} {p.children}
</div>
);
}
154 changes: 50 additions & 104 deletions app/components-react/widgets/GameWidget.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import React, { useState } from 'react';
import React from 'react';
import { IWidgetCommonState, useWidget, WidgetModule } from './common/useWidget';
import { WidgetLayout } from './common/WidgetLayout';
import { $t } from 'services/i18n';
import { metadata } from 'components-react/shared/inputs/metadata';
import { TextInput, ColorInput, SliderInput } from 'components-react/shared/inputs';
import { TextInput, SliderInput, ListInput } from 'components-react/shared/inputs';
import Form from 'components-react/shared/inputs/Form';
import componentMap from './games';
import { Menu } from 'antd';

type TGameType = 'tic-tac-toe';
type TGameType = 'tic-tac-toe' | 'chat-word';

interface ITicTacToeOptions {
export interface ITicTacToeOptions {
background_color: string;
border_color: string;
chat_marker_color: string;
@@ -27,6 +28,23 @@ interface ITicTacToeOptions {
cannot_play_here: string;
}

export interface IChatWordOptions {
character_misplaced_tile_color: string;
character_misplaced_color: string;
character_correct_tile_color: string;
character_correct_color: string;
character_wrong_tile_color: string;
character_wrong_color: string;
chat_won_game_title: string;
chat_won_game_message: string;
chat_lost_game_title: string;
chat_lost_game_message: string;
chat_turn_message: string;
chat_wrong_word_chosen: string;
chat_response_invalid: string;
game_ended_message_duration: number;
}

interface IGameWidgetState extends IWidgetCommonState {
data: {
settings: {
@@ -38,13 +56,27 @@ interface IGameWidgetState extends IWidgetCommonState {
available_games: TGameType[];
game_options: {
'tic-tac-toe': ITicTacToeOptions;
'chat-word': IChatWordOptions;
};
};
};
}

type TGameOptions = ITicTacToeOptions & IChatWordOptions;

function gameOption(key: string) {
const optionTable = {
'tic-tac-toe': $t('Tic Tac Toe'),
'chat-word': $t('Chat Word'),
};

return { label: optionTable[key], value: key };
}

export function GameWidget() {
const { isLoading, bind, selectedTab, setSelectedTab } = useGameWidget();
const { isLoading, bind, selectedTab, setSelectedTab, settings } = useGameWidget();

const availableGames = settings.available_games?.map(gameOption);

return (
<WidgetLayout>
@@ -55,11 +87,12 @@ export function GameWidget() {
<Form>
{!isLoading && selectedTab === 'general' && (
<>
<ListInput label={$t('Current Game')} {...bind.current_game} options={availableGames} />
<SliderInput
label={$t('Chat Decision Time')}
tooltip={{
title: $t(
"The duration in seconds to collect chat's responses before passing them to the game.",
"The duration in seconds to collect chat's responses before passing them to the game",
),
placement: 'bottom',
}}
@@ -68,22 +101,22 @@ export function GameWidget() {
/>
<TextInput
label={$t('Trigger Command')}
tooltip={$t('Command used by the chat to provide their response.')}
tooltip={$t('Command used by the chat to provide their response')}
{...bind.trigger_command}
/>
<TextInput
label={$t('No Input Recieved')}
tooltip={$t("Message displayed to let the chat know they didn't provide any input.")}
tooltip={$t("Message displayed to let the chat know they didn't provide any input")}
{...bind.no_input_received_message}
/>
<TextInput
label={$t('Restarting Game')}
tooltip={$t('Message displayed to let the chat know the game is restarting.')}
tooltip={$t('Message displayed to let the chat know the game is restarting')}
{...bind.restarting_game_message}
/>
</>
)}
{!isLoading && selectedTab === 'game' && <GameOptions game="tic-tac-toe" />}
{!isLoading && selectedTab === 'game' && <GameOptions game={settings.current_game} />}
</Form>
</WidgetLayout>
);
@@ -97,105 +130,18 @@ function useGameWidget() {

function GameOptions(p: { game: TGameType }) {
const { settings, updateSettings } = useGameWidget();
const game = p.game;

function updateGameOption(key: keyof ITicTacToeOptions) {
return (value: unknown) => {
updateSettings({ game_options: { [game]: { [key]: value } } });
updateSettings({ game_options: { [p.game]: { [key]: value } } });
};
}

const GameSettings = componentMap[p.game];

return (
<>
<ColorInput
label={$t('Background Color')}
value={settings.game_options[game].background_color}
onChange={updateGameOption('background_color')}
/>
<ColorInput
label={$t('Border Color')}
value={settings.game_options[game].border_color}
onChange={updateGameOption('border_color')}
/>
<TextInput
label={$t('Chat Marker')}
tooltip={$t(
"Marker used to display where chat played their turn. Please make sure it's not more than 1 character.",
)}
value={settings.game_options[game].chat_marker}
onChange={updateGameOption('chat_marker')}
/>
<TextInput
label={$t("Chat's Turn")}
tooltip={$t("Message to let everyone know that it's chat's turn to play.")}
value={settings.game_options[game].chat_turn_message}
onChange={updateGameOption('chat_turn_message')}
/>
<ColorInput
label={$t('Chat Marker Color')}
value={settings.game_options[game].chat_marker_color}
onChange={updateGameOption('chat_marker_color')}
/>
<ColorInput
label={$t('Chat Win Color')}
value={settings.game_options[game].chat_win_marker_color}
onChange={updateGameOption('chat_win_marker_color')}
/>
<TextInput
label={$t('AI Marker')}
tooltip={$t(
"Marker used to display where AI played it's turn. Please make sure it's not more than 1 character.",
)}
value={settings.game_options[game].ai_marker}
onChange={updateGameOption('ai_marker')}
/>
<TextInput
label={$t("AI's Turn")}
tooltip={$t("Message to let everyone know that it's AI's turn to play.")}
value={settings.game_options[game].ai_turn_message}
onChange={updateGameOption('ai_turn_message')}
/>
<ColorInput
label={$t('AI Marker Color')}
value={settings.game_options[game].ai_marker_color}
onChange={updateGameOption('ai_marker_color')}
/>
<ColorInput
label={$t('AI Win Color')}
value={settings.game_options[game].ai_win_marker_color}
onChange={updateGameOption('ai_win_marker_color')}
/>
<TextInput
label={$t('Chat Won')}
tooltip={$t('Message displayed to let everyone know chat won.')}
value={settings.game_options[game].chat_won_game_message}
onChange={updateGameOption('chat_won_game_message')}
/>
<TextInput
label={$t('Chat Lost')}
tooltip={$t('Message displayed to let everyone know chat lost.')}
value={settings.game_options[game].chat_lost_game_message}
onChange={updateGameOption('chat_lost_game_message')}
/>
<TextInput
label={$t('Draw Game')}
tooltip={$t('Message displayed to let everyone know the game was a draw.')}
value={settings.game_options[game].draw_game_message}
onChange={updateGameOption('draw_game_message')}
/>
<TextInput
label={$t('Cannot Play Here')}
tooltip={$t('Message to let chat know that they cannot play the current move.')}
value={settings.game_options[game].cannot_play_here}
onChange={updateGameOption('cannot_play_here')}
/>
<SliderInput
label={$t('Game End Message Duration')}
tooltip={$t('Display the game ended message for these many seconds.')}
value={settings.game_options[game].game_ended_message_duration}
onChange={updateGameOption('game_ended_message_duration')}
{...metadata.seconds({ min: 3000, max: 5000 })}
/>
</>
<GameSettings
gameSettings={settings.game_options[p.game] as TGameOptions}
updateGameOption={updateGameOption}
/>
);
}
Loading