migrate components stickers to eslint

This commit is contained in:
Chris Svenningsen 2020-09-14 15:14:03 -07:00 committed by Josh Perez
parent 2ade4acd52
commit 5364de90a4
15 changed files with 225 additions and 203 deletions

View file

@ -31,8 +31,6 @@ webpack.config.ts
# Temporarily ignored during TSLint transition # Temporarily ignored during TSLint transition
# JIRA: DESKTOP-304 # JIRA: DESKTOP-304
ts/*.ts
ts/components/stickers/**
ts/shims/** ts/shims/**
ts/sql/** ts/sql/**
ts/storybook/** ts/storybook/**

View file

@ -1892,6 +1892,26 @@
"message": "Why use words when you can use stickers?", "message": "Why use words when you can use stickers?",
"description": "Shown as the body on a tooltip when the user upgrades to a version of Signal supporting stickers." "description": "Shown as the body on a tooltip when the user upgrades to a version of Signal supporting stickers."
}, },
"stickers--StickerPicker--Open": {
"message": "Open the sticker picker",
"description": "Label for the open button for the sticker picker"
},
"stickers--StickerPicker--AddPack": {
"message": "Add a sticker pack",
"description": "Label for the add pack button in the sticker picker"
},
"stickers--StickerPicker--NextPage": {
"message": "Next Page",
"description": "Label for the next page button in the sticker picker"
},
"stickers--StickerPicker--PrevPage": {
"message": "Previous Page",
"description": "Label for the previous page button in the sticker picker"
},
"stickers--StickerPicker--Recents": {
"message": "Recent Sticker",
"description": "Label for the recent stickers button in the sticker picker"
},
"stickers--StickerPicker--DownloadError": { "stickers--StickerPicker--DownloadError": {
"message": "Some stickers could not be downloaded.", "message": "Some stickers could not be downloaded.",
"description": "Shown in the sticker picker when one or more stickers could not be downloaded." "description": "Shown in the sticker picker when one or more stickers could not be downloaded."

View file

@ -3,12 +3,8 @@ import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions'; import { action } from '@storybook/addon-actions';
import { boolean } from '@storybook/addon-knobs'; import { boolean } from '@storybook/addon-knobs';
// @ts-ignore
import { setup as setupI18n } from '../../../js/modules/i18n'; import { setup as setupI18n } from '../../../js/modules/i18n';
// @ts-ignore
import enMessages from '../../../_locales/en/messages.json'; import enMessages from '../../../_locales/en/messages.json';
import { Props, StickerButton } from './StickerButton'; import { Props, StickerButton } from './StickerButton';
import { import {
createPack, createPack,

View file

@ -29,7 +29,6 @@ export type OwnProps = {
export type Props = OwnProps; export type Props = OwnProps;
export const StickerButton = React.memo( export const StickerButton = React.memo(
// tslint:disable-next-line max-func-body-length
({ ({
i18n, i18n,
clearInstalledStickerPack, clearInstalledStickerPack,
@ -67,8 +66,9 @@ export const StickerButton = React.memo(
} }
}, [ }, [
clearInstalledStickerPack, clearInstalledStickerPack,
onClickAddPack, clearShowIntroduction,
installedPacks, installedPacks,
onClickAddPack,
popperRoot, popperRoot,
setOpen, setOpen,
]); ]);
@ -161,7 +161,6 @@ export const StickerButton = React.memo(
// Clear the installed pack after one minute // Clear the installed pack after one minute
React.useEffect(() => { React.useEffect(() => {
if (installedPack) { if (installedPack) {
// tslint:disable-next-line:no-string-based-set-timeout
const timerId = setTimeout(clearInstalledStickerPack, 10 * 1000); const timerId = setTimeout(clearInstalledStickerPack, 10 * 1000);
return () => { return () => {
@ -188,12 +187,14 @@ export const StickerButton = React.memo(
<Reference> <Reference>
{({ ref }) => ( {({ ref }) => (
<button <button
type="button"
ref={ref} ref={ref}
onClick={handleClickButton} onClick={handleClickButton}
className={classNames({ className={classNames({
'module-sticker-button__button': true, 'module-sticker-button__button': true,
'module-sticker-button__button--active': open, 'module-sticker-button__button--active': open,
})} })}
aria-label={i18n('stickers--StickerPicker--Open')}
/> />
)} )}
</Reference> </Reference>
@ -201,6 +202,7 @@ export const StickerButton = React.memo(
<Popper placement={position} key={installedPack.id}> <Popper placement={position} key={installedPack.id}>
{({ ref, style, placement, arrowProps }) => ( {({ ref, style, placement, arrowProps }) => (
<button <button
type="button"
ref={ref} ref={ref}
style={style} style={style}
className="module-sticker-button__tooltip" className="module-sticker-button__tooltip"
@ -237,6 +239,7 @@ export const StickerButton = React.memo(
<Popper placement={position}> <Popper placement={position}>
{({ ref, style, placement, arrowProps }) => ( {({ ref, style, placement, arrowProps }) => (
<button <button
type="button"
ref={ref} ref={ref}
style={style} style={style}
className={classNames( className={classNames(
@ -260,8 +263,10 @@ export const StickerButton = React.memo(
</div> </div>
<div className="module-sticker-button__tooltip--introduction__close"> <div className="module-sticker-button__tooltip--introduction__close">
<button <button
type="button"
className="module-sticker-button__tooltip--introduction__close__button" className="module-sticker-button__tooltip--introduction__close__button"
onClick={handleClearIntroduction} onClick={handleClearIntroduction}
aria-label={i18n('close')}
/> />
</div> </div>
<div <div

View file

@ -2,12 +2,8 @@ import * as React from 'react';
import { storiesOf } from '@storybook/react'; import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions'; import { action } from '@storybook/addon-actions';
// @ts-ignore
import { setup as setupI18n } from '../../../js/modules/i18n'; import { setup as setupI18n } from '../../../js/modules/i18n';
// @ts-ignore
import enMessages from '../../../_locales/en/messages.json'; import enMessages from '../../../_locales/en/messages.json';
import { Props, StickerManager } from './StickerManager'; import { Props, StickerManager } from './StickerManager';
import { createPack, sticker1, sticker2 } from './StickerPicker.stories'; import { createPack, sticker1, sticker2 } from './StickerPicker.stories';

View file

@ -19,7 +19,6 @@ export type OwnProps = {
export type Props = OwnProps; export type Props = OwnProps;
export const StickerManager = React.memo( export const StickerManager = React.memo(
// tslint:disable-next-line max-func-body-length
({ ({
installedPacks, installedPacks,
receivedPacks, receivedPacks,
@ -51,18 +50,17 @@ export const StickerManager = React.memo(
focusRef.current.focus(); focusRef.current.focus();
} }
}); });
// We only want to attempt downloads on initial load
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []); }, []);
const clearPackToPreview = React.useCallback(() => { const clearPackToPreview = React.useCallback(() => {
setPackToPreview(null); setPackToPreview(null);
}, [setPackToPreview]); }, [setPackToPreview]);
const previewPack = React.useCallback( const previewPack = React.useCallback((pack: StickerPackType) => {
(pack: StickerPackType) => { setPackToPreview(pack);
setPackToPreview(pack); }, []);
},
[clearPackToPreview]
);
return ( return (
<> <>
@ -98,7 +96,7 @@ export const StickerManager = React.memo(
}, },
].map(section => { ].map(section => {
if (section.hideIfEmpty && section.packs.length === 0) { if (section.hideIfEmpty && section.packs.length === 0) {
return; return null;
} }
return ( return (

View file

@ -15,7 +15,6 @@ export type OwnProps = {
export type Props = OwnProps; export type Props = OwnProps;
export const StickerManagerPackRow = React.memo( export const StickerManagerPackRow = React.memo(
// tslint:disable-next-line max-func-body-length
({ ({
installStickerPack, installStickerPack,
uninstallStickerPack, uninstallStickerPack,
@ -37,7 +36,7 @@ export const StickerManagerPackRow = React.memo(
installStickerPack(id, key); installStickerPack(id, key);
} }
}, },
[installStickerPack, pack] [id, installStickerPack, key]
); );
const handleUninstall = React.useCallback( const handleUninstall = React.useCallback(
@ -49,7 +48,7 @@ export const StickerManagerPackRow = React.memo(
setUninstalling(true); setUninstalling(true);
} }
}, },
[setUninstalling, id, key, isBlessed] [id, isBlessed, key, setUninstalling, uninstallStickerPack]
); );
const handleConfirmUninstall = React.useCallback(() => { const handleConfirmUninstall = React.useCallback(() => {
@ -57,7 +56,7 @@ export const StickerManagerPackRow = React.memo(
if (uninstallStickerPack) { if (uninstallStickerPack) {
uninstallStickerPack(id, key); uninstallStickerPack(id, key);
} }
}, [id, key, clearUninstalling]); }, [id, key, clearUninstalling, uninstallStickerPack]);
const handleKeyDown = React.useCallback( const handleKeyDown = React.useCallback(
(event: React.KeyboardEvent) => { (event: React.KeyboardEvent) => {
@ -134,7 +133,7 @@ export const StickerManagerPackRow = React.memo(
<div className="module-sticker-manager__pack-row__controls"> <div className="module-sticker-manager__pack-row__controls">
{pack.status === 'installed' ? ( {pack.status === 'installed' ? (
<StickerPackInstallButton <StickerPackInstallButton
installed={true} installed
i18n={i18n} i18n={i18n}
onClick={handleUninstall} onClick={handleUninstall}
/> />

View file

@ -15,11 +15,13 @@ export const StickerPackInstallButton = React.forwardRef<
Props Props
>(({ i18n, installed, blue, ...props }: Props, ref) => ( >(({ i18n, installed, blue, ...props }: Props, ref) => (
<button <button
type="button"
ref={ref} ref={ref}
className={classNames({ className={classNames({
'module-sticker-manager__install-button': true, 'module-sticker-manager__install-button': true,
'module-sticker-manager__install-button--blue': blue, 'module-sticker-manager__install-button--blue': blue,
})} })}
aria-label={i18n('stickers--StickerManager--Install')}
{...props} {...props}
> >
{installed {installed

View file

@ -4,12 +4,8 @@ import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions'; import { action } from '@storybook/addon-actions';
import { boolean } from '@storybook/addon-knobs'; import { boolean } from '@storybook/addon-knobs';
// @ts-ignore
import { setup as setupI18n } from '../../../js/modules/i18n'; import { setup as setupI18n } from '../../../js/modules/i18n';
// @ts-ignore
import enMessages from '../../../_locales/en/messages.json'; import enMessages from '../../../_locales/en/messages.json';
import { Props, StickerPicker } from './StickerPicker'; import { Props, StickerPicker } from './StickerPicker';
import { StickerPackType, StickerType } from '../../state/ducks/stickers'; import { StickerPackType, StickerType } from '../../state/ducks/stickers';

View file

@ -1,5 +1,3 @@
/* tslint:disable:max-func-body-length */
/* tslint:disable:cyclomatic-complexity */
import * as React from 'react'; import * as React from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import { useRestoreFocus } from '../../util/hooks'; import { useRestoreFocus } from '../../util/hooks';
@ -25,7 +23,7 @@ function useTabs<T>(tabs: ReadonlyArray<T>, initialTab = tabs[0]) {
tabs.map(t => () => { tabs.map(t => () => {
setTab(t); setTab(t);
}), }),
tabs [tabs]
); );
return [tab, handlers] as [T, ReadonlyArray<() => void>]; return [tab, handlers] as [T, ReadonlyArray<() => void>];
@ -72,11 +70,13 @@ export const StickerPicker = React.memo(
const focusRef = React.useRef<HTMLButtonElement>(null); const focusRef = React.useRef<HTMLButtonElement>(null);
const tabIds = React.useMemo( const tabIds = React.useMemo(
() => ['recents', ...packs.map(({ id }) => id)], () => ['recents', ...packs.map(({ id }) => id)],
packs [packs]
); );
const [currentTab, [recentsHandler, ...packsHandlers]] = useTabs( const [currentTab, [recentsHandler, ...packsHandlers]] = useTabs(
tabIds, tabIds,
// If there are no recent stickers, default to the first sticker pack, unless there are no sticker packs. // If there are no recent stickers,
// default to the first sticker pack,
// unless there are no sticker packs.
tabIds[recentStickers.length > 0 ? 0 : Math.min(1, tabIds.length)] tabIds[recentStickers.length > 0 ? 0 : Math.min(1, tabIds.length)]
); );
const selectedPack = packs.find(({ id }) => id === currentTab); const selectedPack = packs.find(({ id }) => id === currentTab);
@ -110,8 +110,6 @@ export const StickerPicker = React.memo(
event.preventDefault(); event.preventDefault();
onClose(); onClose();
return;
} }
}; };
@ -160,6 +158,7 @@ export const StickerPicker = React.memo(
> >
{hasPacks ? ( {hasPacks ? (
<button <button
type="button"
onClick={recentsHandler} onClick={recentsHandler}
className={classNames({ className={classNames({
'module-sticker-picker__header__button': true, 'module-sticker-picker__header__button': true,
@ -167,10 +166,12 @@ export const StickerPicker = React.memo(
'module-sticker-picker__header__button--selected': 'module-sticker-picker__header__button--selected':
currentTab === 'recents', currentTab === 'recents',
})} })}
aria-label={i18n('stickers--StickerPicker--Recents')}
/> />
) : null} ) : null}
{packs.map((pack, i) => ( {packs.map((pack, i) => (
<button <button
type="button"
key={pack.id} key={pack.id}
onClick={packsHandlers[i]} onClick={packsHandlers[i]}
className={classNames( className={classNames(
@ -198,24 +199,29 @@ export const StickerPicker = React.memo(
</div> </div>
{!isUsingKeyboard && packsPage > 0 ? ( {!isUsingKeyboard && packsPage > 0 ? (
<button <button
type="button"
className={classNames( className={classNames(
'module-sticker-picker__header__button', 'module-sticker-picker__header__button',
'module-sticker-picker__header__button--prev-page' 'module-sticker-picker__header__button--prev-page'
)} )}
onClick={onClickPrevPackPage} onClick={onClickPrevPackPage}
aria-label={i18n('stickers--StickerPicker--PrevPage')}
/> />
) : null} ) : null}
{!isUsingKeyboard && !isLastPacksPage(packsPage, packs.length) ? ( {!isUsingKeyboard && !isLastPacksPage(packsPage, packs.length) ? (
<button <button
type="button"
className={classNames( className={classNames(
'module-sticker-picker__header__button', 'module-sticker-picker__header__button',
'module-sticker-picker__header__button--next-page' 'module-sticker-picker__header__button--next-page'
)} )}
onClick={onClickNextPackPage} onClick={onClickNextPackPage}
aria-label={i18n('stickers--StickerPicker--NextPage')}
/> />
) : null} ) : null}
</div> </div>
<button <button
type="button"
ref={addPackRef} ref={addPackRef}
className={classNames( className={classNames(
'module-sticker-picker__header__button', 'module-sticker-picker__header__button',
@ -225,6 +231,7 @@ export const StickerPicker = React.memo(
} }
)} )}
onClick={onClickAddPack} onClick={onClickAddPack}
aria-label={i18n('stickers--StickerPicker--AddPack')}
/> />
</div> </div>
<div <div
@ -290,6 +297,7 @@ export const StickerPicker = React.memo(
return ( return (
<button <button
type="button"
ref={maybeFocusRef} ref={maybeFocusRef}
key={`${packId}-${id}`} key={`${packId}-${id}`}
className="module-sticker-picker__body__cell" className="module-sticker-picker__body__cell"
@ -307,6 +315,7 @@ export const StickerPicker = React.memo(
.fill(0) .fill(0)
.map((_, i) => ( .map((_, i) => (
<div <div
// eslint-disable-next-line react/no-array-index-key
key={i} key={i}
className="module-sticker-picker__body__cell__placeholder" className="module-sticker-picker__body__cell__placeholder"
role="presentation" role="presentation"

View file

@ -1,8 +1,10 @@
import * as React from 'react'; import * as React from 'react';
import { storiesOf } from '@storybook/react';
import { text } from '@storybook/addon-knobs';
import { action } from '@storybook/addon-actions';
import { StickerPreviewModal } from './StickerPreviewModal'; import { StickerPreviewModal } from './StickerPreviewModal';
// @ts-ignore
import { setup as setupI18n } from '../../../js/modules/i18n'; import { setup as setupI18n } from '../../../js/modules/i18n';
// @ts-ignore
import enMessages from '../../../_locales/en/messages.json'; import enMessages from '../../../_locales/en/messages.json';
import { import {
landscapeGreenUrl, landscapeGreenUrl,
@ -10,10 +12,6 @@ import {
squareStickerUrl, squareStickerUrl,
} from '../../storybook/Fixtures'; } from '../../storybook/Fixtures';
import { storiesOf } from '@storybook/react';
import { text } from '@storybook/addon-knobs';
import { action } from '@storybook/addon-actions';
const i18n = setupI18n('en', enMessages); const i18n = setupI18n('en', enMessages);
storiesOf('Components/Stickers/StickerPreviewModal', module).add('Full', () => { storiesOf('Components/Stickers/StickerPreviewModal', module).add('Full', () => {
@ -46,7 +44,7 @@ storiesOf('Components/Stickers/StickerPreviewModal', module).add('Full', () => {
title, title,
isBlessed: true, isBlessed: true,
author, author,
status: 'downloaded' as 'downloaded', status: 'downloaded' as const,
stickerCount: 101, stickerCount: 101,
stickers: [ stickers: [
wideSticker, wideSticker,

View file

@ -64,171 +64,175 @@ function renderBody({ pack, i18n }: Props) {
); );
} }
export const StickerPreviewModal = React.memo( export const StickerPreviewModal = React.memo((props: Props) => {
// tslint:disable-next-line max-func-body-length const {
(props: Props) => { onClose,
const { pack,
onClose, i18n,
pack, downloadStickerPack,
i18n, installStickerPack,
downloadStickerPack, uninstallStickerPack,
installStickerPack, } = props;
uninstallStickerPack, const focusRef = React.useRef<HTMLButtonElement>(null);
} = props; const [root, setRoot] = React.useState<HTMLElement | null>(null);
const focusRef = React.useRef<HTMLButtonElement>(null); const [confirmingUninstall, setConfirmingUninstall] = React.useState(false);
const [root, setRoot] = React.useState<HTMLElement | null>(null);
const [confirmingUninstall, setConfirmingUninstall] = React.useState(false);
// Restore focus on teardown // Restore focus on teardown
useRestoreFocus(focusRef, root); useRestoreFocus(focusRef, root);
React.useEffect(() => { React.useEffect(() => {
const div = document.createElement('div'); const div = document.createElement('div');
document.body.appendChild(div); document.body.appendChild(div);
setRoot(div); setRoot(div);
return () => { return () => {
document.body.removeChild(div); document.body.removeChild(div);
}; };
}, []); }, []);
React.useEffect(() => { React.useEffect(() => {
if (pack && pack.status === 'known') { if (pack && pack.status === 'known') {
downloadStickerPack(pack.id, pack.key); downloadStickerPack(pack.id, pack.key);
} }
if ( if (
pack && pack &&
pack.status === 'error' && pack.status === 'error' &&
(pack.attemptedStatus === 'downloaded' || (pack.attemptedStatus === 'downloaded' ||
pack.attemptedStatus === 'installed') pack.attemptedStatus === 'installed')
) { ) {
downloadStickerPack(pack.id, pack.key, { downloadStickerPack(pack.id, pack.key, {
finalStatus: pack.attemptedStatus, finalStatus: pack.attemptedStatus,
}); });
} }
}, []); // We only want to attempt downloads on initial load
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const isInstalled = Boolean(pack && pack.status === 'installed'); const isInstalled = Boolean(pack && pack.status === 'installed');
const handleToggleInstall = React.useCallback(() => { const handleToggleInstall = React.useCallback(() => {
if (!pack) { if (!pack) {
return; return;
} }
if (isInstalled) { if (isInstalled) {
setConfirmingUninstall(true); setConfirmingUninstall(true);
} else if (pack.status === 'ephemeral') { } else if (pack.status === 'ephemeral') {
downloadStickerPack(pack.id, pack.key, { finalStatus: 'installed' }); downloadStickerPack(pack.id, pack.key, { finalStatus: 'installed' });
onClose(); onClose();
} else { } else {
installStickerPack(pack.id, pack.key); installStickerPack(pack.id, pack.key);
onClose();
}
}, [
downloadStickerPack,
installStickerPack,
isInstalled,
onClose,
pack,
setConfirmingUninstall,
]);
const handleUninstall = React.useCallback(() => {
if (!pack) {
return;
}
uninstallStickerPack(pack.id, pack.key);
setConfirmingUninstall(false);
// onClose is called by the confirmation modal
}, [uninstallStickerPack, setConfirmingUninstall, pack]);
React.useEffect(() => {
const handler = ({ key }: KeyboardEvent) => {
if (key === 'Escape') {
onClose(); onClose();
} }
}, [ };
isInstalled,
pack,
setConfirmingUninstall,
installStickerPack,
onClose,
]);
const handleUninstall = React.useCallback(() => { document.addEventListener('keydown', handler);
if (!pack) {
return; return () => {
document.removeEventListener('keydown', handler);
};
}, [onClose]);
const handleClickToClose = React.useCallback(
(e: React.MouseEvent) => {
if (e.target === e.currentTarget) {
onClose();
} }
uninstallStickerPack(pack.id, pack.key); },
setConfirmingUninstall(false); [onClose]
// onClose is called by the confirmation modal );
}, [uninstallStickerPack, setConfirmingUninstall, pack]);
React.useEffect(() => { return root
const handler = ({ key }: KeyboardEvent) => { ? createPortal(
if (key === 'Escape') { // Not really a button. Just a background which can be clicked to close modal
onClose(); // eslint-disable-next-line max-len
} // eslint-disable-next-line jsx-a11y/interactive-supports-focus, jsx-a11y/click-events-have-key-events
}; <div
role="button"
document.addEventListener('keydown', handler); className="module-sticker-manager__preview-modal__overlay"
onClick={handleClickToClose}
return () => { >
document.removeEventListener('keydown', handler); {confirmingUninstall ? (
}; <ConfirmationDialog
}, [onClose]); i18n={i18n}
onClose={onClose}
const handleClickToClose = React.useCallback( actions={[
(e: React.MouseEvent) => { {
if (e.target === e.currentTarget) { style: 'negative',
onClose(); text: i18n('stickers--StickerManager--Uninstall'),
} action: handleUninstall,
}, },
[onClose] ]}
); >
{i18n('stickers--StickerManager--UninstallWarning')}
return root </ConfirmationDialog>
? createPortal( ) : (
<div <div className="module-sticker-manager__preview-modal__container">
// Not really a button. Just a background which can be clicked to close modal <header className="module-sticker-manager__preview-modal__container__header">
role="button" <h2 className="module-sticker-manager__preview-modal__container__header__text">
className="module-sticker-manager__preview-modal__overlay" {i18n('stickers--StickerPreview--Title')}
onClick={handleClickToClose} </h2>
> <button
{confirmingUninstall ? ( type="button"
<ConfirmationDialog onClick={onClose}
i18n={i18n} className="module-sticker-manager__preview-modal__container__header__close-button"
onClose={onClose} aria-label={i18n('close')}
actions={[ />
{ </header>
style: 'negative', {renderBody(props)}
text: i18n('stickers--StickerManager--Uninstall'), {pack && pack.status !== 'error' ? (
action: handleUninstall, <div className="module-sticker-manager__preview-modal__container__meta-overlay">
}, <div className="module-sticker-manager__preview-modal__container__meta-overlay__info">
]} <h3 className="module-sticker-manager__preview-modal__container__meta-overlay__info__title">
> {pack.title}
{i18n('stickers--StickerManager--UninstallWarning')} {pack.isBlessed ? (
</ConfirmationDialog> <span className="module-sticker-manager__preview-modal__container__meta-overlay__info__blessed-icon" />
) : ( ) : null}
<div className="module-sticker-manager__preview-modal__container"> </h3>
<header className="module-sticker-manager__preview-modal__container__header"> <h4 className="module-sticker-manager__preview-modal__container__meta-overlay__info__author">
<h2 className="module-sticker-manager__preview-modal__container__header__text"> {pack.author}
{i18n('stickers--StickerPreview--Title')} </h4>
</h2>
<button
onClick={onClose}
className="module-sticker-manager__preview-modal__container__header__close-button"
/>
</header>
{renderBody(props)}
{pack && pack.status !== 'error' ? (
<div className="module-sticker-manager__preview-modal__container__meta-overlay">
<div className="module-sticker-manager__preview-modal__container__meta-overlay__info">
<h3 className="module-sticker-manager__preview-modal__container__meta-overlay__info__title">
{pack.title}
{pack.isBlessed ? (
<span className="module-sticker-manager__preview-modal__container__meta-overlay__info__blessed-icon" />
) : null}
</h3>
<h4 className="module-sticker-manager__preview-modal__container__meta-overlay__info__author">
{pack.author}
</h4>
</div>
<div className="module-sticker-manager__preview-modal__container__meta-overlay__install">
{pack.status === 'pending' ? (
<Spinner svgSize="small" size="14px" />
) : (
<StickerPackInstallButton
ref={focusRef}
installed={isInstalled}
i18n={i18n}
onClick={handleToggleInstall}
blue={true}
/>
)}
</div>
</div> </div>
) : null} <div className="module-sticker-manager__preview-modal__container__meta-overlay__install">
</div> {pack.status === 'pending' ? (
)} <Spinner svgSize="small" size="14px" />
</div>, ) : (
root <StickerPackInstallButton
) ref={focusRef}
: null; installed={isInstalled}
} i18n={i18n}
); onClick={handleToggleInstall}
blue
/>
)}
</div>
</div>
) : null}
</div>
)}
</div>,
root
)
: null;
});

View file

@ -7,7 +7,7 @@ export function countStickers(o: {
blessedPacks: ReadonlyArray<StickerPackType>; blessedPacks: ReadonlyArray<StickerPackType>;
installedPacks: ReadonlyArray<StickerPackType>; installedPacks: ReadonlyArray<StickerPackType>;
receivedPacks: ReadonlyArray<StickerPackType>; receivedPacks: ReadonlyArray<StickerPackType>;
}) { }): number {
return ( return (
o.knownPacks.length + o.knownPacks.length +
o.blessedPacks.length + o.blessedPacks.length +

View file

@ -13126,7 +13126,7 @@
"rule": "React-createRef", "rule": "React-createRef",
"path": "ts/components/stickers/StickerManager.js", "path": "ts/components/stickers/StickerManager.js",
"line": " const focusRef = React.createRef();", "line": " const focusRef = React.createRef();",
"lineNumber": 20, "lineNumber": 18,
"reasonCategory": "usageTrusted", "reasonCategory": "usageTrusted",
"updated": "2019-11-21T06:13:49.384Z", "updated": "2019-11-21T06:13:49.384Z",
"reasonDetail": "Used for setting focus only" "reasonDetail": "Used for setting focus only"

View file

@ -185,6 +185,7 @@
"ts/components/*.ts[x]", "ts/components/*.ts[x]",
"ts/components/conversation/**", "ts/components/conversation/**",
"ts/components/emoji/**", "ts/components/emoji/**",
"ts/components/stickers/**",
"ts/notifications/**", "ts/notifications/**",
"ts/protobuf/**", "ts/protobuf/**",
"ts/scripts/**", "ts/scripts/**",