Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor for flow #5281

Merged
merged 6 commits into from
Jan 11, 2025
Merged
Changes from all 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
6 changes: 3 additions & 3 deletions app/app-services.ts
Original file line number Diff line number Diff line change
@@ -74,11 +74,11 @@ export {
export { FacebookService } from 'services/platforms/facebook';
export { TikTokService } from 'services/platforms/tiktok';
export { TrovoService } from 'services/platforms/trovo';
export { KickService } from 'services/platforms/kick';
export { RestreamService } from 'services/restream';
export { TwitterService } from 'services/integrations/twitter';
export { TwitterPlatformService } from 'services/platforms/twitter';
export { InstagramService } from 'services/platforms/instagram';
export { KickService } from 'services/platforms/kick';
export { UsageStatisticsService } from './services/usage-statistics';
export { GameOverlayService } from 'services/game-overlay';
export { SharedStorageService } from 'services/integrations/shared-storage';
@@ -206,10 +206,10 @@ import { MarkersService } from 'services/markers';
import { SharedStorageService } from 'services/integrations/shared-storage';
import { RealmService } from 'services/realm';
import { InstagramService } from 'services/platforms/instagram';
import { KickService } from 'services/platforms/kick';
import { TwitchStudioImporterService } from 'services/ts-importer';
import { RemoteControlService } from 'services/api/remote-control-api';
import { UrlService } from 'services/hosts';
import { KickService } from 'services/platforms/kick';

export const AppServices = {
AppService,
@@ -242,8 +242,8 @@ export const AppServices = {
TwitchTagsService,
TwitchContentClassificationService,
TrovoService,
InstagramService,
KickService,
InstagramService,
DismissablesService,
HighlighterService,
GrowService,
10 changes: 7 additions & 3 deletions app/components-react/pages/onboarding/Connect.tsx
Original file line number Diff line number Diff line change
@@ -63,7 +63,7 @@ export function Connect() {
// streamlabs and trovo are added separarely on markup below
const platforms = RecordingModeService.views.isRecordingModeEnabled
? ['youtube']
: ['twitch', 'youtube', 'facebook', 'twitter', 'tiktok'];
: ['twitch', 'youtube', 'tiktok', 'kick', 'facebook', 'twitter'];

const shouldAddTrovo = !RecordingModeService.views.isRecordingModeEnabled;

@@ -132,7 +132,9 @@ export function Connect() {
loading={loading}
onClick={() => authPlatform(platform, afterLogin)}
key={platform}
logoSize={['twitter', 'tiktok', 'youtube'].includes(platform) ? 15 : undefined}
logoSize={
['twitter', 'tiktok', 'youtube', 'kick'].includes(platform) ? 15 : undefined
}
>
<Translate
message={$t('Log in with <span>%{platform}</span>', {
@@ -263,7 +265,9 @@ export class LoginModule {

const result = await this.UserService.startAuth(
platform,
['youtube', 'twitch', 'twitter', 'tiktok'].includes(platform) ? 'external' : 'internal',
['youtube', 'twitch', 'twitter', 'tiktok', 'kick'].includes(platform)
? 'external'
: 'internal',
merge,
);

Original file line number Diff line number Diff line change
@@ -22,7 +22,7 @@ export function PrimaryPlatformSelect() {
isPrime: UserService.state.isPrime,
}));
const { loading, authInProgress, authPlatform, finishSLAuth } = useModule(LoginModule);
const platforms = ['twitch', 'youtube', 'facebook', 'twitter', 'tiktok', 'trovo'];
const platforms = ['twitch', 'youtube', 'tiktok', 'kick', 'facebook', 'twitter', 'trovo'];
const platformOptions = [
{
value: 'twitch',
@@ -54,6 +54,11 @@ export function PrimaryPlatformSelect() {
label: 'TikTok',
image: <PlatformLogo platform="tiktok" size={14} />,
},
{
value: 'kick',
label: 'Kick',
image: <PlatformLogo platform="kick" size={14} />,
},
].filter(opt => {
return linkedPlatforms.includes(opt.value as TPlatform);
});
37 changes: 7 additions & 30 deletions app/components-react/root/LiveDock.tsx
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@ import React, { useEffect, useMemo, useState } from 'react';
import * as remote from '@electron/remote';
import cx from 'classnames';
import Animation from 'rc-animate';
import { Button, Menu } from 'antd';
import { Menu } from 'antd';
import pick from 'lodash/pick';
import { initStore, useController } from 'components-react/hooks/zustand';
import { EStreamingState } from 'services/streaming';
@@ -27,6 +27,7 @@ class LiveDockController {
private youtubeService = Services.YoutubeService;
private facebookService = Services.FacebookService;
private trovoService = Services.TrovoService;
private kickService = Services.KickService;
private tiktokService = Services.TikTokService;
private userService = Services.UserService;
private customizationService = Services.CustomizationService;
@@ -159,6 +160,7 @@ class LiveDockController {
// Twitter & Tiktok don't support editing title after going live
if (this.isPlatform('twitter') && !this.isRestreaming) return false;
if (this.isPlatform('tiktok') && !this.isRestreaming) return false;
if (this.isPlatform('kick') && !this.isRestreaming) return false;

return (
this.streamingService.views.isMidStreamMode ||
@@ -181,6 +183,7 @@ class LiveDockController {
if (this.platform === 'youtube') url = this.youtubeService.streamPageUrl;
if (this.platform === 'facebook') url = this.facebookService.streamPageUrl;
if (this.platform === 'trovo') url = this.trovoService.streamPageUrl;
if (this.platform === 'kick') url = this.kickService.streamPageUrl;
if (this.platform === 'tiktok') url = this.tiktokService.streamPageUrl;
remote.shell.openExternal(url);
}
@@ -190,6 +193,7 @@ class LiveDockController {
if (this.platform === 'youtube') url = this.youtubeService.dashboardUrl;
if (this.platform === 'facebook') url = this.facebookService.streamDashboardUrl;
if (this.platform === 'tiktok') url = this.tiktokService.dashboardUrl;
if (this.platform === 'kick') url = this.kickService.dashboardUrl;
remote.shell.openExternal(url);
}

@@ -356,33 +360,6 @@ function LiveDock(p: { onLeft: boolean }) {
return <></>;
}

const showKickInfo =
visibleChat === 'kick' || (visibleChat === 'default' && primaryChat === 'kick');
if (showKickInfo) {
return (
<div
style={{
display: 'flex',
flexDirection: 'column',
marginTop: '30px',
}}
>
<div style={{ marginBottom: '5px' }}>
{$t('Access chat for Kick in the Stream Dashboard.')}
</div>
<Button
style={{
width: '200px',
marginBottom: '10px',
}}
onClick={() => remote.shell.openExternal(Services.KickService.chatUrl)}
>
{$t('Open Kick Chat')}
</Button>
</div>
);
}

return (
<Chat
restream={isRestreaming && visibleChat === 'restream'}
@@ -446,7 +423,7 @@ function LiveDock(p: { onLeft: boolean }) {
<i onClick={() => ctrl.showEditStreamInfo()} className="icon-edit" />
</Tooltip>
)}
{isPlatform(['youtube', 'facebook', 'trovo', 'tiktok']) && isStreaming && (
{isPlatform(['youtube', 'facebook', 'trovo', 'tiktok', 'kick']) && isStreaming && (
<Tooltip
title={$t('View your live stream in a web browser')}
placement="right"
@@ -467,7 +444,7 @@ function LiveDock(p: { onLeft: boolean }) {
)}
</div>
<div className="flex">
{(isPlatform(['twitch', 'trovo', 'facebook']) ||
{(isPlatform(['twitch', 'trovo', 'facebook', 'kick']) ||
(isPlatform(['youtube', 'twitter']) && isStreaming) ||
(isPlatform(['tiktok']) && isRestreaming)) && (
<a onClick={() => ctrl.refreshChat()}>{$t('Refresh Chat')}</a>
3 changes: 1 addition & 2 deletions app/components-react/sidebar/NavTools.tsx
Original file line number Diff line number Diff line change
@@ -80,9 +80,8 @@ export default function SideNav() {
const throttledOpenDashboard = throttle(openDashboard, 2000, { trailing: false });

// Instagram doesn't provide a username, since we're not really linked, pass undefined for a generic logout msg w/o it
// Kick doesn't provide a username, since we're not really linked, pass undefined for a generic logout msg w/o it
const username =
isLoggedIn && !['instagram', 'kick'].includes(UserService.views.auth!.primaryPlatform)
isLoggedIn && UserService.views.auth!.primaryPlatform !== 'instagram'
? UserService.username
: undefined;

7 changes: 6 additions & 1 deletion app/components-react/sidebar/PlatformIndicator.m.less
Original file line number Diff line number Diff line change
@@ -11,7 +11,12 @@
&-facebook {
color: var(--facebook) !important;
}
&-trovo, &-twitter, &-tiktok, &-instagram, &-youtube, &-kick {
&-trovo,
&-twitter,
&-tiktok,
&-instagram,
&-youtube,
&-kick {
width: 15px;
height: 15px;
}
3 changes: 1 addition & 2 deletions app/components-react/sidebar/PlatformIndicator.tsx
Original file line number Diff line number Diff line change
@@ -46,8 +46,7 @@ export default function PlatformIndicator({ platform }: IPlatformIndicatorProps)
}

const SinglePlatformIndicator = ({ platform }: Pick<IPlatformIndicatorProps, 'platform'>) => {
const username =
platform?.type === 'instagram' || platform?.type === 'kick' ? undefined : platform?.username;
const username = platform?.type === 'instagram' ? undefined : platform?.username;

return (
<>
19 changes: 14 additions & 5 deletions app/components-react/windows/go-live/CommonPlatformFields.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { TPlatform } from '../../../services/platforms';
import { $t } from '../../../services/i18n';
import React from 'react';
import React, { useMemo } from 'react';
import { CheckboxInput, InputComponent, TextAreaInput, TextInput } from '../../shared/inputs';
import { assertIsDefined } from '../../../util/properties-type-guards';
import InputWrapper from '../../shared/inputs/InputWrapper';
@@ -90,6 +90,18 @@ export const CommonPlatformFields = InputComponent((rawProps: IProps) => {
maxCharacters = 140;
}

const titleTooltip = useMemo(() => {
if (enabledPlatforms.includes('tiktok')) {
return $t('Only 32 characters of your title will display on TikTok');
}

if (enabledPlatforms.length === 1 && p?.platform === 'kick') {
return $t('Edit your stream title on Kick after going live.');
}

return undefined;
}, [enabledPlatforms]);

return (
<div>
{/* USE CUSTOM CHECKBOX */}
@@ -115,10 +127,7 @@ export const CommonPlatformFields = InputComponent((rawProps: IProps) => {
label={$t('Title')}
required={true}
max={maxCharacters}
tooltip={
enabledPlatforms.includes('tiktok') &&
$t('Only 32 characters of your title will display on TikTok')
}
tooltip={titleTooltip}
/>

{/*DESCRIPTION*/}
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@
align-items: center;
justify-content: center;
height: 100%;
margin: 0px 20px;
}

// make timeline icons and text bigger
Original file line number Diff line number Diff line change
@@ -1,65 +1,36 @@
import React from 'react';
import { $t } from 'services/i18n';
import { CommonPlatformFields } from '../CommonPlatformFields';
import Form from '../../../shared/inputs/Form';
import { createBinding } from '../../../shared/inputs';
import { IPlatformComponentParams } from './PlatformSettingsLayout';
import { clipboard } from 'electron';
import { TextInput } from 'components-react/shared/inputs';
import { Alert, Button } from 'antd';
import { createBinding, InputComponent } from '../../../shared/inputs';
import PlatformSettingsLayout, { IPlatformComponentParams } from './PlatformSettingsLayout';
import { IKickStartStreamOptions } from '../../../../services/platforms/kick';

/**
* Note: The implementation for this component is a light refactor of the InstagramEditStreamInfo component.
/***
* Stream Settings for Kick
*/
export const KickEditStreamInfo = InputComponent((p: IPlatformComponentParams<'kick'>) => {
function updateSettings(patch: Partial<IKickStartStreamOptions>) {
p.onChange({ ...kickSettings, ...patch });
}

type Props = IPlatformComponentParams<'kick'> & {
isStreamSettingsWindow?: boolean;
};

export function KickEditStreamInfo(p: Props) {
const bind = createBinding(p.value, updatedSettings =>
p.onChange({ ...p.value, ...updatedSettings }),
);

const { isStreamSettingsWindow } = p;
const streamKeyLabel = $t(isStreamSettingsWindow ? 'Stream Key' : 'Kick Stream Key');
const streamUrlLabel = $t(isStreamSettingsWindow ? 'Stream URL' : 'Kick Stream URL');
const kickSettings = p.value;
const bind = createBinding(kickSettings, newKickSettings => updateSettings(newKickSettings));

return (
<Form name="kick-settings">
<TextInput
{...bind.streamUrl}
required
label={streamUrlLabel}
addonAfter={<PasteButton onPaste={bind.streamUrl.onChange} />}
/>

<TextInput
{...bind.streamKey}
required
label={streamKeyLabel}
isPassword
placeholder={$t('Remember to update your Stream Key')}
addonAfter={<PasteButton onPaste={bind.streamKey.onChange} />}
<PlatformSettingsLayout
layoutMode={p.layoutMode}
commonFields={
<CommonPlatformFields
key="common"
platform="kick"
layoutMode={p.layoutMode}
value={kickSettings}
onChange={updateSettings}
/>
}
requiredFields={<div key={'empty-kick'} />}
/>
{!isStreamSettingsWindow && (
<Alert
style={{ marginBottom: 8 }}
message={$t(
'Remember to open Kick in browser and enter your Stream URL and Key to start streaming!',
)}
type="warning"
showIcon
closable
/>
)}
</Form>
);
}

function PasteButton({ onPaste }: { onPaste: (text: string) => void }) {
return (
<Button title={$t('Paste')} onClick={() => onPaste(clipboard.readText())}>
<i className="fa fa-paste" />
</Button>
);
}
});
Loading