Skip to content

Commit

Permalink
Merge branch 'master' into staging
Browse files Browse the repository at this point in the history
  • Loading branch information
SLOBS-Release committed Dec 16, 2024
2 parents 9362237 + ca4130d commit 2254d5b
Show file tree
Hide file tree
Showing 7 changed files with 145 additions and 79 deletions.
34 changes: 34 additions & 0 deletions app/components-react/windows/go-live/DestinationSwitchers.m.less
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
@import '../../../styles/index.less';
@import '../../../styles/mixins.less';

.destination-logo {
font-size: 38px;
Expand Down Expand Up @@ -74,3 +75,36 @@
.column-padding {
padding: 0px 15px;
}

.tiktok-modal-logo {
display: inline-block;
width: 18px;
height: 18px;
margin-right: 5px;
vertical-align: super;
}

.tiktok-modal {
&:global(.ant-modal-confirm .ant-modal-body) {
padding: 0px;
}

:global(div.ant-modal-content) {
box-shadow: none;
}

:global(.ant-modal-confirm-body .ant-modal-confirm-title) {
display: inline-block;
font-size: 19px;
line-height: unset;
}

:global(.ant-modal-confirm-btns) {
display: none;
}
}

.tiktok-modal-footer {
display: flex;
justify-content: flex-end;
}
81 changes: 60 additions & 21 deletions app/components-react/windows/go-live/DestinationSwitchers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,18 @@ import React, { useRef, MouseEvent } from 'react';
import { getPlatformService, TPlatform } from '../../../services/platforms';
import cx from 'classnames';
import { $t } from '../../../services/i18n';
import * as remote from '@electron/remote';
import styles from './DestinationSwitchers.m.less';
import { ICustomStreamDestination } from '../../../services/settings/streaming';
import { Services } from '../../service-provider';
import { SwitchInput } from '../../shared/inputs';
import PlatformLogo from '../../shared/PlatformLogo';
import { assertIsDefined } from '../../../util/properties-type-guards';
import { useDebounce } from '../../hooks';
import { useGoLiveSettings } from './useGoLiveSettings';
import { alertAsync } from '../../modals';
import { ModalLayout } from 'components-react/shared/ModalLayout';
import { Button, Form, Modal } from 'antd';
import Translate from 'components-react/shared/Translate';

/**
* Allows enabling/disabling platforms and custom destinations for the stream
Expand Down Expand Up @@ -188,9 +191,11 @@ const DestinationSwitcher = React.forwardRef<{}, IDestinationSwitcherProps>((p,
const switchInputRef = useRef<HTMLInputElement>(null);
const containerRef = useRef<HTMLDivElement>(null);
const platform = typeof p.destination === 'string' ? (p.destination as TPlatform) : null;
const { RestreamService, MagicLinkService, StreamingService } = Services;
const { RestreamService, TikTokService, StreamingService } = Services;
const canEnableRestream = RestreamService.views.canEnableRestream;
const cannotDisableDestination = p.isPrimary && !canEnableRestream;
const showTikTokModal =
p.promptConnectTikTok || (platform === 'tiktok' && TikTokService.missingLiveAccess);

// Preserving old TikTok functionality, so they can't enable the toggle if TikTok is not
// connected.
Expand All @@ -199,25 +204,8 @@ const DestinationSwitcher = React.forwardRef<{}, IDestinationSwitcherProps>((p,
platform === 'tiktok' && !StreamingService.views.isPlatformLinked('tiktok');

function onClickHandler(ev: MouseEvent) {
if (p.promptConnectTikTok) {
alertAsync({
type: 'confirm',
title: $t('Connect TikTok Account'),
closable: true,
content: (
<span>
{$t(
'Connect your TikTok account to stream to TikTok and one additional platform for free.',
)}
</span>
),
okText: $t('Connect'),
onOk: () => {
Services.NavigationService.actions.navigate('PlatformMerge', { platform: 'tiktok' });
Services.WindowsService.actions.closeChildWindow();
},
});
return;
if (showTikTokModal) {
renderTikTokModal(p.promptConnectTikTok);
}

// If we're disabling the switch we shouldn't be emitting anything past below
Expand Down Expand Up @@ -332,3 +320,54 @@ const DestinationSwitcher = React.forwardRef<{}, IDestinationSwitcherProps>((p,
</div>
);
});

export function renderTikTokModal(promptConnectTikTok?: boolean) {
const { TikTokService } = Services;

const message = promptConnectTikTok
? $t('Connect your TikTok account to stream to TikTok and one additional platform for free.')
: $t(
"Connect your TikTok account to stream to TikTok and one other platform for free. Haven't applied to stream on TikTok Live yet? <link>Start the process here</link>.",
{ link: <a href={TikTokService.applicationUrl} /> },
);

function openApplicationInfoPage() {
remote.shell.openExternal(Services.TikTokService.applicationUrl);
}

alertAsync({
bodyStyle: { padding: '24px' },
className: styles.tiktokModal,
type: 'confirm',
title: $t('Connect your TikTok Account'),
content: (
<Translate message={message}>
<a slot="link" onClick={openApplicationInfoPage} style={{ textDecoration: 'underline' }} />
</Translate>
),
icon: <PlatformLogo platform="tiktok" className={styles.tiktokModalLogo} />,
closable: true,
maskClosable: true,
cancelButtonProps: { style: { display: 'none' } },
okButtonProps: { style: { display: 'none' } },
modalRender: node => <ModalLayout footer={<TikTokModalFooter />}>{node}</ModalLayout>,
width: 600,
});
}

function TikTokModalFooter() {
function connect() {
Modal.destroyAll();
Services.NavigationService.actions.navigate('PlatformMerge', { platform: 'tiktok' });
Services.WindowsService.actions.closeChildWindow();
}

return (
<Form layout={'inline'} className={styles.tiktokModalFooter}>
<Button onClick={Modal.destroyAll}>{$t('Skip')}</Button>
<Button type="primary" onClick={connect}>
{$t('Connect TikTok Account')}
</Button>
</Form>
);
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useRef, useCallback } from 'react';
import React, { useRef, useCallback, useMemo } from 'react';
import { getPlatformService, TPlatform } from 'services/platforms';
import cx from 'classnames';
import { $t } from 'services/i18n';
Expand All @@ -14,6 +14,7 @@ import Translate from 'components-react/shared/Translate';
import DualOutputPlatformSelector from './DualOutputPlatformSelector';
import { useDebounce } from 'components-react/hooks';
import DualOutputToggle from '../../../shared/DualOutputToggle';
import { renderTikTokModal } from '../DestinationSwitchers';

interface INonUltraDestinationSwitchers {
showSelector?: boolean;
Expand All @@ -35,6 +36,11 @@ export function NonUltraDestinationSwitchers(p: INonUltraDestinationSwitchers) {
const destinationSwitcherRef = useRef({ addClass: () => undefined });
const promptConnectTikTok = !isPlatformLinked('tiktok');

const platforms = useMemo(
() => (promptConnectTikTok ? enabledPlatforms.concat('tiktok') : enabledPlatforms),
[enabledPlatforms, promptConnectTikTok],
);

const emitSwitch = useDebounce(500, () => {
switchPlatforms(enabledPlatformsRef.current);
});
Expand Down Expand Up @@ -69,7 +75,7 @@ export function NonUltraDestinationSwitchers(p: INonUltraDestinationSwitchers) {
style={{ marginBottom: '15px' }}
/>
)}
{enabledPlatforms.map((platform: TPlatform, index: number) => (
{platforms.map((platform: TPlatform, index: number) => (
<DestinationSwitcher
key={platform}
destination={platform}
Expand Down Expand Up @@ -138,7 +144,10 @@ const DestinationSwitcher = React.forwardRef<{ addClass: () => void }, IDestinat
};
});
const containerRef = useRef<HTMLDivElement>(null);
const { TikTokService } = Services;
const platform = typeof p.destination === 'string' ? (p.destination as TPlatform) : null;
const showTikTokModal =
p.promptConnectTikTok || (platform === 'tiktok' && TikTokService.missingLiveAccess);

function addClass() {
containerRef.current?.classList.remove(styles.platformDisabled);
Expand All @@ -158,26 +167,6 @@ const DestinationSwitcher = React.forwardRef<{ addClass: () => void }, IDestinat
containerRef.current?.classList.add(styles.platformDisabled);
}

function showTikTokConnectModal() {
alertAsync({
type: 'confirm',
title: $t('Connect TikTok Account'),
closable: true,
content: (
<span>
{$t(
'Connect your TikTok account to stream to TikTok and one additional platform for free.',
)}
</span>
),
okText: $t('Connect'),
onOk: () => {
Services.NavigationService.actions.navigate('PlatformMerge', { platform: 'tiktok' });
Services.WindowsService.actions.closeChildWindow();
},
});
}

const { title, description, CloseIcon, Logo } = (() => {
if (platform) {
const { UserService } = Services;
Expand Down Expand Up @@ -220,15 +209,18 @@ const DestinationSwitcher = React.forwardRef<{ addClass: () => void }, IDestinat
}
})();
return (
<div data-test="non-ultra-switcher" className={styles.platformSwitcher}>
<div
data-test="non-ultra-switcher"
className={cx(styles.platformSwitcher, {
[styles.platformDisabled]: !p.enabled || p.promptConnectTikTok,
})}
>
<div
ref={containerRef}
className={cx(styles.switcherHeader, {
[styles.platformDisabled]: !p.enabled || p.promptConnectTikTok,
})}
className={styles.switcherHeader}
onClick={() => {
if (p.promptConnectTikTok) {
showTikTokConnectModal();
if (showTikTokModal) {
renderTikTokModal(p.promptConnectTikTok);
}
}}
>
Expand All @@ -241,7 +233,7 @@ const DestinationSwitcher = React.forwardRef<{ addClass: () => void }, IDestinat
<span className={styles.platformUsername}>{description}</span>
</div>
{/* CLOSE */}
{!p.isPrimary && <CloseIcon />}
{(!p.isPrimary || !p.promptConnectTikTok) && <CloseIcon />}
</div>
</div>
<div className={styles.platformDisplay}>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useRef, MouseEvent, useCallback } from 'react';
import React, { useRef, MouseEvent, useCallback, useMemo } from 'react';
import { getPlatformService, TPlatform } from 'services/platforms';
import cx from 'classnames';
import { $t } from 'services/i18n';
Expand All @@ -14,6 +14,7 @@ import { alertAsync } from 'components-react/modals';
import Translate from 'components-react/shared/Translate';
import { useDebounce } from 'components-react/hooks';
import DualOutputToggle from '../../../shared/DualOutputToggle';
import { renderTikTokModal } from '../DestinationSwitchers';

interface IUltraDestinationSwitchers {
type?: 'default' | 'ultra';
Expand All @@ -38,6 +39,11 @@ export function UltraDestinationSwitchers(p: IUltraDestinationSwitchers) {
enabledPlatformsRef.current = enabledPlatforms;
const promptConnectTikTok = !isPlatformLinked('tiktok');

const platforms = useMemo(
() => (promptConnectTikTok ? linkedPlatforms.concat('tiktok') : linkedPlatforms),
[linkedPlatforms, promptConnectTikTok],
);

const emitSwitch = useDebounce(500, () => {
switchPlatforms(enabledPlatformsRef.current);
});
Expand Down Expand Up @@ -77,7 +83,7 @@ export function UltraDestinationSwitchers(p: IUltraDestinationSwitchers) {
style={{ marginBottom: '15px' }}
/>
)}
{linkedPlatforms.map((platform: TPlatform, index: number) => (
{platforms.map((platform: TPlatform, index: number) => (
<DestinationSwitcher
key={platform}
destination={platform}
Expand Down Expand Up @@ -120,28 +126,10 @@ function DestinationSwitcher(p: IDestinationSwitcherProps) {
const containerRef = useRef<HTMLDivElement>(null);
const platform = typeof p.destination === 'string' ? (p.destination as TPlatform) : null;
const enable = !p.enabled ?? (p.promptConnectTikTok && p.promptConnectTikTok === true);
const { RestreamService, MagicLinkService } = Services;
const { RestreamService, MagicLinkService, TikTokService } = Services;
const canDisablePrimary = p.canDisablePrimary;

function showTikTokConnectModal() {
alertAsync({
type: 'confirm',
title: $t('Connect TikTok Account'),
closable: true,
content: (
<span>
{$t(
'Connect your TikTok account to stream to TikTok and one additional platform for free.',
)}
</span>
),
okText: $t('Connect'),
onOk: () => {
Services.NavigationService.actions.navigate('PlatformMerge', { platform: 'tiktok' });
Services.WindowsService.actions.closeChildWindow();
},
});
}
const showTikTokModal =
p.promptConnectTikTok || (platform === 'tiktok' && TikTokService.missingLiveAccess);

function onClickHandler(ev: MouseEvent) {
// TODO: do we need this check if we're on an Ultra DestinationSwitcher
Expand Down Expand Up @@ -229,10 +217,12 @@ function DestinationSwitcher(p: IDestinationSwitcherProps) {
<div
ref={containerRef}
data-test="ultra-switcher"
className={cx(styles.platformSwitcher, { [styles.platformDisabled]: !p.enabled })}
className={cx(styles.platformSwitcher, {
[styles.platformDisabled]: !p.enabled || p.promptConnectTikTok,
})}
onClick={() => {
if (p.promptConnectTikTok) {
showTikTokConnectModal();
if (showTikTokModal) {
renderTikTokModal(p.promptConnectTikTok);
}
}}
>
Expand All @@ -249,8 +239,8 @@ function DestinationSwitcher(p: IDestinationSwitcherProps) {
{/* SWITCH */}
<div
onClick={e => {
if (p.promptConnectTikTok) {
showTikTokConnectModal();
if (showTikTokModal) {
renderTikTokModal(p.promptConnectTikTok);
e.stopPropagation();
return;
} else {
Expand Down
4 changes: 3 additions & 1 deletion app/i18n/en-US/tiktok.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,7 @@
"You may be eligible for TikTok Live Access. <apply>Apply here.</apply>": "You may be eligible for TikTok Live Access. <apply>Apply here.</apply>",
"Click to view TikTok Replay in your browser.": "Click to view TikTok Replay in your browser.",
"TikTok Stream Error": "TikTok Stream Error",
"Couldn't confirm TikTok Live Access. Apply for Live Permissions below": "Couldn't confirm TikTok Live Access. Apply for Live Permissions below"
"Couldn't confirm TikTok Live Access. Apply for Live Permissions below": "Couldn't confirm TikTok Live Access. Apply for Live Permissions below",
"Connect your TikTok account": "Connect your TikTok account",
"Connect your TikTok account to stream to TikTok and one other platform for free. Haven't applied to stream on TikTok Live yet? <link>Start the process here</link>.": "Connect your TikTok account to stream to TikTok and one other platform for free. Haven't applied to stream on TikTok Live yet? <link>Start the process here</link>."
}
5 changes: 5 additions & 0 deletions app/services/platforms/tiktok.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,11 @@ export class TikTokService
return ['approved', 'legacy'].includes(scope);
}

get missingLiveAccess(): boolean {
const scope = this.state.settings?.liveScope ?? 'never-applied';
return ['legacy', 'never-applied'].includes(scope);
}

get approved(): boolean {
return this.state.settings.liveScope === 'approved';
}
Expand Down
Loading

0 comments on commit 2254d5b

Please sign in to comment.