Skip to content

Commit 68dafeb

Browse files
23Kevclaudetariknz
authored
feat: add Twitch Chat overlay widget (#340)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: tariknz <tarik.nzl@gmail.com>
1 parent 2bde8c6 commit 68dafeb

36 files changed

+2139
-1178
lines changed

package-lock.json

Lines changed: 28 additions & 27 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@
8787
"license": "MIT",
8888
"dependencies": {
8989
"@phosphor-icons/react": "^2.1.10",
90+
"@tmi.js/chat": "^0.7.4",
9091
"d3": "^7.9.0",
9192
"electron-squirrel-startup": "^1.0.1",
9293
"flag-icons": "^7.5.0",

src/app/storage/defaultDashboard.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -838,6 +838,24 @@ export const defaultDashboard: DashboardLayout = {
838838
background: { opacity: 80 },
839839
},
840840
},
841+
{
842+
id: 'twitchchat',
843+
alwaysEnabled: true,
844+
enabled: false,
845+
layout: {
846+
x: 378,
847+
y: 102,
848+
width: 400,
849+
height: 500,
850+
},
851+
config: {
852+
fontSize: 16,
853+
channel: '',
854+
background: {
855+
opacity: 30,
856+
},
857+
},
858+
},
841859
],
842860
generalSettings: {
843861
fontSize: 'sm',

src/frontend/WidgetIndex.tsx

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,16 @@ import { GarageCover } from './components/GarageCover/GarageCover';
1111
import { RejoinIndicator } from './components/RejoinIndicator/RejoinIndicator';
1212
import { TelemetryInspector } from './components/TelemetryInspector/TelemetryInspector';
1313
import { PitlaneHelper } from './components/PitlaneHelper/PitlaneHelper';
14-
import { Flag } from './components/Flag';
14+
import { Flag } from './components/Flag';
15+
import { TwitchChat } from './components/TwitchChat/TwitchChat';
1516

1617
// TODO: type this better, right now the config comes from settings
17-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
18-
export const WIDGET_MAP: Record<string, (config?: any) => React.JSX.Element | null> = {
18+
/* eslint-disable @typescript-eslint/no-explicit-any */
19+
export const WIDGET_MAP: Record<
20+
string,
21+
(config?: any) => React.JSX.Element | null
22+
> = {
23+
/* eslint-enable @typescript-eslint/no-explicit-any */
1924
standings: Standings,
2025
input: Input,
2126
relative: Relative,
@@ -30,6 +35,7 @@ export const WIDGET_MAP: Record<string, (config?: any) => React.JSX.Element | nu
3035
telemetryinspector: TelemetryInspector,
3136
pitlanehelper: PitlaneHelper,
3237
flag: Flag,
38+
twitchchat: TwitchChat,
3339
};
3440

3541
export type WidgetId = keyof typeof WIDGET_MAP;

src/frontend/components/OverlayContainer/OverlayContainer.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,9 @@ export const OverlayContainer = memo(() => {
9696
zIndex={index + 1}
9797
onLayoutChange={handleLayoutChange}
9898
>
99-
{running ? <WidgetComponent {...widget.config} /> : null}
99+
{running || widget.alwaysEnabled ? (
100+
<WidgetComponent {...widget.config} />
101+
) : null}
100102
</WidgetContainer>
101103
);
102104
})}

src/frontend/components/Settings/SettingsLoader.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { GarageCoverSettings } from './sections/GarageCoverSettings';
1717
import { ProfileSettings } from './sections/ProfileSettings';
1818
import { FlagSettings } from './sections/FlagSettings';
1919
import { CarSetupSettings } from './sections/CarSetupSettings';
20+
import { TwitchChatSettings } from './sections/TwitchChatSettings';
2021
import { useDashboard } from '@irdashies/context';
2122

2223
export const SettingsLoader = () => {
@@ -61,6 +62,8 @@ export const SettingsLoader = () => {
6162
return <GarageCoverSettings />;
6263
case 'flag':
6364
return <FlagSettings />;
65+
case 'twitchchat':
66+
return <TwitchChatSettings />;
6467
default:
6568
return widget ? (
6669
<div className="text-red-400">No settings available for {type}</div>

src/frontend/components/Settings/SettingsMenu.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,14 @@ export const SettingsMenu = () => {
108108
Track Map
109109
</Link>
110110
</li>
111+
<li>
112+
<Link
113+
to="/settings/twitchchat"
114+
className={menuItemClass('/twitchchat')}
115+
>
116+
Twitch Chat
117+
</Link>
118+
</li>
111119
<li>
112120
<Link to="/settings/weather" className={menuItemClass('/weather')}>
113121
Weather

src/frontend/components/Settings/components/TabButton.stories.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@ type Story = StoryObj<typeof TabButton>;
1313

1414
export const Interactive: Story = {
1515
render: () => {
16-
const [activeTab, setActiveTab] =
17-
useState<SettingsTabType>('layout');
16+
const [activeTab, setActiveTab] = useState<SettingsTabType>('layout');
1817

1918
return (
2019
<div className="bg-slate-900 p-6 flex gap-4">
@@ -44,4 +43,4 @@ export const Interactive: Story = {
4443
</div>
4544
);
4645
},
47-
};
46+
};

0 commit comments

Comments
 (0)