migrate components stickers to eslint
This commit is contained in:
parent
2ade4acd52
commit
5364de90a4
15 changed files with 225 additions and 203 deletions
|
@ -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/**
|
||||||
|
|
|
@ -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."
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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';
|
||||||
|
|
||||||
|
|
|
@ -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 (
|
||||||
|
|
|
@ -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}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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';
|
||||||
|
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
|
});
|
||||||
|
|
|
@ -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 +
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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/**",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue